系统Verilog循环
我目前正在系统Verilog中进行移位加法算法(32x32位乘法)。系统Verilog找不到任何错误,我的代码根据GTKwave正常工作。当我用yosys合成电路时,将添加锁存器。这就是问题所在。我的电路不需要插销。这是我的密码:系统Verilog循环,verilog,system-verilog,cpu-architecture,hdl,yosys,Verilog,System Verilog,Cpu Architecture,Hdl,Yosys,我目前正在系统Verilog中进行移位加法算法(32x32位乘法)。系统Verilog找不到任何错误,我的代码根据GTKwave正常工作。当我用yosys合成电路时,将添加锁存器。这就是问题所在。我的电路不需要插销。这是我的密码: module multiplier( input logic clk_i, input logic rst_i, input logic start_i, input logic [31:0] a_i,
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
模块乘法器(
输入逻辑时钟i,
输入逻辑rst_i,
输入逻辑启动i,
输入逻辑[31:0]a_i,
输入逻辑[31:0]b_i,
输出逻辑已完成,
输出逻辑[63:0]结果\u o
);
typedef枚举逻辑[1:0]{STATE_A,STATE_B}STATE_t;
州,州,州;
逻辑[63:0]fin_res;
逻辑[63:0]tmp;
逻辑rst_标志;
整数i;
始终@(posedge clk_i或posedge rst_i)开始
如果(rst_i==1'b1)开始
从注释中可以看出,在第二个case语句中没有分配一组变量,从而导致合成生成锁存。为了避免这种情况,您需要递归地分配case语句和条件语句的所有分支中的所有变量
但是,如果有一个默认值可以分配给所有这些值,则可以使用类似于第二个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_标志=0;
fin_res=0;
成品_o=0;
tmp=0;
结果_o=0;
案件(州)
A国:开始
rst_标志=1;
对于(i=0;i<32;i=i+1)开始
如果(a_i[i]==1'b1)开始
tmp=b_i;
tmp=tmp从注释中可以看出,在第二个case语句中没有分配一组变量,从而导致合成生成锁存。为了避免这种情况,您需要递归地分配case语句和条件语句的所有分支中的所有变量
但是,如果有一个默认值可以分配给所有这些值,则可以使用类似于第二个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_标志=0;
fin_res=0;
成品_o=0;
tmp=0;
结果_o=0;
案件(州)
A国:开始
rst_标志=1;
对于(i=0;i<32;i=i+1)开始
如果(a_i[i]==1'b1)开始
tmp=b_i;
tmp=tmp,但您确实使用第二个case语句编写了一个闩锁。e、 例如,您不会在每种情况下都分配完成的o(您使用“if”而没有其他选项)。同样使用rst\u标志
,因为如果state\u p
不是state\u A
则不会分配它。是的,但即使修复了这些,也不会改变闩锁的任何内容。好的,我修复了它。有时候重写整个代码比搜索bug要好。。。Thx for the help guys:)还有fin_res
,可能还有tmp
。但是您确实用第二个case语句编写了一个闩锁。e、 例如,您不会在每种情况下都分配完成的o(您使用“if”而没有其他选项)。同样使用rst\u标志
,因为如果state\u p
不是state\u A
则不会分配它。是的,但即使修复了这些,也不会改变闩锁的任何内容。好的,我修复了它。有时候重写整个代码比搜索bug要好。。。谢谢大家:)还有fin\u res
,可能还有tmp
。是的,你说得对。锁存器在我的代码中是必需的。我重写了整个代码,所以我现在没有任何锁存。谢谢你的帮助:)是的,你是对的。锁存器在我的代码中是必需的。我重写了整个代码,所以我现在没有任何锁存。谢谢您的帮助:)