我正在尝试进行的合成是在 GCD 算法有限状态机上进行的,该算法使用“如果更大则减去”方法工作。我将附上代码并尝试制定一个体面的问题。
module GCD_R (A,B,out,nrst,act,clk,fla_g);
input [31:0] A, B;
input clk, act, nrst;
output reg fla_g;
output reg [31:0] out;
reg [3:0] state, next_state;
reg [31:0] A_reg, B_reg, Aint_reg, Bint_reg, out_reg;//2 registers will keep intermediate numbers+out, and next numbers
parameter IDLE = 3'b001;
parameter ABIG = 3'b010;
parameter BBIG = 3'b100;
reg next_flag;
always @(*)
case (state)
IDLE: begin
$display("start");
if(act == 0) begin
A_reg = A; //A,B are wires that contain numbers from an external source
B_reg = B; //first assign to A_reg and B_reg
out_reg = 31'bx;
next_flag = 1'b0;
next_state = IDLE;
end
if(act == 1)
if(A_reg==0) begin
out_reg = B_reg;
next_flag = 1'b1; //testbench will know when we stopped
Aint_reg = A_reg; //taking care not to infer latches
Bint_reg = B_reg;
next_state = IDLE;
end
else if (B_reg==0) begin
out_reg = A_reg;
next_flag = 1'b1;
Aint_reg = A_reg; //taking care not to infer latches
Bint_reg = B_reg;
next_state = IDLE;
end
else if (A_reg >= B_reg) begin
out_reg = 31'bx;
next_flag = 1'b0;
Aint_reg = A_reg;
Bint_reg = B_reg;
next_state = ABIG;
end
else begin
out_reg = 4'bxxx;
next_flag = 1'b0;
Aint_reg = A_reg;
Bint_reg = B_reg;
next_state = BBIG;
end
else
begin
Aint_reg = A_reg;
Bint_reg = B_reg;
out_reg = 4'bxxx;
next_flag = 1'b0;
next_state = 4'bx;
end
end
ABIG: begin
if (A_reg==0 | B_reg==0) begin
out_reg = 31'bx;
next_flag = 1'b0;
next_state = IDLE;
Aint_reg = A_reg;
Bint_reg = B_reg;
end
else if (B_reg > A_reg) begin
out_reg = 31'bx;
next_flag = 1'b0;
next_state = BBIG;
Aint_reg = A_reg;
Bint_reg = B_reg;
end
else begin
out_reg = 31'bx;
next_flag = 1'b0;
next_state = ABIG;
Aint_reg = A_reg - B_reg;
Bint_reg = B_reg;
end
end
BBIG: begin
if (A_reg==0 | B_reg==0) begin
out_reg = 31'bx;
next_flag = 1'b0;
next_state = IDLE;
Aint_reg = A_reg;
Bint_reg = B_reg;
end
else if (A_reg > B_reg) begin
out_reg = 31'bx;
next_flag = 1'b0;
next_state = ABIG;
Aint_reg = A_reg;
Bint_reg = B_reg;
end
else begin
out_reg = 31'bx;
next_flag = 1'b0;
next_state = BBIG;
Aint_reg = A_reg;
Bint_reg = B_reg - A_reg;
end
end
default: begin
out_reg = 31'bx;
next_flag = 1'b0;
next_state = 4'bx;
Aint_reg = A_reg;
Bint_reg = B_reg;
$display("%t: State machine not initialized/n",$time);
end
endcase
always @(posedge clk or negedge nrst)
if (~nrst) begin
state <= IDLE;//we get the new values by resetting first
out <= 4'bx;//we don't want anything there at the reset
fla_g <= 1'b0;
end
else begin
state <= next_state;//otherwise, get the next state and the next registers to the intermediate ones
A_reg <= Aint_reg;// 2nd assign to A_reg and B_reg- that's the problem
B_reg <= Bint_reg;
out <= out_reg;
fla_g <= next_flag;
end
endmodule
首先,A 和 B 是电线,它们将通过外部源(测试台中的一些文本文件)接收要比较的数字列表。
A_reg 和 B_reg 是中间寄存器,用于保存我们正在检查“if”语句的数字,
Aint_reg 和 Bint_reg 是寄存器,在操作后保留寄存器的中间值,仅在时钟上升时将它们发送回 A_reg 和 B_reg,
act 决定机器是否处于“开启”模式并可以执行算法
nrst 是负复位切换
问题是如何形成的:
你可以看到,一开始,有一个if(act == 0)
条件。它被放在那里是为了确保 A、B 线上的值(从外部接收)将进入那里的寄存器,而不是在我们处于这种if(~nrst)
情况时将它们输入到顺序块中,因为在重置。
这将我们带到了当前的问题——我知道在顺序块和组合块中为 A 和 B 赋值是造成问题的原因,但我找不到替代方案。
ps 我正在使用的事实A_reg = A
创建了闩锁,因为我没有分配给A_reg
其他任何地方,这是另一个问题,因为写
Aint_reg = A_reg;
A_reg = Aint_reg;
来满足闩锁并不适合我。
ps2。我尝试在网站上查看类似的问题,但由于我对该主题缺乏足够的知识,我无法将我的问题与那里的问题联系起来
我很乐意得到任何帮助,谢谢
编辑:我删除了 if(~nrst) 顺序块中的非阻塞分配,以免在A_reg <= 0
那里和A_reg = A
组合块中进行多重分配,但是多重分配问题仍然以某种方式对其进行了错误处理
EDIT2:似乎我忘记了一个基本的事情 - 不要在两个不同的“总是”块中分配给同一个变量,但我只是想不出一个足够好的解决方案来将电线 A,B 分配给寄存器而不是在顺序块中再次分配给它