下一阶段的Systemverilog递归更新值
我试图在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;
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