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

凯珀·巴纳西克

我想使用扩展的欧几里得算法编写用于GCD计算的模块。但是主要的问题是,在不达到最低(RTL)级别的情况下,我完全不知道该怎么做。我的意思是使FSM具有三种状态:

  1. 空闲(等待输入)
  2. 计算(根据需要的时钟周期数)
  3. 完成(准备读取输出)。

但是,当我尝试将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)解决方案的情况下正确地做到这一点?

我当前的波形:

波形图

提姆

您似乎在设计中缺少一些时钟元素。

从我了解你的设计,你似乎期望一旦国家去计算它应该保持迭代值ab直到b达到0。但是,只有你实际计时时钟边沿上的事情是状态变量,所以从一个状态到下一个状态都没有记忆a和b。如果您希望像这样的变量ab从一个时钟周期到下一个时钟周期具有内存,则还需要锁存这些变量:

我对您的程序进行了一些修改,可能不是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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章