Verilog中的行为算法(GCD)-可能吗?

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

我想写一个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
    
    模块修改(时钟、复位、编号、素数、已完成、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)
    开始
    
    请说明你到目前为止有什么。尝试将
    始终@(状态)
    更改为
    始终@*
    。使用代码和波形更新