下一阶段的Systemverilog递归更新值

下一阶段的Systemverilog递归更新值,verilog,system-verilog,hdl,Verilog,System Verilog,Hdl,我试图在Systemverilog中创建一个递归逻辑,但似乎缺少将一个迭代的输出传递到下一个迭代的正确逻辑 以下是问题的一个示例: parameter WIDTH=4; module test_ckt #(parameter WIDTH = 4)(CK, K, Z); input CK; input [WIDTH-1:0] K; output reg Z; wire [WIDTH/2-1:0] tt; wire [WIDTH-1:0] tempin; assign tempin = K;

我试图在Systemverilog中创建一个递归逻辑,但似乎缺少将一个迭代的输出传递到下一个迭代的正确逻辑

以下是问题的一个示例:

parameter WIDTH=4;
module test_ckt #(parameter WIDTH = 4)(CK, K, Z);

input CK;
input [WIDTH-1:0] K;
output reg Z;

wire [WIDTH/2-1:0] tt;
wire [WIDTH-1:0] tempin;
assign tempin  = K;
genvar i,j;
generate
    for (j=$clog2(WIDTH); j>0; j=j-1)
    begin: outer
        wire [(2**(j-1))-1:0] tt;
        for (i=(2**j)-1; i>0; i=i-2)
        begin
            glitchy_ckt #(.WIDTH(1)) gckt (tempin[i:i], tempin[(i-1):i-1], tt[((i+1)/2)-1]);
        end
        // How do I save the value for the next iteration?
        wire [(2**(j-1))-1:0] tempin;
        assign outer[j].tempin = outer[j].tt;
    end
endgenerate

always @(posedge CK)
begin
    // How do I use the final output here?
    Z <= tt[0];
end

endmodule

module glitchy_ckt #(parameter WIDTH = 1)(A1, B1, Z1);
input [WIDTH-1:0] A1,B1;
output Z1;
assign Z1 = ~A1[0] ^ B1[0];
endmodule

如何确保
tempin
tt
在我从一个阶段进入下一个阶段时得到更新。

您的代码中没有任何递归。您试图使用循环解决它,但生成块是非常有限的构造,例如,您无法访问在其他生成迭代中定义的参数(但可以访问变量或模块实例)

因此,我们的想法是使用模块的真正递归实例化。在下面的实现中,
rec
模块是递归实例化的模块。它实际上是根据您的示例构建层次结构(我希望是正确的)。 因为您将其标记为system verilog,所以我使用了system verilog语法

module rec#(WIDTH=1) (input logic [WIDTH-1:0]source, output logic result);
   
   if (WIDTH <= 2) begin
     always_comb
       result = source; // << generating the result and exiting recursion.
   end
   else begin:blk
      localparam REC_WDT = WIDTH / 2;
      logic [REC_WDT-1:0] newSource; 
   
      always_comb // << calculation of your expression
        for (int i = 0; i < REC_WDT; i++)
          newSource[i] = source[i*2] ^ ~source[(i*2)+1]; 
   
      rec #(REC_WDT) rec(newSource, result); // << recursive instantiation with WIDTH/2
   end // else: !if(WIDTH <= 2)

   initial $display("%m: W=%0d", WIDTH);  // just my testing leftover
endmodule
还有你的测试台,有点变化:

module mytb;

   reg CK;
   reg [WIDTH-1:0] A;
   wire        Z;

   test_ckt #(.WIDTH(WIDTH)) dut(.CK(CK), .K(A), .Z(Z));

   always #200 CK = ~CK;
   integer     i;
   initial begin
      $display($time, "Starting simulation");
      CK = 0;
      A = 4'b1010;
      #500 
      A = 4'b1000;
      #500 $finish;
   end

   initial begin
      $monitor("Z=%b", Z);     
   end
endmodule // mytb
对于这样的小示例,使用$display/$monitor比转储跟踪更方便


我没有对我创建的东西做太多测试,所以可能会有问题,但无论如何,你都可以从中获得基本的想法。我假设它可以使用2的幂的任何宽度。

您应该能够从上一次迭代中访问tempin和tt作为
outerp[j-1]。tempin
。确保你的代码是可编译的,并提供你的测试平台。我可以使用第二次迭代中的outerp,但是我如何初始化它?您不监视测试台中的任何东西。您的输出来自何处?我正在向VCD写入以查看波形。您在S1和S2的输出中显示了哪些变量?谢谢@serge此解决方案可以创建正确的逻辑!
`timescale 1 ps / 1 ps
`include "test_ckt.v"

module mytb;

reg CK;
reg [WIDTH-1:0] A;
wire Z;

test_ckt #(.WIDTH(WIDTH)) dut(.CK(CK), .K(A), .Z(Z));

always #200 CK = ~CK;
integer i;
initial begin
    $display($time, "Starting simulation");
    #0 CK = 0;
    A = 4'b1010;
    #500 $finish;
end

initial begin
    //dump waveform
    $dumpfile("test_ckt.vcd");
    $dumpvars(0,dut);
end

endmodule
module rec#(WIDTH=1) (input logic [WIDTH-1:0]source, output logic result);
   
   if (WIDTH <= 2) begin
     always_comb
       result = source; // << generating the result and exiting recursion.
   end
   else begin:blk
      localparam REC_WDT = WIDTH / 2;
      logic [REC_WDT-1:0] newSource; 
   
      always_comb // << calculation of your expression
        for (int i = 0; i < REC_WDT; i++)
          newSource[i] = source[i*2] ^ ~source[(i*2)+1]; 
   
      rec #(REC_WDT) rec(newSource, result); // << recursive instantiation with WIDTH/2
   end // else: !if(WIDTH <= 2)

   initial $display("%m: W=%0d", WIDTH);  // just my testing leftover
endmodule
module test_ckt #(parameter WIDTH = 4)(input logic CK, input logic [WIDTH-1:0] K, output logic Z);
   logic                 result;
   rec#(WIDTH) rec(K, result); // instantiate first time )(top)
   always_ff @(posedge CK)
     Z <= result;  // assign the results  
endmodule // test_ckt
module mytb;

   reg CK;
   reg [WIDTH-1:0] A;
   wire        Z;

   test_ckt #(.WIDTH(WIDTH)) dut(.CK(CK), .K(A), .Z(Z));

   always #200 CK = ~CK;
   integer     i;
   initial begin
      $display($time, "Starting simulation");
      CK = 0;
      A = 4'b1010;
      #500 
      A = 4'b1000;
      #500 $finish;
   end

   initial begin
      $monitor("Z=%b", Z);     
   end
endmodule // mytb