user367640
user367640

Reputation: 37

Verilog - Issue with Main Module for Adder

I am trying to write the code which models an input register with 8 bits that outputs the sum of the input data. The model also contains a clock, enable and reset pin.

I started this problem by first making a 1-bit and 8-bit adder as seen below. (Should be noted that I am not concerned with the carry out pin for the MSB).

module adder_1bit(A,B,Cin,S,Cout);

input A,B,Cin;
output  Cout,S;
wire   W1, W2, W3;
assign W1 = A ^ B;
assign W2 = Cin & W1;
assign W3 = A & B;
assign S = Cin ^ W1;
assign Cout = W2 | W3;

endmodule

module adder_8bit(Din,Sum);
input [7:0] Din;
output [7:0] Sum;
wire [7:0] C;

adder_1bit M1(Din[0],Din[0],1'b0,Sum[0],C[0]);
adder_1bit M2(Din[1],Din[1],C[0],Sum[1],C[1]);
adder_1bit M3(Din[2],Din[2],C[1],Sum[2],C[2]);
adder_1bit M4(Din[3],Din[3],C[2],Sum[3],C[3]);
adder_1bit M5(Din[4],Din[4],C[3],Sum[4],C[4]);
adder_1bit M6(Din[5],Din[5],C[4],Sum[5],C[5]);
adder_1bit M7(Din[6],Din[6],C[5],Sum[6],C[6]);
adder_1bit M8(Din[7],Din[7],C[6],Sum[7],C[7]);

endmodule

I then made a testbench and everything was working fine. My main issue is incorporating these modules with my clk, enable, and rst code. This is was I currently have. When my reset pin is high, my output is 0. I also have to check if the MSB is negative to make sure I convert it to a positive value (part of my problem).

module Main(Data_in,Start,rst,clk,Sum_Abs);

input rst, clk, Start;
input [7:0] Data_in;
output  [7:0] Sum_Abs;
reg [7:0] Sum_Abs;
reg [7:0] Data_in_buffer;

adder_8bit M9(Data_in_buffer,Sum_abs);

always @(posedge clk)
begin
    if(rst == 1'b1)
        begin
            Sum_Abs = 8'b00000000;      
        end 
    else if(Start == 1'b1)
        begin
            case(Data_in)
            8'b1xxxxxxx: Data_in_buffer = ~Data_in + 1'b1;
            8'b0xxxxxxx: Data_in_buffer = Data_in;
            endcase     
        end 
end
endmodule

This is where my issue arises. When I create the testbench as seen below, my output for the sum is always 'x'. My problem has to be from the Main module, since my previous tests I was not having this issue. I am relatively new to verilog, and any tips or help would be grateful, thanks!

module Main_tb;

integer k;
reg signed [7:0] Din_tb;
reg str, rst_tb, clk_tb;
wire signed [7:0] Sum_tb; 

Main DUT(Din_tb,str,rst_tb,clk_tb,Sum_tb);

initial begin
$display("\tData,\tOutput");
$monitor("\t%d,\t%d",Din_tb,Sum_tb); 
Din_tb = 8'b00000001;
clk_tb = 0;
str = 1'b1;
rst_tb = 1'b0;

#5 clk_tb = 1;
#5 Din_tb = 8'b00000010;
#5 clk_tb = 0;
#5 Din_tb = 8'b00000100;
#5 clk_tb = 1;
#5 Din_tb = 8'b00001000;
#5 clk_tb = 0;
#5 Din_tb = 8'b00100000;
#5 clk_tb = 1;

end

endmodule 

Upvotes: 1

Views: 543

Answers (1)

Oldfart
Oldfart

Reputation: 6259

You have errors in several places:

In the module Main Sum_Abs is driven from two places. By the reset and it comes out of the M9 module. You can't do that. Think of HDL as hardware: you have just connected two output ports together both driving the same wires.
Just make it:

if(rst == 1'b1)
   Data_in_buffer <= 8'b00000000;      

Then you make a spelling error in Main:

output  [7:0] Sum_Abs;
//                ^Upper case!
adder_8bit M9(Data_in_buffer,Sum_abs);
//                               ^ Lower case

The next error is understandable and it is here:

case(Data_in)
8'b1xxxxxxx: Data_in_buffer = ~Data_in + 1'b1;
8'b0xxxxxxx: Data_in_buffer = Data_in;
endcase     

You are assuming that the LS 7 bits are ignored. But the case statement is really looking for the literal value 8'b1xxxxxxx thus with the x-es.
You can use:

casez(Data_in)
8'b1zzzzzzz: Data_in_buffer <= ~Data_in + 1'b1;
8'b0zzzzzzz: Data_in_buffer <= Data_in;
endcase     

But much simpler is to look at the MS bit:

if (Data_in[7]=1'b1)
  ....

Forth error is that you use blocking assignments in a clocked section. If you have paid attention you will see that I have replaced all your = with <= in the new code.

Fifth error is in your test-bench: you do not change the clock fast enough. The code only looks at the rising edge and you change the input at the rising and falling edges. That is not the best way to make a clock. What if you need to simulate a million clocks?

This is how you make a clock:

initial
begin
   clk_tb= 1'b0;
   forever
      #50 clk_tb= ~clk_tb; // clock period of 100 time units
end

After all that something comes out but I have not checked if the right values come out. I leave that to you.

Upvotes: 2

Related Questions