LouWill
LouWill

Reputation: 57

How to Check Values in a Module vs the Values in Another Module in Verilog

I have this assignment where I am supposed to design an 8 bit 1's complement subtractor that doesn't use word-level operators like + or -.

I think that it is working (tested it manually on other values), but the last part of the assignment is to have the testbench iterate all the possible values and add them together (256*256 or 65,536 possible values) (not all the numbers added cumulatively to produce a very large number, but 0+1, 0+2, ... 1+1, 1+2, etc.) and check the calculated values with my other module and print the number of values that match the subtractor correctly and the number of values that are incorrect.

The last line of code should look like this:

$display("All cases tested; %d correct, %d failed", correct, failed);

I am not sure what is wrong. This is the error I am now receiving:

/home/kaos/IVER/5f5bd2824865.v:105: error: subtractionresult is not a valid l-value in testbench.
/home/kaos/IVER/5f5bd2824865.v:88:      : subtractionresult is declared here as wire.
/home/kaos/IVER/5f5bd2824865.v:106: error: Unable to bind wire/reg/memory `refonesub.subtractionresult' in `testbench'
/home/kaos/IVER/5f5bd2824865.v:106: error: Unable to elaborate condition expression.
3 error(s) during elaboration.

Here is what I have:

module refonesub (
  output [7:0] subtractionresult ,
  output carryoverflow ,

  input    [7:0] A ,
  input    [7:0] B ,
  input mode 
  );

wire B0; 
wire B1; 
wire B2; 
wire B3; 
wire B4; 
wire B5; 
wire B6; 
wire B7; 

wire C0; 
wire C1; 
wire C2; 
wire C3;
wire C4; 
wire C5; 
wire C6; 
wire C7;  

xor(B0, B[0], mode);
xor(B1, B[1], mode);
xor(B2, B[2], mode);
xor(B3, B[3], mode);
xor(B4, B[4], mode);
xor(B5, B[5], mode);
xor(B6, B[6], mode);
xor(B7, B[7], mode);


onesub U0(A[0],B0,mode,C0,subtractionresult[0]);
onesub U1(A[1],B1,C0,C1,subtractionresult[1]);
onesub U2(A[2],B2,C1,C2,subtractionresult[2]);
onesub U3(A[3],B3,C2,C3,subtractionresult[3]);
onesub U4(A[4],B4,C3,C4,subtractionresult[4]);
onesub U5(A[5],B5,C4,C5,subtractionresult[5]);
onesub U6(A[6],B6,C5,C6,subtractionresult[6]);
onesub U7(A[7],B7,C6,C7,subtractionresult[7]);  

xor (carryoverflow,C6,C7);                

endmodule


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

output Cout ;
output  S ;           


input A ;
wire A ;
input B ;
wire B ;
input Cin ;
wire Cin ;    

reg Cout;
reg S;

always @(A or B or Cin) begin
    case ({A,B,Cin})
     0: begin Cout=0; S=0; end
     1: begin Cout=0; S=1; end
     2: begin Cout=0; S=1; end      
     3: begin Cout=1; S=0; end
     4: begin Cout=0; S=1; end
     5: begin Cout=1; S=0; end
     6: begin Cout=1; S=0; end
     7: begin Cout=1; S=1; end
    endcase
    end
endmodule


module testbench;
  
  reg [7:0] A;
  reg [7:0] B;
  reg       mode;
  wire [7:0] subtractionresult;
  wire carryoverflow;
  
  refonesub sub( 
    .A(A),
    .B(B),
    .mode(mode),
    .subtractionresult(subtractionresult),
    .carryoverflow(carryoverflow) );
  
 integer i, j;
    initial begin
        // Note that ++ operator does not exist in Verilog !
        for (A = 0; i < 256; A = A + 1) 
                begin
                for (B = 0; B < 256; B = B + 1) 
                begin
                subtractionresult = A+B;
                if (refonesub.subtractionresult == testbench.subtractionresult) begin
                i = i + 1;
                end
                else begin
                j = j + 1;
                end
                end
                end
                
   $display("All cases tested; %d correct, %d failed", i, j);
  end
endmodule

Upvotes: 2

Views: 371

Answers (1)

toolic
toolic

Reputation: 62096

Since subtractionresult is already a module output, there is no need to scope down into the module. Instead, create a testbench signal for the comparison: subtractionresult_expect. Since you are making a procedural assignment to it, it must be a reg:

module testbench;
   
   reg [7:0] A;
   reg [7:0] B;
   reg       mode;
   wire [7:0] subtractionresult;
   reg  [7:0] subtractionresult_expect;
   wire      carryoverflow;
   
   refonesub sub( 
                  .A(A),
                  .B(B),
                  .mode(mode),
                  .subtractionresult(subtractionresult),
                  .carryoverflow(carryoverflow) );

   
    integer    i, j;
    initial begin
        for (A = 0; i < 256; A = A + 1) begin
            for (B = 0; B < 256; B = B + 1) begin
                subtractionresult_expect = A+B;
                if (subtractionresult == subtractionresult_expect) begin
                    i = i + 1;
                end else begin
                    j = j + 1;
                end
            end
        end
        $display("All cases tested; %d correct, %d failed", i, j);
   end

endmodule

The code in the original Question had another problem...

A $display statement must be inside a procedural block, such as an initial block. I think you meant to have it as the last line of your initial block:

initial begin
    for (A = 0; i < 256; A = A + 1) begin
        for (B = 0; B < 256; B = B + 1) begin
            subtractionresult = A+B;
            if (refonesub.subtractionresult == testbench.subtractionresult) begin
                i = i + 1;
            end else begin
                j = j + 1;
            end
        end
    end
    $display("All cases tested; %d correct, %d failed", i, j);
end

I used emacs to automatically indent your code to make it a little easier to read.

Upvotes: 1

Related Questions