Skip to content

Commit

Permalink
First implementation of the 4x1 multiplication block with test
Browse files Browse the repository at this point in the history
  • Loading branch information
rejunity committed Mar 10, 2024
1 parent c92f439 commit 5af667b
Show file tree
Hide file tree
Showing 6 changed files with 344 additions and 82 deletions.
4 changes: 2 additions & 2 deletions info.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ project:
tiles: "1x1" # Valid values: 1x1, 1x2, 2x2, 3x2, 4x2, 6x2 or 8x2

# Your top module name must start with "tt_um_". Make it unique by including your github username:
top_module: "tt_um_example"
top_module: "tt_um_rejunity_1_58bit"

# List your project's source files here. Source files must be in ./src and you must list each source file separately, one per line:
source_files:
- "project.v"
- "1_58bit_mul.v"

# The pinout of your project. Leave unused pins blank. DO NOT delete or add any pins.
pinout:
Expand Down
125 changes: 125 additions & 0 deletions src/1_58bit_mul.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*
* Copyright (c) 2024 Your Name
* SPDX-License-Identifier: Apache-2.0
*/


// TODOs:
// * pack ternary
// * signal to shift accumulators by 1
// * multiply by beta
// * handle both signed & unsigned inputs

`define default_netname none

module tt_um_rejunity_1_58bit (
input wire [7:0] ui_in, // Dedicated inputs
output wire [7:0] uo_out, // Dedicated outputs
input wire [7:0] uio_in, // IOs: Input path
output wire [7:0] uio_out, // IOs: Output path
output wire [7:0] uio_oe, // IOs: Enable path (active high: 0=input, 1=output)
input wire ena, // will go high when the design is enabled
input wire clk, // clock
input wire rst_n // reset_n - low to reset
);
assign uio_oe = 0; // bidirectional IOs set to INPUT
assign uio_out = 0; // drive bidirectional IO outputs to 0

wire reset = ! rst_n;

// decode ternary weights
wire [3:0] weights_zero = ~ { |ui_in[1:0], |ui_in[3:2], |ui_in[5:4], |ui_in[7:6] };
wire [3:0] weights_sign = { ui_in[1 ], ui_in[3 ], ui_in[5 ], ui_in[7 ] };

// wire [3:0] weights_zero = ~ { |ui_in[7:6], |ui_in[5:4], |ui_in[3:2], |ui_in[1:0] };
// wire [3:0] weights_sign = { ui_in[7 ], ui_in[5 ], ui_in[3 ], ui_in[1 ] };

// @TODO: special weight to initiate readout
wire initiate_read_out = !ena;

systolic_array systolic_array(
.clk(clk),
.reset(reset),

.in_left_zero(weights_zero),
.in_left_sign(weights_sign),
.in_top(uio_in),
.reset_accumulators(initiate_read_out),
.copy_accumulator_values_to_out_queue(initiate_read_out),
.restart_out_queue(initiate_read_out),

.out(uo_out)
);

endmodule

// module systolic_element (
// input wire zero,
// input wire sign,
// input wire arg
// )

module systolic_array (
input wire clk,
input wire reset,

input wire [3:0] in_left_zero,
input wire [3:0] in_left_sign,
input wire [7:0] in_top,
input wire reset_accumulators,
input wire copy_accumulator_values_to_out_queue,
input wire restart_out_queue,
//input wire [2:0] apply_shift_to_out,
//input wire apply_relu_to_out,

output wire [7:0] out
);
reg signed [16:0] accumulators [3:0];
wire signed [16:0] accumulators_next [3:0];
reg signed [16:0] out_queue [3:0];
reg [1:0] out_queue_index;
// wire [16:0] top_in_negative = 17'b0 - top_in;

reg [7:0] n; // mac iterator
// clocked accumulators[]
always @(posedge clk)
for (n = 0; n < 4; n = n + 1)
if (reset | reset_accumulators)
accumulators[n] <= 0;
else
accumulators[n] <= accumulators_next[n];

// clocked out_queue[]
always @(posedge clk)
for (n = 0; n < 4; n = n + 1)
// if (reset)
// out_queue[n] <= 0;
// else
if (copy_accumulator_values_to_out_queue)
out_queue[n] <= accumulators_next[n];

// clocked out_queue_index[]
always @(posedge clk)
if (reset | restart_out_queue)
out_queue_index <= 0;
else
out_queue_index <= out_queue_index + 1;

genvar i, j;
generate
// integer i, j;
for (j = 0; j < 1; j = j + 1)
for (i = 0; i < 4; i = i + 1) begin : mac
wire [16:0] value_curr = accumulators [i*1+j];
wire [16:0] value_next = accumulators_next[i*1+j];
wire [16:0] value_queue = out_queue [i*1+j];
assign accumulators_next[i*1+j] =
reset ? 0 :
in_left_zero[i] ? accumulators[i*1+j] + 0 :
(in_left_sign[i] ? accumulators[i*1+j] - $signed(in_top) :
accumulators[i*1+j] + $signed(in_top));
end
endgenerate

assign out = out_queue[out_queue_index] >> 8;
endmodule
24 changes: 0 additions & 24 deletions src/project.v

This file was deleted.

2 changes: 1 addition & 1 deletion test/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
SIM ?= icarus
TOPLEVEL_LANG ?= verilog
SRC_DIR = $(PWD)/../src
PROJECT_SOURCES = project.v
PROJECT_SOURCES = 1_58bit_mul.v

ifneq ($(GATES),yes)

Expand Down
61 changes: 30 additions & 31 deletions test/tb.v
Original file line number Diff line number Diff line change
Expand Up @@ -5,40 +5,39 @@
*/
module tb ();

// Dump the signals to a VCD file. You can view it with gtkwave.
initial begin
$dumpfile("tb.vcd");
$dumpvars(0, tb);
#1;
end
// Dump the signals to a VCD file. You can view it with gtkwave.
initial begin
$dumpfile("tb.vcd");
$dumpvars(0, tb);
#1;
end

// Wire up the inputs and outputs:
reg clk;
reg rst_n;
reg ena;
reg [7:0] ui_in;
reg [7:0] uio_in;
wire [7:0] uo_out;
wire [7:0] uio_out;
wire [7:0] uio_oe;
// Wire up the inputs and outputs:
reg clk;
reg rst_n;
reg ena;
reg [7:0] ui_in;
reg [7:0] uio_in;
wire [7:0] uo_out;
wire [7:0] uio_out;
wire [7:0] uio_oe;

// Replace tt_um_example with your module name:
tt_um_example user_project (
// Replace tt_um_example with your module name:
tt_um_rejunity_1_58bit user_project (
// Include power ports for the Gate Level test:
`ifdef GL_TEST
.VPWR(1'b1),
.VGND(1'b0),
`endif

// Include power ports for the Gate Level test:
`ifdef GL_TEST
.VPWR(1'b1),
.VGND(1'b0),
`endif

.ui_in (ui_in), // Dedicated inputs
.uo_out (uo_out), // Dedicated outputs
.uio_in (uio_in), // IOs: Input path
.uio_out(uio_out), // IOs: Output path
.uio_oe (uio_oe), // IOs: Enable path (active high: 0=input, 1=output)
.ena (ena), // enable - goes high when design is selected
.clk (clk), // clock
.rst_n (rst_n) // not reset
.ui_in (ui_in), // Dedicated inputs
.uo_out (uo_out), // Dedicated outputs
.uio_in (uio_in), // IOs: Input path
.uio_out(uio_out), // IOs: Output path
.uio_oe (uio_oe), // IOs: Enable path (active high: 0=input, 1=output)
.ena (ena), // enable - goes high when design is selected
.clk (clk), // clock
.rst_n (rst_n) // not reset
);

endmodule
Loading

0 comments on commit 5af667b

Please sign in to comment.