如何解决系统Verilog循环
我目前正在研究系统Verilog中的Shift-Add算法(32x32位乘法)。根据GTKwave,系统Verilog无法找到任何错误,我的代码正在正常工作。当我用yosys综合电路时,将添加锁存器。这就是问题所在。我不希望闩锁在我的电路中。这是我的代码:
module multiplier(
input logic clk_i,input logic rst_i,input logic start_i,input logic [31:0] a_i,input logic [31:0] b_i,output logic finished_o,output logic [63:0] result_o
);
typedef enum logic [1:0] { STATE_A,STATE_B} state_t;
state_t state_p,state_n;
logic [63:0] fin_res;
logic [63:0] tmp;
logic rst_flag;
integer i;
always @(posedge clk_i or posedge rst_i) begin
if (rst_i == 1'b1) begin
state_p <= STATE_B;
end
else begin
state_p <= state_n;
end
end
always @(*)begin
state_n = state_p;
case (state_p)
STATE_A: if (start_i == 0) state_n = STATE_B;
STATE_B: if (start_i == 1) state_n = STATE_A;
default: state_n = state_p;
endcase
end
always @(*) begin
case (state_p)
STATE_A: begin
rst_flag = 1;
fin_res = 0;
finished_o = 0;
tmp = 0;
for (i = 0; i < 32; i = i + 1) begin
if (a_i[i] == 1'b1) begin
tmp = b_i;
tmp = tmp << i;
fin_res = fin_res + tmp;
end
end
end
STATE_B: begin
result_o = fin_res;
if (rst_flag == 1) finished_o = 1;
if (start_i == 1) finished_o = 0;
end
default: begin
finished_o = 0;
result_o = 0;
end
endcase
end
endmodule
仅花了2天的调试时间,没有发现任何错误,我想问一下您是否可以帮助我。我正在分配每个输出(至少我认为是这样)。那我的错误在哪里?是for循环吗?但是,这有什么问题呢?预先感谢您的帮助:)
一些有关代码段的有用信息:start_i是启动信号。如果将其设置为1,则应开始乘法。 finish_o是完成标志。如果将其设置为1,cpu将知道计算已完成。 a_i和b_i是应该相乘的输入。 result_o是乘法的结果,当finish_o设置为1时可以读取。
根据yosys,我得到以下闩锁:
64 DLATCH_N
64 DLATCH_P
我认为for循环中的fin_res可能出了一些问题,原因是逻辑变量与锁存器一样正好是64位长
解决方法
从注释中可以看到一堆未在第二个case语句中分配的变量,这些变量导致综合生成锁存器。为了避免这种情况,您需要递归地分配case语句和条件语句的所有分支中的所有var。
但是,如果可以为它们分配默认值,则可以使用类似于第二个Always块中的模式的模式,只需在'case'语句之前分配默认值。这样,您甚至不需要 default 子句,就可以在第二个always块中将其删除。
always @(*) begin
// set default values
rst_flag = 0;
fin_res = 0;
finished_o = 0;
tmp = 0;
result_o = 0;
case (state_p)
STATE_A: begin
rst_flag = 1;
for (i = 0; i < 32; i = i + 1) begin
if (a_i[i] == 1'b1) begin
tmp = b_i;
tmp = tmp << i;
fin_res = fin_res + tmp;
end
end
end
STATE_B: begin
result_o = fin_res;
// are you sure that you do not need a latch here?
if (rst_flag == 1) finished_o = 1;
if (start_i == 1) finished_o = 0;
end
// you do not need 'default' here.
endcase
end
我的修复将导致组合行为,并且应该摆脱综合中的闩锁,但是看起来它们不会像您期望的那样运行。看来您确实在这里需要闩锁。
-
rst_flag 必须是闩锁。您在STATE_A中设置了它,并在STATE_B中使用了它。它必须保持状态之间的价值。这是闩锁行为。
-
在STATE_B中,仅当满足某些条件时,才更改 finished_o 。如果 rst_flag 和 start_i 都为0,会发生什么。您是否要将finish_o设为0或先前的值?在后一种情况下,您需要一个闩锁。
-
fin_res 怎么样?您想在其他州做什么?保留以前的值(锁存器)或具有默认值(无锁存器)。
...
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。