基于大数蒙哥马利的模乘的硬件实现上一篇博客蒙哥马利基2的算法的Verilog 硬件实现(大数模乘)
下面介绍基于蒙哥马利算法实现大数模幂的硬件verilog语言实现
module modular_me_v1 #(parameter WIDTH=1024)
(
input clk,
input rst_n,
input me_start,
input [WIDTH-1:0] M,
input [WIDTH-1:0] E,
input [WIDTH-1:0] Z,
input [WIDTH-1:0] N,
output [WIDTH-1:0] result_C,
output done_flg
);
reg [WIDTH-1:0] M_r,E_r,Z_r,N_r,C_r;
reg [WIDTH-1:0] m0_a,m0_b;
reg [WIDTH-1:0] m1_a,m1_b;
wire [WIDTH-1:0] result_m0,result_m1;
reg [10:0] cnt_i;
wire done0,done1;
parameter CNT_LENGTH = WIDTH;
//reg cm_done;
//reg mm_done;
reg me_done;
reg [WIDTH-1:0] C;
reg [2:0] current_state;
reg [2:0] next_state;
reg done_flg0,done_flg1;
parameter IDLE = 3'b000,
READY1 = 3'b001,
WAIT_CALCU1 = 3'b010,
READY2 = 3'b011,
WAIT_CALCU2 = 3'b100,
READY3 = 3'b101,
WAIT_CALCU3 = 3'b110,
DONE = 3'b111;
wire start;
reg start_dly;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
start_dly <= 0;
else
start_dly <= me_start;
end
assign start = me_start & (!start_dly);
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
E_r<=0;
Z_r<=0;
N_r<=0;
end
else if(start==1'b1)
begin
E_r<=E;
Z_r<=Z;
N_r<=N;
end
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
begin
M_r<=0;
C_r<=1;
end
else if(start==1'b1)
begin
M_r<=M;
C_r<=1;
end
else if (current_state == WAIT_CALCU3 & next_state == READY1)
begin
M_r<=result_m0;
C_r<=result_m1;
end
end
//cnt
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt_i <= 0;
else if (current_state == DONE | current_state == IDLE)
cnt_i <= 0;
else if (current_state == WAIT_CALCU3 & next_state == READY1)
cnt_i <= cnt_i + 1'b1;
end
/*
reg done_dly0;
reg done_dly1;
//delay
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
done_dly0 <= 0;
done_dly1 <= 0;
end
else
begin
done_dly0 <= done0;
done_dly1 <= done1;
end
end
*/
//fsm_ctl
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
current_state <= 3'b000;
else
current_state <= next_state;
end
always@(*)
begin
case(current_state)
IDLE: begin
if(start==1'b1)
next_state = READY1;
else
next_state = IDLE;
end
READY1: begin
if(cnt_i != (WIDTH))
next_state = WAIT_CALCU1;
else
next_state = DONE;
end
WAIT_CALCU1: begin
if(done_flg0 == 1'b1 & done_flg1 == 1'b1)
next_state = READY2;
else
next_state = WAIT_CALCU1;
end
READY2: begin
next_state = WAIT_CALCU2;
end
WAIT_CALCU2: begin
if(done_flg0 == 1'b1 & done_flg1 == 1'b1)
next_state = READY3;
else
next_state = WAIT_CALCU2;
end
READY3: begin
next_state = WAIT_CALCU3;
end
WAIT_CALCU3: begin
if(done_flg0 == 1'b1 & done_flg1 == 1'b1)
next_state = READY1;
else
next_state = WAIT_CALCU3;
end
DONE: begin
next_state = IDLE;
end
default: begin
next_state = IDLE;
end
endcase
end
reg start_mm_en0;
reg start_cm_en1;
//flag_start
always@(*)
begin
if(!rst_n)
begin
start_cm_en1 = 1'b0;
m1_a = 0;
m1_b = 0;
end
else
begin
if (E_r[cnt_i] == 1'b1)
begin
if (current_state == READY1)
begin
start_cm_en1 = 1'b1;
m1_a = C_r;
m1_b = Z_r;
end
else if (current_state == READY2)
begin
start_cm_en1 = 1'b1;
m1_a = result_m1;
m1_b = result_m0;
end
else if (current_state == READY3)
begin
start_cm_en1 = 1'b1;
m1_a = result_m1;
m1_b = 1;
end
else if (current_state == WAIT_CALCU1 | current_state == WAIT_CALCU2 | current_state == WAIT_CALCU3 )
start_cm_en1 = 1'b0;
end
else
start_cm_en1 = 1'b0;
end
end
always@(*)
begin
if(!rst_n)
begin
start_mm_en0 = 1'b0;
m0_a = 0;
m0_b = 0;
end
else if (current_state == READY1)
begin
start_mm_en0 = 1'b1;
m0_a = M_r;
m0_b = Z_r;
end
else if (current_state == READY2)
begin
start_mm_en0 = 1'b1;
m0_a = result_m0;
m0_b = result_m0;
end
else if (current_state == READY3)
begin
start_mm_en0 = 1'b1;
m0_a = result_m0;
m0_b = 1;
end
else if (current_state == WAIT_CALCU1 | current_state == WAIT_CALCU2 | current_state == WAIT_CALCU3 )
start_mm_en0 <= 1'b0;
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
me_done <= 1'b0;
else if (current_state == READY1)
me_done <= 1'b0;
else if (current_state == DONE)
me_done <= 1'b1;
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
C <= 0;
else if (current_state == DONE)
C <= result_m1;
end
assign done_flg = me_done;
assign result_C = C;
montgomery #(.WIDTH(WIDTH)) u_mont_cm(
.clk (clk),
.rstn (rst_n),
.start_flag (start_cm_en1),
.in_a (m1_a),
.in_b (m1_b),
.in_m (N_r),
.result (result_m1),
.done_flag (done1)
);
montgomery #(.WIDTH(WIDTH)) u_mont_mm(
.clk (clk),
.rstn (rst_n),
.start_flag (start_mm_en0),
.in_a (m0_a),
.in_b (m0_b),
.in_m (N_r),
.result (result_m0),
.done_flag (done0)
);
always@(posedge clk or negedge rst_n)
begin
if (!rst_n)
begin
done_flg0<=1'b0;
done_flg1<=1'b0;
end
else if (current_state == READY1 | current_state == READY2 | current_state == READY3 )
begin
done_flg0<=1'b0;
done_flg1<=1'b0;
end
else
begin
done_flg0<=done0;
done_flg1<=done1;
end
end
endmodule