Verilog中的算术方程除以带时钟的电平,收到"Latch warnings"请指教
Arithmetic Equation in Verilog divided by levels with clocks, receiving "Latch warnings" please advices
更新:我正在编辑这个问题以将方程式更改为更简单的方程式,尽管问题大致相同,但这次不同的是,我实际上可以让它给出正确答案计算,但我一直遇到 "latches" 的问题。(我的原始方程式也工作正常,但同样的警告闩锁问题)。
我想一步一步做一个简单的方程式,如下所示:
c = 50 / (|a - 2|^2 + |b - 5|^2)
数据是无符号二进制32位值,减法结果也是无符号(绝对值),我想做的是使用时钟分几步执行,
|a - 2| , // First this subtraction
|b - 5| AND |a - 2|^2, // then a subtraction and a square of before
|a - 2|^2 + |b - 5|^2 // then the another square plus the before square
c = 50 / |a - 2|^2 + |b - 5|^2 /// finally a division of 50
我期望的是综合工具在整个过程中只生成 1 个减法、1 个平方和 1 个除法,在这个简化版本中,这种情况只发生在平方和减法中,因为只有 1 个除法手术。第一个问题:我真的在做我想做的事吗? Quartus II 是否生成 "datapath"? hardware/energy 真的被拯救了吗?
我是 verilog 和数字设计的新手,正在自学,如果我的概念有误,请指正。
我把除法、减法和平方模块分别创建了,因为我打算稍后实现它们,而不是依赖于/、-、*运算符。原因是因为我可能会猜测,通过编写更高效的算法(例如,作者可以在互联网上获得),我可以替代 Quartus II 的运算符推断算法。但我还是不确定。
这个程序运行正确,输出是预期的,但是,我从 Quartus-II 收到很多这样的警告
警告 (10240):Verilog HDL 始终在 FCM_EQ.v(88) 构造警告:推断变量 "SU_in_a" 的锁存器,它通过总是构造
警告 (13012):闩锁 SQ_in_a[18] 存在不安全行为
警告 (13013):锁存器上的端口 D 和 ENA 由相同的信号状态馈送。S2
我几乎不知道锁存器是什么,我读到一个必须避免锁存器,寄存器是否在不同的时钟中保持其值?整个程序就是关于这个的,所以我不确定我将如何解决这个问题。有什么建议或替代解决方案吗?
顶层模块是这样的:
module FCM_EQ (a, b, c, clk, enable, rst_n, all_finish, OBS);
input [31:0] a, b;
input clk, enable, rst_n;
output [31:0] c;
output [63:0] OBS;
output all_finish;
reg [31:0] SU_in_a, SU_in_b;
wire [31:0] SU_out_r;
reg [31:0] SQ_in_a;
wire [63:0] SQ_out_r;
reg [63:0] DIV_in_b;
reg [63:0] DIV_in_a;
wire [63:0] DIV_out_r;
reg [31:00] botA, botB, c;
reg [63:00] SQ_botA, SQ_botB, N_C;
reg [63:0] den_total;
reg all_finish;
reg [4:0] state, nextstate;
reg [63:0] OBS;
parameter FIFTY = 64'b0000000000000000_0000000000110010_0000000000000000_0000000000000000;
parameter FIVE = 32'b0000000000000101_0000000000000000;
parameter TWO = 32'b0000000000000010_0000000000000000;
parameter reset = 0;
parameter S0 = 1;
parameter S1 = 2;
parameter S2 = 3;
parameter S3 = 4;
SUB_VAL SU_inst1(.a (SU_in_a),.b (SU_in_b),.r (SU_out_r) );
SQ_VAL SQ_inst1 (.a (SQ_in_a),.r (SQ_out_r) );
DIV_VAL DIV_inst1 (.a (DIV_in_a),.b (DIV_in_b),.r (DIV_out_r) );
always @ (posedge clk or negedge rst_n)
if (~rst_n)
state <= reset ;
else
state <= nextstate;
always @*
begin
case (state)
reset:
begin
if (enable == 1)
nextstate = S0;
else
nextstate = reset;
end
S0:
begin
SU_in_a = a;
SU_in_b = TWO;
botA = SU_out_r;
nextstate = S1;
end
S1:
begin
SU_in_a = b;
SU_in_b = FIVE;
botB = SU_out_r;
SQ_in_a = botA;
SQ_botA = SQ_out_r;
nextstate = S2;
end
S2:
begin
SQ_in_a = botB;
SQ_botB = SQ_out_r; // SQ_botB is 64 bits (32_32)
den_total = SQ_botA + SQ_botB;
den_total = den_total >> 24;
nextstate = S3;
end
S3:
begin
DIV_in_a = FIFTY;
DIV_in_b = den_total;
N_C = DIV_out_r;
OBS = N_C;
c = N_C [31:0]; // Extract 32 bits en total (16_24)
all_finish = 1;
nextstate = reset;
end
default:
begin
nextstate = reset;
end
endcase
end
endmodule
OBS 寄存器只是我在 Modelsim 中检查寄存器值的新手方法,因为我忽略了是否有更好的方法来监视它。
可以在此处查看测试台和完整代码
不是完整答案只是快速观察:
always @ (posedge clk)
state <= nextstate; //Use Non blocking
always @* // Auto sensitivity list
begin
case (state)
我还建议您重置状态:
always @ (posedge clk or negedge rst_n)
if (~rst_n)
state <= 'b0 ;
else
state <= nextstate; //Non blocking
更新:我正在编辑这个问题以将方程式更改为更简单的方程式,尽管问题大致相同,但这次不同的是,我实际上可以让它给出正确答案计算,但我一直遇到 "latches" 的问题。(我的原始方程式也工作正常,但同样的警告闩锁问题)。
我想一步一步做一个简单的方程式,如下所示:
c = 50 / (|a - 2|^2 + |b - 5|^2)
数据是无符号二进制32位值,减法结果也是无符号(绝对值),我想做的是使用时钟分几步执行,
|a - 2| , // First this subtraction
|b - 5| AND |a - 2|^2, // then a subtraction and a square of before
|a - 2|^2 + |b - 5|^2 // then the another square plus the before square
c = 50 / |a - 2|^2 + |b - 5|^2 /// finally a division of 50
我期望的是综合工具在整个过程中只生成 1 个减法、1 个平方和 1 个除法,在这个简化版本中,这种情况只发生在平方和减法中,因为只有 1 个除法手术。第一个问题:我真的在做我想做的事吗? Quartus II 是否生成 "datapath"? hardware/energy 真的被拯救了吗?
我是 verilog 和数字设计的新手,正在自学,如果我的概念有误,请指正。
我把除法、减法和平方模块分别创建了,因为我打算稍后实现它们,而不是依赖于/、-、*运算符。原因是因为我可能会猜测,通过编写更高效的算法(例如,作者可以在互联网上获得),我可以替代 Quartus II 的运算符推断算法。但我还是不确定。
这个程序运行正确,输出是预期的,但是,我从 Quartus-II 收到很多这样的警告
警告 (10240):Verilog HDL 始终在 FCM_EQ.v(88) 构造警告:推断变量 "SU_in_a" 的锁存器,它通过总是构造
警告 (13012):闩锁 SQ_in_a[18] 存在不安全行为 警告 (13013):锁存器上的端口 D 和 ENA 由相同的信号状态馈送。S2
我几乎不知道锁存器是什么,我读到一个必须避免锁存器,寄存器是否在不同的时钟中保持其值?整个程序就是关于这个的,所以我不确定我将如何解决这个问题。有什么建议或替代解决方案吗?
顶层模块是这样的:
module FCM_EQ (a, b, c, clk, enable, rst_n, all_finish, OBS);
input [31:0] a, b;
input clk, enable, rst_n;
output [31:0] c;
output [63:0] OBS;
output all_finish;
reg [31:0] SU_in_a, SU_in_b;
wire [31:0] SU_out_r;
reg [31:0] SQ_in_a;
wire [63:0] SQ_out_r;
reg [63:0] DIV_in_b;
reg [63:0] DIV_in_a;
wire [63:0] DIV_out_r;
reg [31:00] botA, botB, c;
reg [63:00] SQ_botA, SQ_botB, N_C;
reg [63:0] den_total;
reg all_finish;
reg [4:0] state, nextstate;
reg [63:0] OBS;
parameter FIFTY = 64'b0000000000000000_0000000000110010_0000000000000000_0000000000000000;
parameter FIVE = 32'b0000000000000101_0000000000000000;
parameter TWO = 32'b0000000000000010_0000000000000000;
parameter reset = 0;
parameter S0 = 1;
parameter S1 = 2;
parameter S2 = 3;
parameter S3 = 4;
SUB_VAL SU_inst1(.a (SU_in_a),.b (SU_in_b),.r (SU_out_r) );
SQ_VAL SQ_inst1 (.a (SQ_in_a),.r (SQ_out_r) );
DIV_VAL DIV_inst1 (.a (DIV_in_a),.b (DIV_in_b),.r (DIV_out_r) );
always @ (posedge clk or negedge rst_n)
if (~rst_n)
state <= reset ;
else
state <= nextstate;
always @*
begin
case (state)
reset:
begin
if (enable == 1)
nextstate = S0;
else
nextstate = reset;
end
S0:
begin
SU_in_a = a;
SU_in_b = TWO;
botA = SU_out_r;
nextstate = S1;
end
S1:
begin
SU_in_a = b;
SU_in_b = FIVE;
botB = SU_out_r;
SQ_in_a = botA;
SQ_botA = SQ_out_r;
nextstate = S2;
end
S2:
begin
SQ_in_a = botB;
SQ_botB = SQ_out_r; // SQ_botB is 64 bits (32_32)
den_total = SQ_botA + SQ_botB;
den_total = den_total >> 24;
nextstate = S3;
end
S3:
begin
DIV_in_a = FIFTY;
DIV_in_b = den_total;
N_C = DIV_out_r;
OBS = N_C;
c = N_C [31:0]; // Extract 32 bits en total (16_24)
all_finish = 1;
nextstate = reset;
end
default:
begin
nextstate = reset;
end
endcase
end
endmodule
OBS 寄存器只是我在 Modelsim 中检查寄存器值的新手方法,因为我忽略了是否有更好的方法来监视它。
可以在此处查看测试台和完整代码
不是完整答案只是快速观察:
always @ (posedge clk)
state <= nextstate; //Use Non blocking
always @* // Auto sensitivity list
begin
case (state)
我还建议您重置状态:
always @ (posedge clk or negedge rst_n)
if (~rst_n)
state <= 'b0 ;
else
state <= nextstate; //Non blocking