我想使用扩展的欧几里得算法编写用于GCD计算的模块。但是主要的问题是,在不达到最低(RTL)级别的情况下,我完全不知道该怎么做。我的意思是使FSM具有三种状态:
但是,当我尝试将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表示是正确的,因为在完成计算之前,状态不会改变,因此不会再次调用该过程。
但是,当我将计算放在第一个过程中时,没有任何非丑陋的方式将计算限制为仅校正STATE,这会导致错误的输出(一旦FSM处于FINISHED状态,则输出已经不正确-更进一步)。
因此,我的问题是-如何在不使用FSM +数据路径(低级RTL)解决方案的情况下正确地做到这一点?
我当前的波形:
您似乎在设计中缺少一些时钟元素。
从我了解你的设计,你似乎期望一旦国家去计算它应该保持迭代值a
和b
直到b
达到0。但是,只有你实际计时时钟边沿上的事情是状态变量,所以从一个状态到下一个状态都没有记忆a和b。如果您希望像这样的变量a
并b
从一个时钟周期到下一个时钟周期具有内存,则还需要锁存这些变量:
我对您的程序进行了一些修改,可能不是100%正确,但是您应该了解我的意思。看看这在第二个块中如何执行组合逻辑是否有意义,但是将这些值注册在posege上,以便可以在下一个时钟周期开始时使用它们。
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;
integer a_next, b_next, p_next, r_next;
always @ (posedge clk, posedge reset)
begin
if (reset == 1)
begin
state <= IDLE;
a <= 0;
b <= 0;
p <= 0;
r <= 0;
end
else
begin
state <= state_next;
a <= a_next;
b <= b_next;
p <= p_next;
r <= r_next;
end
end
always @* //just use the auto-triggered '@*' operator
begin
finished <= 0;
inverse_fail <= 0;
case (state)
IDLE:
begin
a_next <= number;
b_next <= prime;
p_next <= 1;
r_next <= 0;
state_next <= COMPUTING;
end
COMPUTING:
begin
c = a % b;
q = a / b;
a_next = b;
b_next = c;
r_next = p - q * r;
p_next = 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
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句