DSP : Vector Multiplier
// Advanced DSP : Vector Multiplier
// DSD week 6
module MAC(
input wire clk_i,
input wire rstn_i,
input wire dsp_enable_i,
input wire signed [7:0] dsp_input_i,
input wire signed [7:0] dsp_weight_i,
input wire dsp_valid_i, //모든 input이 입력 되었다.
output reg signed [31:0] dsp_output_o,
output reg dsp_valid_o
);
reg signed [30:0] partial_sum;
reg delay;
wire [31:0] dsp_output;
always@ (posedge clk_i or negedge rstn_i) begin
if(!rstn_i) begin
partial_sum<= 0;
end
else begin
partial_sum<= $signed({dsp_output[31], dsp_output[29:0]});
end
end
always@ (posedge clk_i or negedge rstn_i) begin
if(!rstn_i) begin
dsp_valid_o<= 0;
delay<= 0;
end
else begin
delay<= dsp_valid_i;
dsp_valid_o<= delay;
end
end
always@ (posedge clk_i or negedge rstn_i) begin
if(!rstn_i) begin
dsp_output_o<= 0;
end
else if(dsp_valid_o) begin
dsp_output_o<= dsp_output;
end
else begin
dsp_output_o<= 0;
end
end
dsp_macro_0 DSP_for_MAC(
.CLK(clk_i), // input wire CLK
.CE(dsp_enable_i), // input wire CE
.A(dsp_input_i), // input wire [7 : 0] A
.B(dsp_weight_i), // input wire [7 : 0] B
.C(partial_sum), // input wire [30 : 0] C
.P(dsp_output) // output wire [31 : 0] P
);
endmodule
`timescale 1ns / 1ps
module tb_MAC();
reg clk;
reg rstn;
reg dsp_enable;
reg signed [7:0] dsp_input;
reg signed [7:0] dsp_weight;
reg dsp_valid_i;
wire dsp_valid_o;
wire signed [31:0] dsp_output;
// make clock (frequency : 100MHz)
initial begin
clk= 0;
forever
#5 clk= ~clk;
end
//reset all system
initial begin
rstn= 1;
#20 rstn= 0; dsp_enable= 0; dsp_input= 0;
dsp_weight= 0; dsp_valid_i= 0;
#10 rstn= 1;
end
initial begin
#40
wait(rstn);
#15 dsp_enable= 1; dsp_input= 1; dsp_weight= -1;
#10 dsp_enable= 1; dsp_input= 2; dsp_weight= -1;
#10 dsp_enable= 1; dsp_input= 3; dsp_weight= -1;
#10 dsp_enable= 1; dsp_input= 4; dsp_weight= -1;
#10 dsp_enable= 1; dsp_input= 5; dsp_weight= -1;
#10 dsp_enable= 1; dsp_input= 6; dsp_weight= -1;
#10 dsp_enable= 1; dsp_input= 7; dsp_weight= -1;
#10 dsp_enable= 1; dsp_input= 8; dsp_weight= -1;
dsp_valid_i= 1;
#10 dsp_enable= 0; dsp_input= 0; dsp_weight= 0;
dsp_valid_i= 0;
#10 dsp_enable= 0; dsp_input= 0; dsp_weight= 0;
end
initial begin
#100
wait(dsp_weight== 0);
#20
$stop();
end
MAC dut(
.clk_i(clk),
.rstn_i(rstn),
.dsp_enable_i(dsp_enable),
.dsp_input_i(dsp_input),
.dsp_weight_i(dsp_weight),
.dsp_valid_i(dsp_valid_i),
.dsp_valid_o(dsp_valid_o),
.dsp_output_o(dsp_output)
);
endmodule

gemv
module gemv(
input wire rstn_i, //Reset signal
input wire clk_i, //Clock signal
input wire en_i, //Enable signal for DSP
input wire valid_i, //Test validity of input signal: High if all input and weight signal are input
input wire [127:0] din_i, //16X8 Matrix input: Receive matrix in one row
input wire [7:0] win_i, //8X1 Vector weight
output reg valid_o, //Verifying signal thet calculation is done
output reg [511:0] gemv_o //Result of calculation
);
wire [31:0] mac_outputs [15:0]; //Calculated signal of each 16 MAC: Each output signal of MAC is 32bit
wire valid_w [15:0]; //Varifying signal that calculation is done: For each 16 MAC
genvar i; //Declare generate variable
generate
for (i = 0; i < 16; i = i + 1) begin : gen_mac //Create module instance 16 times: Since input matrix is '16'X8
MAC mac_inst (
.clk_i (clk_i),
.rstn_i (rstn_i),
.dsp_enable_i (en_i),
.dsp_input_i (din_i [(i*8)+7:i*8]), //For next starting index genvar i, start at (index started before) + 8: Since matrix is expressed in one row
.dsp_weight_i (win_i),
.dsp_valid_i (valid_i),
.dsp_output_o (mac_outputs [i]),
.dsp_valid_o (valid_w [i])
);
end
endgenerate
always @(*) begin
valid_o = valid_w[0]; //Use first valid signal only
gemv_o = {mac_outputs[15], mac_outputs[14], mac_outputs[13], mac_outputs[12], //Concentrate all 16 MAC outputs into GEMV output
mac_outputs[11], mac_outputs[10], mac_outputs[9], mac_outputs[8],
mac_outputs[7], mac_outputs[6], mac_outputs[5], mac_outputs[4],
mac_outputs[3], mac_outputs[2], mac_outputs[1], mac_outputs[0]};
end
endmodule
`timescale 1ns / 1ps
module tb_gemv();
reg clk;
reg rstn;
reg valid_i;
reg en;
reg [127:0] din;
reg [7:0] win;
wire valid_o;
wire [511:0] gemv;
// make clock (frequency : 100MHz)
initial begin
clk=0;
forever
#5 clk= ~clk;
end
//reset all system
initial begin
rstn= 1;
#20 rstn= 0; en= 0; valid_i= 0; din = 0; win = 0;
#10 rstn= 1;
end
initial begin
#40
wait(rstn);
#15 en= 1; din = {8'h01, 8'h02, 8'h01, 8'h02, 8'h01,
8'h02, 8'h01, 8'h02, 8'h01, 8'h02, 8'h01, 8'h02, 8'h01, 8'h02,
8'h01, 8'h02}; win = 8'h01;
#10 en= 1; din = {8'h03, 8'h04, 8'h03, 8'h04, 8'h03,
8'h04, 8'h03, 8'h04, 8'h03, 8'h04, 8'h03, 8'h04, 8'h03, 8'h04,
8'h03, 8'h04}; win = 8'h02;
#10 en= 1; din = {8'h05, 8'h06, 8'h05, 8'h06, 8'h05,
8'h06, 8'h05, 8'h06, 8'h05, 8'h06, 8'h05, 8'h06, 8'h05, 8'h06,
8'h05, 8'h06}; win = 8'h03;
#10 en = 1; din = {8'h07, 8'h08, 8'h07, 8'h08, 8'h07,
8'h08, 8'h07, 8'h08, 8'h07, 8'h08, 8'h07, 8'h08, 8'h07,
8'h08, 8'h07, 8'h08}; win = 8'h04;
#10 en = 1; din = {8'h01, 8'h02, 8'h01, 8'h02,
8'h01, 8'h02, 8'h01, 8'h02, 8'h01, 8'h02, 8'h01, 8'h02,
8'h01, 8'h02, 8'h01, 8'h02}; win = 8'h05;
#10 en= 1; din = {8'h03, 8'h04, 8'h03, 8'h04, 8'h03,
8'h04, 8'h03, 8'h04, 8'h03, 8'h04, 8'h03, 8'h04, 8'h03, 8'h04,
8'h03, 8'h04}; win = 8'h06;
#10 en= 1; din = {8'h05, 8'h06, 8'h05, 8'h06, 8'h05,
8'h06, 8'h05, 8'h06, 8'h05, 8'h06, 8'h05, 8'h06, 8'h05, 8'h06,
8'h05, 8'h06}; win = 8'h07;
#10 en = 1; din = {8'h07, 8'h08, 8'h07, 8'h08, 8'h07,
8'h08, 8'h07, 8'h08, 8'h07, 8'h08, 8'h07, 8'h08, 8'h07,
8'h08, 8'h07, 8'h08}; win = 8'h08;
valid_i = 1;
#10 en = 0; din = 0; win = 0; valid_i = 0;
#10 en = 0; din = 0; win = 0;
end
initial begin
#100
wait(win == 0);
#20
$stop();
end
gemv dut(
.clk_i(clk),
.rstn_i(rstn),
.valid_i(valid_i),
.en_i(en),
.din_i(din),
.win_i(win),
.valid_o(valid_o),
.gemv_o(gemv)
);
endmodule


'Digital System Design' 카테고리의 다른 글
| MAC (0) | 2025.04.01 |
|---|




















































































































