Pipelined multiplier: 3-stage LUT-based replaces shift_add, FSM simplified to 2-state
This commit is contained in:
@@ -1,51 +1,27 @@
|
||||
// ═══════════════════════════════════════════════════════
|
||||
// 基础时序乘法器模块 (无 DSP,移位累加,32个周期)
|
||||
// 3-stage pipelined multiplier (LUT-based, no DSP)
|
||||
// latency=3, throughput=1 result/cycle
|
||||
// ═══════════════════════════════════════════════════════
|
||||
module shift_add_mult (
|
||||
(* use_dsp = "no" *)
|
||||
module pipelined_mult_32x32 (
|
||||
input clk,
|
||||
input rstn,
|
||||
input start,
|
||||
input [31:0] a,
|
||||
input [31:0] b,
|
||||
output reg [63:0] p,
|
||||
output reg done
|
||||
output reg [63:0] p
|
||||
);
|
||||
reg [5:0] cnt;
|
||||
reg [63:0] a_reg;
|
||||
reg [31:0] b_reg;
|
||||
reg busy;
|
||||
|
||||
reg [31:0] a_r, b_r;
|
||||
reg [63:0] prod;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (!rstn) begin
|
||||
busy <= 1'b0;
|
||||
done <= 1'b0;
|
||||
p <= 64'b0;
|
||||
cnt <= 6'd0;
|
||||
a_reg<= 64'b0;
|
||||
b_reg<= 32'b0;
|
||||
a_r <= 32'b0; b_r <= 32'b0;
|
||||
prod <= 64'b0; p <= 64'b0;
|
||||
end else begin
|
||||
if (start && !busy) begin
|
||||
a_reg <= {32'b0, a};
|
||||
b_reg <= b;
|
||||
p <= 64'b0;
|
||||
cnt <= 6'd0;
|
||||
busy <= 1'b1;
|
||||
done <= 1'b0;
|
||||
end else if (busy) begin
|
||||
if (cnt == 6'd32) begin
|
||||
busy <= 1'b0;
|
||||
done <= 1'b1;
|
||||
end else begin
|
||||
if (b_reg[0]) begin
|
||||
p <= p + a_reg;
|
||||
end
|
||||
a_reg <= a_reg << 1;
|
||||
b_reg <= b_reg >> 1;
|
||||
cnt <= cnt + 6'd1;
|
||||
end
|
||||
end else begin
|
||||
done <= 1'b0;
|
||||
end
|
||||
a_r <= a; // Stage 1: register inputs
|
||||
b_r <= b;
|
||||
prod <= a_r * b_r; // Stage 2: LUT-based multiply
|
||||
p <= prod; // Stage 3: register output
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
@@ -323,9 +299,7 @@ module matmul_axi_slave (
|
||||
|
||||
// 前向声明引擎的状态
|
||||
localparam C_IDLE = 2'd0;
|
||||
localparam C_CALC = 2'd1;
|
||||
localparam C_WAIT_MULT = 2'd2;
|
||||
localparam C_ACCUM = 2'd3;
|
||||
localparam C_RUN = 2'd1;
|
||||
reg [1:0] state;
|
||||
reg cur_bank;
|
||||
reg calc_done_pulse;
|
||||
@@ -344,8 +318,8 @@ module matmul_axi_slave (
|
||||
done <= 1'b0;
|
||||
error <= 1'b0;
|
||||
end else begin
|
||||
if (req_0 && state == C_CALC && cur_bank == 1'b0) req_0 <= 1'b0;
|
||||
if (req_1 && state == C_CALC && cur_bank == 1'b1) req_1 <= 1'b0;
|
||||
if (req_0 && state == C_RUN && cur_bank == 1'b0) req_0 <= 1'b0;
|
||||
if (req_1 && state == C_RUN && cur_bank == 1'b1) req_1 <= 1'b0;
|
||||
|
||||
if (calc_done_pulse) begin
|
||||
done <= 1'b1;
|
||||
@@ -524,102 +498,104 @@ module matmul_axi_slave (
|
||||
// ==========================================
|
||||
// 计算引擎 (Compute FSM)
|
||||
// ==========================================
|
||||
reg [3:0] calc_idx;
|
||||
|
||||
wire [1:0] row = calc_idx[3:2];
|
||||
wire [1:0] col = calc_idx[1:0];
|
||||
|
||||
reg mult_start;
|
||||
wire mult_done [0:3];
|
||||
wire [63:0] mult_p [0:3];
|
||||
reg [63:0] mult_p_r [0:3];
|
||||
reg [31:0] m_in_a [0:3];
|
||||
reg [31:0] m_in_b [0:3];
|
||||
|
||||
genvar i;
|
||||
generate
|
||||
for (i = 0; i < 4; i = i + 1) begin : mult_inst
|
||||
shift_add_mult u_mult (
|
||||
.clk (clk),
|
||||
.rstn (resetn),
|
||||
.start (mult_start),
|
||||
.a (m_in_a[i]),
|
||||
.b (m_in_b[i]),
|
||||
.p (mult_p[i]),
|
||||
.done (mult_done[i])
|
||||
pipelined_mult_32x32 u_mult (
|
||||
.clk (clk),
|
||||
.rstn (resetn),
|
||||
.a (m_in_a[i]),
|
||||
.b (m_in_b[i]),
|
||||
.p (mult_p[i])
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// Pipeline delay shift registers for accumulation (4 stages = 3 multiplier pipe + 1)
|
||||
reg [3:0] acc_idx_d1, acc_idx_d2, acc_idx_d3, acc_idx_d4;
|
||||
reg acc_bank_d1, acc_bank_d2, acc_bank_d3, acc_bank_d4;
|
||||
reg [4:0] pipe_cnt;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (!resetn) begin
|
||||
state <= C_IDLE;
|
||||
busy <= 1'b0;
|
||||
cur_bank <= 1'b0;
|
||||
calc_idx <= 4'd0;
|
||||
mult_start <= 1'b0;
|
||||
calc_done_pulse <= 1'b0;
|
||||
pipe_cnt <= 5'd0;
|
||||
acc_idx_d1 <= 4'd0;
|
||||
acc_idx_d2 <= 4'd0;
|
||||
acc_idx_d3 <= 4'd0;
|
||||
acc_idx_d4 <= 4'd0;
|
||||
acc_bank_d1 <= 1'b0;
|
||||
acc_bank_d2 <= 1'b0;
|
||||
acc_bank_d3 <= 1'b0;
|
||||
acc_bank_d4 <= 1'b0;
|
||||
end else begin
|
||||
calc_done_pulse <= 1'b0;
|
||||
|
||||
|
||||
// Pipeline shift: issue_idx → d1 → d2 → d3 → d4 (4 cycles total)
|
||||
acc_idx_d4 <= acc_idx_d3;
|
||||
acc_idx_d3 <= acc_idx_d2;
|
||||
acc_idx_d2 <= acc_idx_d1;
|
||||
acc_idx_d1 <= pipe_cnt[3:0];
|
||||
acc_bank_d4 <= acc_bank_d3;
|
||||
acc_bank_d3 <= acc_bank_d2;
|
||||
acc_bank_d2 <= acc_bank_d1;
|
||||
acc_bank_d1 <= cur_bank;
|
||||
|
||||
case (state)
|
||||
C_IDLE: begin
|
||||
calc_idx <= 4'd0;
|
||||
pipe_cnt <= 5'd0;
|
||||
if (req_0) begin
|
||||
cur_bank <= 1'b0;
|
||||
busy <= 1'b1;
|
||||
state <= C_CALC;
|
||||
state <= C_RUN;
|
||||
end else if (req_1) begin
|
||||
cur_bank <= 1'b1;
|
||||
busy <= 1'b1;
|
||||
state <= C_CALC;
|
||||
state <= C_RUN;
|
||||
end else begin
|
||||
busy <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
C_CALC: begin
|
||||
if (cur_bank == 1'b0) begin
|
||||
m_in_a[0] <= b0_a[{row, 2'd0}]; m_in_b[0] <= b0_b[{2'd0, col}];
|
||||
m_in_a[1] <= b0_a[{row, 2'd1}]; m_in_b[1] <= b0_b[{2'd1, col}];
|
||||
m_in_a[2] <= b0_a[{row, 2'd2}]; m_in_b[2] <= b0_b[{2'd2, col}];
|
||||
m_in_a[3] <= b0_a[{row, 2'd3}]; m_in_b[3] <= b0_b[{2'd3, col}];
|
||||
end else begin
|
||||
m_in_a[0] <= b1_a[{row, 2'd0}]; m_in_b[0] <= b1_b[{2'd0, col}];
|
||||
m_in_a[1] <= b1_a[{row, 2'd1}]; m_in_b[1] <= b1_b[{2'd1, col}];
|
||||
m_in_a[2] <= b1_a[{row, 2'd2}]; m_in_b[2] <= b1_b[{2'd2, col}];
|
||||
m_in_a[3] <= b1_a[{row, 2'd3}]; m_in_b[3] <= b1_b[{2'd3, col}];
|
||||
|
||||
C_RUN: begin
|
||||
// Issue 4 new operands every cycle (pipe_cnt 0-11, 12 rounds)
|
||||
if (pipe_cnt < 5'd12) begin
|
||||
if (cur_bank == 1'b0) begin
|
||||
m_in_a[0] <= b0_a[{pipe_cnt[3:2], 2'd0}]; m_in_b[0] <= b0_b[{2'd0, pipe_cnt[1:0]}];
|
||||
m_in_a[1] <= b0_a[{pipe_cnt[3:2], 2'd1}]; m_in_b[1] <= b0_b[{2'd1, pipe_cnt[1:0]}];
|
||||
m_in_a[2] <= b0_a[{pipe_cnt[3:2], 2'd2}]; m_in_b[2] <= b0_b[{2'd2, pipe_cnt[1:0]}];
|
||||
m_in_a[3] <= b0_a[{pipe_cnt[3:2], 2'd3}]; m_in_b[3] <= b0_b[{2'd3, pipe_cnt[1:0]}];
|
||||
end else begin
|
||||
m_in_a[0] <= b1_a[{pipe_cnt[3:2], 2'd0}]; m_in_b[0] <= b1_b[{2'd0, pipe_cnt[1:0]}];
|
||||
m_in_a[1] <= b1_a[{pipe_cnt[3:2], 2'd1}]; m_in_b[1] <= b1_b[{2'd1, pipe_cnt[1:0]}];
|
||||
m_in_a[2] <= b1_a[{pipe_cnt[3:2], 2'd2}]; m_in_b[2] <= b1_b[{2'd2, pipe_cnt[1:0]}];
|
||||
m_in_a[3] <= b1_a[{pipe_cnt[3:2], 2'd3}]; m_in_b[3] <= b1_b[{2'd3, pipe_cnt[1:0]}];
|
||||
end
|
||||
end
|
||||
mult_start <= 1'b1;
|
||||
state <= C_WAIT_MULT;
|
||||
end
|
||||
|
||||
C_WAIT_MULT: begin
|
||||
mult_start <= 1'b0;
|
||||
if (mult_done[0] && mult_done[1] && mult_done[2] && mult_done[3]) begin
|
||||
mult_p_r[0] <= mult_p[0];
|
||||
mult_p_r[1] <= mult_p[1];
|
||||
mult_p_r[2] <= mult_p[2];
|
||||
mult_p_r[3] <= mult_p[3];
|
||||
state <= C_ACCUM;
|
||||
|
||||
// Accumulate results from 4 cycles ago (pipe_cnt 4-15)
|
||||
if (pipe_cnt >= 5'd4 && pipe_cnt < 5'd16) begin
|
||||
if (acc_bank_d4 == 1'b0)
|
||||
b0_c[acc_idx_d4] <= ({2'b0, mult_p[0]} + {2'b0, mult_p[1]}) +
|
||||
({2'b0, mult_p[2]} + {2'b0, mult_p[3]});
|
||||
else
|
||||
b1_c[acc_idx_d4] <= ({2'b0, mult_p[0]} + {2'b0, mult_p[1]}) +
|
||||
({2'b0, mult_p[2]} + {2'b0, mult_p[3]});
|
||||
end
|
||||
end
|
||||
|
||||
C_ACCUM: begin
|
||||
if (cur_bank == 1'b0)
|
||||
b0_c[calc_idx] <= ({2'b0, mult_p_r[0]} + {2'b0, mult_p_r[1]}) +
|
||||
({2'b0, mult_p_r[2]} + {2'b0, mult_p_r[3]});
|
||||
else
|
||||
b1_c[calc_idx] <= ({2'b0, mult_p_r[0]} + {2'b0, mult_p_r[1]}) +
|
||||
({2'b0, mult_p_r[2]} + {2'b0, mult_p_r[3]});
|
||||
|
||||
if (calc_idx == 4'd15) begin
|
||||
|
||||
if (pipe_cnt == 5'd16) begin
|
||||
calc_done_pulse <= 1'b1;
|
||||
busy <= 1'b0;
|
||||
state <= C_IDLE;
|
||||
end else begin
|
||||
calc_idx <= calc_idx + 4'd1;
|
||||
state <= C_CALC;
|
||||
pipe_cnt <= pipe_cnt + 5'd1;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
|
||||
Reference in New Issue
Block a user