Как проверить значения в модуле по сравнению со значениями в другом модуле в Verilog

#verilog

#verilog

Вопрос:

У меня есть это задание, в котором я должен разработать 8-битный вычитатель дополнения 1, который не использует операторы уровня слов, такие как или -.

Я думаю, что это работает (проверено вручную на других значениях), но последняя часть задания заключается в том, чтобы тестовый стенд перебрал все возможные значения и сложил их вместе (256 * 256 или 65 536 возможных значений) (не все числа добавляются кумулятивно, чтобы получить очень большое число, но 0 1, 0 2, … 1 1, 1 2, и т.д.) и проверьте вычисленные значения с помощью моего другого модуля и выведите количество значений, которые правильно соответствуют вычитателю, и количество значений, которые неверны.

Последняя строка кода должна выглядеть следующим образом:

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

Я не уверен, что не так. Это ошибка, которую я сейчас получаю:

 /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.
  

Вот что у меня есть:

 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] subtractionresu<
  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
  

Ответ №1:

Поскольку subtractionresult это уже вывод модуля, нет необходимости расширять область действия в модуле. Вместо этого создайте тестовый сигнал для сравнения: subtractionresult_expect . Поскольку вы выполняете для него процедурное присвоение, оно должно быть reg :

 module testbench;
   
   reg [7:0] A;
   reg [7:0] B;
   reg       mode;
   wire [7:0] subtractionresu<
   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
  

В коде исходного вопроса была другая проблема…

$display Оператор должен находиться внутри процедурного блока, такого как initial блок. Я думаю, вы хотели, чтобы это было последней строкой вашего initial блока:

 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
  

Я использовал emacs для автоматического отступа вашего кода, чтобы его было немного легче читать.