• ECDSA—模乘模块


      如果a,b属于GF(P),则有乘法运算a*b=r (mod p),

    其中r满足0<r<p-1,即a*b除以p的余数。该操作成为模p乘法。本模块输入两个数,完成两个数的模乘运算。

                                                                                                                               

    信号名

    方向

    位宽

    端口定义

    clk

    Input

    1

    时钟

    reset

    Input

    1

    复位

    multip_en

    Input

    1

    模乘使能信号

    a

    Input

    256

    整数乘数a

    b

    Input

    256

    整数乘数b

    product

    output

    256

    模乘运算结果

    done

    output

    1

    模乘完成标识

    算法:模乘运算算法

    输入:a,b∈ [0,n-1], multip_en

    输出:product, done

    1. 初始化product,product=0;
    2. 对于i从0到t-1,重复执行

        2.1.  若bi=1,则product=product + a<<1;

    1. Product = product mod p;
    2. 返回product。

    代码如下:

    module mod_multiplier(
        input                clk, reset,
        input         [255:0] a,
        input         [255:0] b,
        output     reg [255:0] product,
        output     reg         done
    );
        /* multiplication using bit shifting and adding */
        parameter params_p=29;
        //parameter params_p = 256'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F;
    
        reg [510:0] a_in, count_in;
        reg [510:0] b_in,c_in;
        reg a_load, b_load, c_load, count_load;
        wire [510:0] a_out, count_out;
        wire [510:0] b_out, c_out;
    
        reg_256 #(511) a_reg(.clk(clk), .load(a_load), .data(a_in), .out(a_out));
        reg_256 #(511) b_reg(.clk(clk), .load(b_load), .data(b_in), .out(b_out));
        reg_256 #(511) c_reg(.clk(clk), .load(c_load), .data(c_in), .out(c_out));
        reg_256 #(511) count(.clk(clk), .load(count_load), .data(count_in), .out(count_out));
    
        reg [2:0] state, next_state;
        parameter    init        =    3'd0;
        parameter    start        =    3'd1;
        parameter     shift_AB    =    3'd2;
        parameter    reduce_B    =    3'd3;
        parameter    reduce_C    =    3'd4;
        parameter    finish        =    3'd5;
        
    
        always@(posedge clk) begin
            if(reset)
                state <= init;
            else
                state <= next_state;
        end
    
        always@(*) begin
            next_state = state;
            case(state)
                init:
                    next_state = start;
                start:
                    next_state = shift_AB;
                shift_AB: begin
                    if((b_out << 1) >= {255'b0,params_p})
                        next_state = reduce_B;
                    else
                        next_state = reduce_C;
                end
                reduce_B: begin
                    if(b_out >= {255'b0,params_p})
                        next_state = reduce_B;
                    else
                        next_state = reduce_C;
                end
                reduce_C: begin
                    if(count_out == 8'd254)
                        next_state = finish;
                    else
                        next_state = shift_AB;
                end
                finish:
                    next_state = finish;
                default: ;
            endcase
        end
    
    
        always@(*) begin
            count_in = count_out;
            b_in = b_out;
            c_in = c_out;
            a_in = a_out;
    
            count_load = 1'b0;
            a_load = 1'b0;
            b_load = 1'b0;
            c_load = 1'b0;
            product = 256'b0;
            done = 1'b0;
    
            case(state)
                init: begin
                    done = 1'b0;
                    count_in = 8'b0;
                    a_in = a;
                    b_in = {2'b0, b};
                    c_in = 510'b0;
    
                    count_load = 1'b1;
                    a_load = 1'b1;
                    b_load = 1'b1;
                    c_load = 1'b1;
                end
                start: begin
                    if(a[0] == 1)
                        c_in = b_out;
                    else
                        c_in = 510'b0;
                    c_load = 1'b1;
                end
                shift_AB: begin
                    a_in = a_out >> 1;
                    a_load = 1'b1;
                    b_load = 1'b1;
                    b_in = b_out << 1;
                end
                reduce_B: begin
                    b_load = 1'b1;
                    if(b_out >= {255'b0, params_p})
                        b_in = b_out - {255'b0,params_p};
                    else
                        b_in = b_out;
                end
                reduce_C: begin
                    c_load = 1'b1;
                    if(a_out[0] == 1'b1) begin
                        if((c_out + b_out) >= {255'b0, params_p})
                            c_in = (c_out + b_out) - {255'b0, params_p};    
                        else
                            c_in = c_out + b_out;
                    end
                    else begin
                        if(c_out >= {255'b0, params_p})
                            c_in = c_out - params_p;
                        else
                            c_in = c_out;
                    end
                    count_in = count_out + 8'b01;
                    count_load = 1'b1;
                end
                finish: begin
                    if(c_out < params_p) begin
                        done = 1'b1;
                        product = c_out[255:0];
                    end
                    else begin
                        c_in = c_out - {255'b0,params_p};
                        c_load = 1'b1;
                        done = 1'b0;
                    end
                end
                default: ;
            endcase
        end
    
    
    endmodule

    其中reg256.v模块为暂存模块,主要是暂时存储一下temp reg。

    代码如下:

    module reg_256 #(parameter size = 256)
    (
        input   clk, load,
          input   [size-1:0]  data,
          output  reg [size-1:0]  out
    );
    
    always @ (posedge clk)
    begin
        if (load)
              out <= data;
        else
              out <= out;
    end
    
    endmodule

    仿真采用一条简单的曲线先验证结果的正确性,再选用spec256k1曲线来测试模乘速率,

    其参数如下所示,后面的模块都会采用这两条曲线做仿真验证。此次只需将parameter中的p进行修改即可切换曲线。

    sepc256k1曲线参数
    p = FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F a = 0 b =7 G_x = 79BE667E F9DCBBAC 55A06295 CE870B07 029BFCDB 2DCE28D9 59F2815B 16F81798 G_y = 483ADA77 26A3C465 5DA4FBFC 0E1108A8 FD17B448 A6855419 9C47D08F FB10D4B8 n = FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141 h = 01

    testbeach如下所示:

    `timescale 1ns/1ns
    
    module mod_multiplier_tb();
    
        reg clk, reset;
        reg [255:0] a, b;
        wire [255:0] product;
        wire done;
    
        mod_multiplier mult0(
            .clk(clk),
            .reset(reset),
            .a(a),
            .b(b),
            .product(product),
            .done(done)
        );
    
        always #5 clk = ~clk;
    
        initial begin
            clk = 0;
    
            reset = 1'b1;
            #6
            reset = 1'b0;
            a = 12;
            b = 25;
            
            /*
            a = 256'h09;
            b = 256'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFE2F;
            */
            /*#5200
            $display("ad/p=%d",product);
            #20
            $stop();*/
        end
    
    endmodule

    P=29时:选用的测试数据点为(12,25),12*25=300 mod 29 = 10(mod 29),结果正确。

    P=256‘hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F时,

    选用测试点为:a = 256'h09;  b = 256'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFE2F;

    从时间上来看,运算速率看来跟数的大小无关,而是跟相对于p的大小有关。

  • 相关阅读:
    Regionals 2012 :: Asia
    计算几何专题
    简单几何(凸包+多边形面积) POJ 3348 Cows
    简单几何(求凸包点数) POJ 1228 Grandpa's Estate
    简单几何(凸包+枚举) POJ 1873 The Fortified Forest
    简单几何(极角排序) POJ 2007 Scrambled Polygon
    Codeforces Round #328 (Div. 2)
    简单几何(直线求交点) POJ 2074 Line of Sight
    简单几何(点的位置) POJ 1584 A Round Peg in a Ground Hole
    简单几何(线段相交)+模拟 POJ 3449 Geometric Shapes
  • 原文地址:https://www.cnblogs.com/johor-yangmumu/p/15177320.html
Copyright © 2020-2023  润新知