我想为 GCD 计算编写一个模块,使用扩展的欧几里得算法。但主要问题是我完全不知道如何在不达到最低(RTL)级别的情况下做到这一点。我的意思是让 FSM 具有三种状态:
- IDLE(等待输入)
- 计算(根据需要尽可能多的时钟周期)
- FINISHED(准备读取输出)。
但是,当我尝试将 FSM 和计算分成单独的进程时,如下所示:
module modinv(clk, reset, number, prime, finished, gcd, inverse_fail, inverse);
input [31:0] number, prime;
input wire clk, reset;
output integer gcd, inverse;
output reg finished, inverse_fail;
parameter [2:0] IDLE = 3'b001, COMPUTING = 3'b010, END = 3'b100;
reg [2:0] state, state_next;
integer a, b, c, q, p, r;
always @ (posedge clk, posedge reset)
begin
if (reset == 1)
begin
state <= IDLE;
end
else
begin
state <= state_next;
end
end
always @(state or b)
begin
finished <= 0;
inverse_fail <= 0;
case (state)
IDLE:
begin
a <= number;
b <= prime;
p <= 1;
r <= 0;
state_next <= COMPUTING;
end
COMPUTING:
begin
c = a % b;
q = a / b;
a = b;
b = c;
r = p - q * r;
p = r;
if (b == 0)
begin
state_next <= END;
end
else
begin
state_next <= COMPUTING;
end
end
END:
begin
gcd <= a;
inverse <= p;
finished <= 1;
if (gcd != 1)
begin
inverse_fail <= 1;
end
end
endcase
end
endmodule
当我尝试将计算放在第二个进程中时,在 COMPUTING 状态的情况下,它只工作一次 - 在 verilog 中是正确的,因为在计算完成之前,状态不会改变,因此不会再次调用该进程.
但是,当我将计算放在第一个过程中时,没有任何不美观的方法可以将计算限制为仅纠正状态,这会导致错误的输出(一旦 FSM 处于 FINISHED 状态,输出就已经不正确 -更进一步)。
所以,我的问题是 - 如何在不使用 FSM + 数据路径(低级 RTL)解决方案的情况下正确地做到这一点?
我当前的波形: