蒙哥马利基2的算法的Verilog 硬件实现(大数模乘)

Posted 摆渡沧桑

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了蒙哥马利基2的算法的Verilog 硬件实现(大数模乘)相关的知识,希望对你有一定的参考价值。

基于蒙哥马利基2的算法的 的python 语言参考上一篇博客 蒙哥马利基2的Python算法实现(大数模乘)

下面提供基于蒙哥马利算法实现基2 的硬件verilog语言编写,提供给大家学习,参考。

`timescale 1ns / 1ps

module montgomery #(parameter WIDTH =1024)
    (
    input                   clk,
    input                   rstn,
    input                   start_flag, 
    input   [(WIDTH-1):0]   in_a,
    input   [(WIDTH-1):0]   in_b,
    input   [(WIDTH-1):0]   in_m,

    output  [(WIDTH-1):0]   result,    
    output                  done_flag
);

    `define FUNC(x) \\
    (x < 2    ) ? 1   :   \\
    (x < 4    ) ? 2   :   \\
    (x < 8    ) ? 3   :   \\
    (x < 16   ) ? 4   :   \\
    (x < 32   ) ? 5   :   \\
    (x < 64   ) ? 6   :   \\
    (x < 128  ) ? 7   :   \\
    (x < 256  ) ? 8   :   \\
    (x < 512  ) ? 9   :   \\
    (x < 1024 ) ? 10  :   \\
    (x < 2048 ) ? 11  :   \\
    (x < 4096 ) ? 12  :   \\
                -1   
    
    //PARAMETER WIDTH = 1024;
    localparam CNT_WIDTH   = `FUNC(WIDTH+1);


    parameter  IDLE        = 3'b000;
    parameter  START       = 3'b001;
    parameter  WAIT1       = 3'b010;
    parameter  CHECK       = 3'b011;
    parameter  WAIT2       = 3'b100;
    parameter  DONE        = 3'b101;


    reg [(WIDTH + 1):0]         reg_A, reg_B; //1026bit
    reg [(WIDTH - 1):0]         reg_M;
    reg [(WIDTH + 2):0]         add_a, add_b;

    reg [CNT_WIDTH  :0]         cnt;

    reg [(WIDTH + 2):0]         r_result;
    reg [(WIDTH + 2):0]         C;

    reg                         done, subtract, add_start;
    reg [2:0]                   state, next_state;


    //wire [WIDTH:0]              a, b;
    wire [(WIDTH + 2):0]        add_result;
    wire                        add_done, shift;

    assign shift = 0;
    
    adder_sim  #(.ADD_WIDTH(WIDTH)) u_adder
       (.in_a                   (add_a),
        .in_b                   (add_b),
        .subtract               (subtract),
        .start                  (add_start),
        .result                 (add_result),
        .done                   (add_done),
        .clk                    (clk),
        .resetn                 (rstn),
        .shift                  (shift)
        );
    
    //cnt
    always @(posedge clk or negedge rstn)
    begin
        if (!rstn)
                cnt <= 0;
        else if ((state == IDLE) | (state == DONE ))
                cnt <= 0;
        else if (state == CHECK)
                cnt <= cnt + 1'b1;
    end

    wire reg_C_0; //LSB
    assign reg_C_0 = C[0]; //^ (reg_A[cnt]  & reg_B[0]);
    
    reg start_dly;
    wire start;
    always @(posedge clk or negedge rstn)
        if(!rstn)
            start_dly <= 1'b0;
        else 
            start_dly <= start_flag;

    assign start = start_flag & (! start_dly);

    //A,B,M      
    always @(posedge clk or negedge rstn)
        if (!rstn)
            begin
                reg_A <= 0;
                reg_B <= 0;
                reg_M <= 0;
            end
        else if (start == 1'b1)
            begin
                reg_A <= 2'b00,in_a;
                reg_B <= 2'b00,in_b;
                reg_M <= in_m;
            end


    //fsm contrl
    always @(posedge clk or negedge rstn)
        if(!rstn)
            state <= 3'b000;
        else
            state <= next_state;
    
    always @(*)
        begin
              case(state)
                IDLE:   begin//IDLE
                            if (start == 1)
                                next_state = START;
                            else 
                                next_state = IDLE;
                        end

                START:  begin//START
                            if (cnt == (WIDTH+2))
                                next_state = DONE;
                            else
                            begin 
                                if (reg_A[cnt] == 1)
                                    next_state = WAIT1;
                                else
                                    next_state = CHECK;
                            end
                        end

                WAIT1:  begin//WAIT1
                            if (add_done == 1)
                                next_state = CHECK;
                            else
                                next_state = WAIT1;
                        end

                CHECK:  begin// Check
                            if (reg_C_0 == 0)
                                next_state = START;
                            else
                                next_state = WAIT2;
                        end

                WAIT2:  begin//WAIT2
                            if (add_done == 1)
                                next_state = START;
                            else
                                next_state = WAIT2;
                        end

                DONE: begin//DONE
                            next_state = IDLE;
                        end

                default:begin
                            next_state = IDLE;
                        end

                endcase
        end

    //reg_c
    always @(posedge clk or negedge rstn)
        if (!rstn)
            C <= 0;
        else if (state == IDLE)
            C <= 0;
        else if (state == WAIT1 & add_done == 1)
            C <= add_result;
        else if (state == CHECK & reg_C_0 == 0)
            C <= C >> 1;
        else if (state == WAIT2 & add_done == 1)
            C <= add_result >> 1;

    //add_flag
    always @(*)
        if (!rstn)
        begin
            add_start =  0;
            add_a     =  0;
            add_b     =  0;
        end
        else if (state == START & reg_A[cnt] == 1 )
        begin
            add_start =1;
            add_a     = C;
            add_b     = reg_B[(WIDTH-1):0];
        end
        else if (state == CHECK & reg_C_0 != 0 )
        begin
            add_a     = C;
            add_b     = reg_M;
            add_start = 1;
        end
        else if (state == DONE | state == WAIT1 | state == WAIT2 )
            add_start = 0;

    //done_flag
    always @(posedge clk or negedge rstn)
        if (!rstn)
        begin
            done     <= 0;
            r_result <= 0;
        end
        else if (next_state == START )
            done     <= 0;
        else if (state == DONE )
        begin
            done     <= 1'b1;
            r_result <= C;
        end

     
    assign result = r_result[(WIDTH-1):0];
    assign done_flag = done;

endmodule

以上是关于蒙哥马利基2的算法的Verilog 硬件实现(大数模乘)的主要内容,如果未能解决你的问题,请参考以下文章

[从零开始学习FPGA编程-9]:快速入门篇 - 操作步骤2 - 硬件电路图形化描述与文本硬件描述语言Verilog HDL与VHDL语言以及比较

[从零开始学习FPGA编程-10]:快速入门篇 - 操作步骤2 - Verilog HDL语言Module与硬件电路对应关系快速概览

[从零开始学习FPGA编程-16]:快速入门篇 - 操作步骤2-4- Verilog HDL语言描述语言基本语法(软件程序员和硬件工程师都能看懂)

FPGA人员检测基于FPGA的人员检测,verilog编程实现,含硬件测试

蒙哥马利算法详解

蒙哥马利算法详解