Verilog中的行为算法(GCD)-可能吗?
我想写一个GCD计算模块,使用扩展的欧几里德算法。但主要的问题是,我完全不知道如何在不达到最低(RTL)水平的情况下做到这一点。我的意思是FSM有三个州:Verilog中的行为算法(GCD)-可能吗?,verilog,hdl,register-transfer-level,Verilog,Hdl,Register Transfer Level,我想写一个GCD计算模块,使用扩展的欧几里德算法。但主要的问题是,我完全不知道如何在不达到最低(RTL)水平的情况下做到这一点。我的意思是FSM有三个州: 空闲(等待输入) 计算(需要多少时钟周期) 已完成(准备读取输出) 但是,当我尝试将FSM和计算分离为单独的过程时,如下所示: module modinv(clk, reset, number, prime, finished, gcd, inverse_fail, inverse); input [31:0] number, pr
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
模块修改(时钟、复位、编号、素数、已完成、gcd、反向故障、反向);
输入[31:0]个数,素数;
输入线时钟,复位;
输出整数gcd,逆;
输出reg完成,反向_失败;
参数[2:0]怠速=3'b001,计算=3'b010,结束=3'b100;
reg[2:0]状态,状态为“下一步”;
整数a,b,c,q,p,r;
始终@(posedge时钟、posedge重置)
开始
如果(重置==1)
开始
状态您的设计中似乎缺少一些时钟元素
从我对您的设计的理解来看,您似乎期望一旦状态进入计算,它应该不断迭代a
和b
的值,直到b
达到0。但是,在时钟边缘上实际计时的唯一事物是状态变量,因此从一个状态到下一个状态之间没有a和b的内存。如果希望a
和b
等变量从一个时钟周期到下一个时钟周期都有内存,则还需要锁定这些变量:
我对你的程序做了一些修改,可能不是100%正确,但你应该明白我的意思。看看在第二个块中执行组合逻辑的方式是否合理,但在posedge上注册值,以便在下一个时钟周期开始时使用它们
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
模块修改(时钟、复位、编号、素数、已完成、gcd、反向故障、反向);
输入[31:0]个数,素数;
输入线时钟,复位;
输出整数gcd,逆;
输出reg完成,反向_失败;
参数[2:0]怠速=3'b001,计算=3'b010,结束=3'b100;
reg[2:0]状态,状态为“下一步”;
整数a,b,c,q,p,r;
整数a_next,b_next,p_next,r_next;
始终@(posedge时钟、posedge重置)
开始
如果(重置==1)
开始
请说明你到目前为止有什么。尝试将始终@(状态)
更改为始终@*
。使用代码和波形更新