From 8767ed8e48cfe75fc0d5bcda348af5c8ef94c1e8 Mon Sep 17 00:00:00 2001 From: Eva Jin Date: Sun, 15 Feb 2026 18:19:19 -0500 Subject: [PATCH 01/18] Documentaion --- docs/info.md | 22 ++++++++++------------ info.yaml | 4 ++-- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/docs/info.md b/docs/info.md index ce1f04c..cc30aec 100644 --- a/docs/info.md +++ b/docs/info.md @@ -1,20 +1,18 @@ - - ## How it works -Explain how your project works +This control module manages request and completion queues for SPI-based communication. It includes: +- Request queue for incoming commands +- Completion queue for completed operations +- SPI for communication +- AES and SHA FSM controllers for cryptographic operations +- Bus arbiter for managing multi-source requests ## How to test -Explain how to use your project +- Run `make` in the test/ directory to execute all cocotb tests +- Tests verify queue operations, SPI communication, and FSM functionality +- Results are output to test/results.xml ## External hardware -List external hardware used in your project (e.g. PMOD, LED display, etc), if any +SPI Master/Host device for sending commands and receiving responses over MOSI/MISO lines diff --git a/info.yaml b/info.yaml index d6480c5..5147e35 100644 --- a/info.yaml +++ b/info.yaml @@ -3,7 +3,7 @@ project: title: "UWASIC-control-module" # Project title author: "UW-ASIC" # Your name discord: "" # Your discord username, for communication and automatically assigning you a Tapeout role (optional) - description: "" # One line description of what your project does + description: "Control module for queue management and SPI communication" # One line description of what your project does language: "Verilog" # other examples include SystemVerilog, Amaranth, VHDL, etc clock_hz: 0 # Clock frequency in Hz (or 0 if not applicable) @@ -11,7 +11,7 @@ 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_uwasic_control" # List your project's source files here. # Source files must be in ./src and you must list each source file separately, one per line. From 79b6c4f7294e244c6eefb9ee54edadf874540542 Mon Sep 17 00:00:00 2001 From: Eva Jin Date: Sun, 15 Feb 2026 19:18:21 -0500 Subject: [PATCH 02/18] fixes --- info.yaml | 2 +- src/{control_top.v => tt_um_control_top.v} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/{control_top.v => tt_um_control_top.v} (100%) diff --git a/info.yaml b/info.yaml index 5147e35..5f0aa4d 100644 --- a/info.yaml +++ b/info.yaml @@ -11,7 +11,7 @@ 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_uwasic_control" + top_module: "tt_um_control_top" # List your project's source files here. # Source files must be in ./src and you must list each source file separately, one per line. diff --git a/src/control_top.v b/src/tt_um_control_top.v similarity index 100% rename from src/control_top.v rename to src/tt_um_control_top.v From dea0778ae8517e336f527f5b1b8e717ece0e1d76 Mon Sep 17 00:00:00 2001 From: Eva Jin Date: Sun, 15 Feb 2026 19:25:38 -0500 Subject: [PATCH 03/18] Update Makefile --- info.yaml | 10 +++++++++- test/Makefile | 10 +++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/info.yaml b/info.yaml index 5f0aa4d..b2f7d7c 100644 --- a/info.yaml +++ b/info.yaml @@ -17,7 +17,15 @@ project: # Source files must be in ./src and you must list each source file separately, one per line. # Don't forget to also update `PROJECT_SOURCES` in test/Makefile. source_files: - - "control_top.v" + - "aes_fsm.v" + - "bus_arbiter.v" + - "comp_queue.v" + - "deserializer.v" + - "req_queue.v" + - "scoreboard.v" + - "serializer.v" + - "sha_fsm.v" + - "tt_um_control_top.v" # The pinout of your project. Leave unused pins blank. DO NOT delete or add any pins. # This section is for the datasheet/website. Use descriptive names (e.g., RX, TX, MOSI, SCL, SEG_A, etc.). diff --git a/test/Makefile b/test/Makefile index bb64345..ce4b930 100644 --- a/test/Makefile +++ b/test/Makefile @@ -5,7 +5,15 @@ SIM ?= icarus TOPLEVEL_LANG ?= verilog SRC_DIR = $(PWD)/../src -PROJECT_SOURCES = project.v +PROJECT_SOURCES = aes_fsm.v \ + bus_arbiter.v \ + comp_queue.v \ + deserializer.v \ + req_queue.v \ + scoreboard.v \ + serializer.v \ + sha_fsm.v \ + tt_um_control_top.v ifneq ($(GATES),yes) From 12c99d06fad3fc5405c0e79a3eba14dc6e24afcb Mon Sep 17 00:00:00 2001 From: Eva Jin Date: Sun, 15 Feb 2026 19:28:46 -0500 Subject: [PATCH 04/18] Update module name --- src/tt_um_control_top.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tt_um_control_top.v b/src/tt_um_control_top.v index 44933bd..becf195 100644 --- a/src/tt_um_control_top.v +++ b/src/tt_um_control_top.v @@ -5,7 +5,7 @@ `default_nettype none -module control_top #( +module tt_um_control_top #( parameter ADDRW = 24, parameter OPCODEW = 2, parameter REQ_QDEPTH = 4, From 6c876847105aca771f92caea86e0dfecad01a3c0 Mon Sep 17 00:00:00 2001 From: Eva Jin Date: Sun, 15 Feb 2026 20:12:24 -0500 Subject: [PATCH 05/18] Fix lint --- README.md | 10 ++++++++ package-lock.json | 12 ++++++++++ package.json | 10 ++++++++ src/comp_queue.v | 11 ++++++--- src/deserializer.v | 15 ++++++------ src/req_queue.v | 51 +++++++++++++++++++++++------------------ src/serializer.v | 18 ++++++++------- src/sha_fsm.v | 4 ++-- src/tt_um_control_top.v | 12 ++++++---- 9 files changed, 96 insertions(+), 47 deletions(-) create mode 100644 package-lock.json create mode 100644 package.json diff --git a/README.md b/README.md index 68ba6ed..13ed997 100644 --- a/README.md +++ b/README.md @@ -39,3 +39,13 @@ The GitHub action will automatically build the ASIC files using [OpenLane](https - LinkedIn [#tinytapeout](https://www.linkedin.com/search/results/content/?keywords=%23tinytapeout) [@TinyTapeout](https://www.linkedin.com/company/100708654/) - Mastodon [#tinytapeout](https://chaos.social/tags/tinytapeout) [@matthewvenn](https://chaos.social/@matthewvenn) - X (formerly Twitter) [#tinytapeout](https://twitter.com/hashtag/tinytapeout) [@tinytapeout](https://twitter.com/tinytapeout) + +## Linting (developer) + +Add convenience scripts for linting Verilog with `verilator` and `yosys`. + +- **Run lint:** `npm run lint` (requires `verilator` and `yosys` on PATH) +- **Verilator only:** `npm run lint:verilator` +- **Yosys only:** `npm run lint:yosys` + +Note: these scripts assume `verilator` and `yosys` are installed on your system. They do not install those tools. diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..17318ad --- /dev/null +++ b/package-lock.json @@ -0,0 +1,12 @@ +{ + "name": "control-group", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "control-group", + "version": "0.1.0" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..301c51f --- /dev/null +++ b/package.json @@ -0,0 +1,10 @@ +{ + "name": "control-group", + "version": "0.1.0", + "private": true, + "scripts": { + "lint:verilator": "verilator --lint-only --top-module tt_um_control_top src/*.v", + "lint:yosys": "yosys -p \"read_verilog src/*.v; hierarchy -check; proc; stat\"", + "lint": "npm run lint:verilator && npm run lint:yosys" + } +} diff --git a/src/comp_queue.v b/src/comp_queue.v index fbef25e..c114639 100644 --- a/src/comp_queue.v +++ b/src/comp_queue.v @@ -25,7 +25,9 @@ module comp_queue #( // Internal FIFO reg [ADDRW-1:0] mem [0:QDEPTH-1]; - reg [$clog2(QDEPTH)-1:0] head, tail; + localparam integer IDXW = $clog2(QDEPTH); + reg [31:0] head, tail; // widened to 32 bits to avoid width-expansion warnings + wire [31:0] LAST_IDX = QDEPTH - 1; reg [$clog2(QDEPTH+1)-1:0] count; wire full = (count == QDEPTH); @@ -73,7 +75,9 @@ module comp_queue #( // Enqueue logic if (enq_valid && enq_ready) begin mem[tail] <= enq_data; - tail <= (tail + 1) % QDEPTH; + // avoid modulo on mixed widths to prevent WIDTHTRUNC warnings + if (tail == LAST_IDX) tail <= 0; + else tail <= tail + 1; count <= count + 1; end @@ -84,7 +88,8 @@ module comp_queue #( // Dequeue logic if (deq_valid && ready_in) begin data_out <= mem[head]; - head <= (head + 1) % QDEPTH; + if (head == LAST_IDX) head <= 0; + else head <= head + 1; count <= count - 1; end diff --git a/src/deserializer.v b/src/deserializer.v index d28e15c..7808f53 100644 --- a/src/deserializer.v +++ b/src/deserializer.v @@ -38,8 +38,9 @@ module deserializer #( end end endfunction - localparam integer SHIFT_W = 1 + OPCODEW + (3 * ADDRW); - localparam integer CW = clog2(SHIFT_W + 1); + localparam integer SHIFT_W = 1 + OPCODEW + (3 * ADDRW); + localparam integer CW = clog2(SHIFT_W + 1); + localparam integer CNT_FULL = SHIFT_W - 1; //Synchronize reg [1:0] r_clk; @@ -63,13 +64,13 @@ module deserializer #( wire cs_active = ~r_cs_n[1]; // active-low CS wire mosi_s = r_mosi[1]; - reg [CW-1:0] cnt; // how many bits of current word have been collected + reg [31:0] cnt; // how many bits of current word have been collected (widened to avoid width warnings) reg [SHIFT_W-1:0] shift_reg; reg busy; // when pending_valid == 1, ignore new incoming bits always @ (posedge clk or negedge rst_n) begin if (!rst_n) begin // Active-low reset - cnt <= {CW{1'b0}}; + cnt <= 32'd0; shift_reg <= {SHIFT_W{1'b0}}; busy <= 1'b0; valid <= 1'b0; @@ -86,9 +87,9 @@ module deserializer #( if (clk_posedge && !busy) begin // shift in data shift_reg <= {shift_reg[SHIFT_W-2:0], r_mosi[1]}; - if (cnt == (SHIFT_W-1)) begin + if (cnt == CNT_FULL) begin busy <= 1'b1; // full word captured - cnt <= {CW{1'b0}}; + cnt <= 32'd0; end else begin cnt <= cnt + 1'b1; // increment count end @@ -96,7 +97,7 @@ module deserializer #( end else begin // on de-assertion, clear partial word if (!busy) begin - cnt <= {CW{1'b0}}; + cnt <= 32'd0; shift_reg <= {SHIFT_W{1'b0}}; end end diff --git a/src/req_queue.v b/src/req_queue.v index 40c52a5..bda92e6 100644 --- a/src/req_queue.v +++ b/src/req_queue.v @@ -22,18 +22,19 @@ module req_queue #( output wire ready_out_sha ); + integer i; + function integer clog2; input integer value; - integer v, i; + integer v, k; begin v = value - 1; - for (i = 0; v > 0; i = i + 1) v = v >> 1; - clog2 = (value <= 1) ? 1 : i; + for (k = 0; v > 0; k = k + 1) v = v >> 1; + clog2 = (value <= 1) ? 1 : k; end endfunction initial begin - integer i; $dumpfile("tb.vcd"); for (i = 0; i < QDEPTH; i = i + 1) $dumpvars(0, aesQueue[i]); for (i = 0; i < QDEPTH; i = i + 1) $dumpvars(0, shaQueue[i]); @@ -42,51 +43,57 @@ module req_queue #( localparam integer SHA_INSTRW = 2 * ADDRW + OPCODEW; localparam integer AES_INSTRW = 3 * ADDRW + OPCODEW; localparam integer IDXW = clog2(QDEPTH); + localparam integer LAST_IDX = QDEPTH - 1; reg [AES_INSTRW - 1:0] aesQueue [QDEPTH - 1:0]; - reg [IDXW - 1:0] aesReadIdx; - reg [IDXW - 1:0] aesWriteIdx; + reg [31:0] aesReadIdx; + reg [31:0] aesWriteIdx; reg aesFull; reg [SHA_INSTRW - 1:0] shaQueue [QDEPTH - 1:0]; - reg [IDXW - 1:0] shaReadIdx; - reg [IDXW - 1:0] shaWriteIdx; + reg [31:0] shaReadIdx; + reg [31:0] shaWriteIdx; reg shaFull; assign ready_out_aes = (aesReadIdx != aesWriteIdx || !aesFull) && rst_n; assign ready_out_sha = (shaReadIdx != shaWriteIdx || !shaFull) && rst_n; assign valid_out_aes = (aesReadIdx != aesWriteIdx || aesFull) && rst_n; - assign valid_out_sha = (shaReadIdx != shaWriteIdx || shaFull) && rst_n; assign instr_aes = aesQueue[aesReadIdx]; assign instr_sha = shaQueue[shaReadIdx]; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin - integer i; for (i = 0; i < QDEPTH; i = i + 1) aesQueue[i] <= {AES_INSTRW{1'b0}}; - aesReadIdx <= {IDXW{1'b0}}; - aesWriteIdx <= {IDXW{1'b0}}; + aesReadIdx <= 32'd0; + aesWriteIdx <= 32'd0; aesFull <= 0; for (i = 0; i < QDEPTH; i = i + 1) shaQueue[i] <= {SHA_INSTRW{1'b0}}; - shaReadIdx <= {IDXW{1'b0}}; - shaWriteIdx <= {IDXW{1'b0}}; + shaReadIdx <= 32'd0; + shaWriteIdx <= 32'd0; shaFull <= 0; end else begin if (valid_in) begin if (ready_out_aes) begin if (opcode[0] == 0) begin - aesQueue[aesWriteIdx] <= {opcode, key_addr, text_addr, dest_addr}; - aesWriteIdx <= (aesWriteIdx + 1) % QDEPTH; - if (aesReadIdx == (aesWriteIdx + 1) % QDEPTH) begin - aesFull <= 1; - end + aesQueue[aesWriteIdx] <= {opcode, key_addr, text_addr, dest_addr}; + // compute next index without using % to avoid width warnings + if (aesWriteIdx == LAST_IDX) begin + if (aesReadIdx == 0) aesFull <= 1; + aesWriteIdx <= 0; + end else begin + if (aesReadIdx == aesWriteIdx + 1) aesFull <= 1; + aesWriteIdx <= aesWriteIdx + 1; + end end end if (ready_out_sha) begin if (opcode[0] == 1) begin shaQueue[shaWriteIdx] <= {opcode, text_addr, dest_addr}; - shaWriteIdx <= (shaWriteIdx + 1) % QDEPTH; - if (shaReadIdx == (shaWriteIdx + 1) % QDEPTH) begin - shaFull <= 1; + if (shaWriteIdx == LAST_IDX) begin + if (shaReadIdx == 0) shaFull <= 1; + shaWriteIdx <= 0; + end else begin + if (shaReadIdx == shaWriteIdx + 1) shaFull <= 1; + shaWriteIdx <= shaWriteIdx + 1; end end end diff --git a/src/serializer.v b/src/serializer.v index c6be4c4..cffbe24 100644 --- a/src/serializer.v +++ b/src/serializer.v @@ -23,11 +23,13 @@ module serializer #( end endfunction - localparam integer SHIFT_W = ADDRW; - localparam integer CW = clog2(SHIFT_W + 1); //addrw + valid width + localparam integer SHIFT_W = ADDRW + 1; // include valid bit + addr + localparam integer CW = clog2(SHIFT_W + 1); // count width - reg [CW-1:0] cnt; //count reg - reg [SHIFT_W-1:0] PISOreg; //ASSUMES 25 -> [VALID][ADDRW] -> 0, left shift + localparam integer CNT_INIT = SHIFT_W - 1; + + reg [31:0] cnt; //count reg (widened to avoid width warnings) + reg [SHIFT_W-1:0] PISOreg; // [VALID][ADDRW] reg [1:0] clkstat; //clock for spi wire negedgeSPI = (clkstat == 2'b10); //detect edge @@ -83,7 +85,7 @@ module serializer #( always @(posedge clk or negedge rst_n) begin if (!rst_n) begin ready_out <= 1; - cnt <= (SHIFT_W-1); + cnt <= CNT_INIT; PISOreg <= 0; miso <= 1'b0; err <= 1'b0; @@ -92,11 +94,11 @@ module serializer #( if (valid_in && ready_out == 1 && negedgeSPI) begin PISOreg <= {1'b1 , addr}; ready_out <= 0; - cnt <= (SHIFT_W-1); + cnt <= CNT_INIT; miso <= 1'b1; end else if (negedgeSPI && !ready_out) begin miso <= PISOreg[SHIFT_W-1]; - PISOreg <= {PISOreg[SHIFT_W-1:0], 1'b0}; + PISOreg <= {PISOreg[SHIFT_W-2:0], 1'b0}; if (cnt != 1) begin cnt <= cnt - 1; @@ -110,7 +112,7 @@ module serializer #( end else if (valid_ncs && !ready_out) begin //ncs goes high while ready_out still ongoing, clear error state and raise flag err <= 1'b1; ready_out <= 1; - cnt <= (SHIFT_W-1); + cnt <= CNT_INIT; PISOreg <= 0; miso <= 1'b0; end else begin diff --git a/src/sha_fsm.v b/src/sha_fsm.v index 25db9c5..da00f50 100644 --- a/src/sha_fsm.v +++ b/src/sha_fsm.v @@ -147,11 +147,11 @@ module sha_fsm #( HASHOP: begin arb_req = 1'b1; - data_out = {24'b0, r_req_data[73], 1'b0, ACCEL_ID, 4'b0011}; + data_out = {24'b0, r_req_data[2*ADDRW+1], 1'b0, ACCEL_ID, 4'b0011}; end WAIT_HASHOP: begin - data_out = {24'b0, r_req_data[73], 1'b0, ACCEL_ID, 4'b0011}; + data_out = {24'b0, r_req_data[2*ADDRW+1], 1'b0, ACCEL_ID, 4'b0011}; end MEMWR: begin diff --git a/src/tt_um_control_top.v b/src/tt_um_control_top.v index becf195..1117894 100644 --- a/src/tt_um_control_top.v +++ b/src/tt_um_control_top.v @@ -37,12 +37,12 @@ module tt_um_control_top #( deserializer #(.ADDRW(ADDRW), .OPCODEW(OPCODEW)) deserializer_inst(.clk(clk), .rst_n(rst_n), .spi_clk(spi_clk), .mosi(mosi), .cs_n(cs_n), .aes_ready_in(aes_queue_ready), .sha_ready_in(sha_queue_ready), .valid(valid), .opcode(opcode), .key_addr(key_addr), .text_addr(text_addr), .dest_addr(dest_addr), .valid_out(req_q_valid)); wire aes_fsm_ready, sha_fsm_ready; - wire [AES_INSTRW] instr_aes; - wire [SHA_INSTRW] instr_sha; + wire [AES_INSTRW-1:0] instr_aes; + wire [SHA_INSTRW-1:0] instr_sha; wire valid_out_aes, valid_out_sha; wire aes_queue_ready, sha_queue_ready; // May need to change deserializer so that it holds instruction until req_queue is ready for aes or sha - req_queue #(.ADDRW(ADDRW) .OPCODEW(OPCODEW), .QDEPTH(REQ_QDEPTH)) req_queue_inst(.clk(clk), .rst_n(rst_n), .valid_in(req_q_valid), .ready_in_aes(aes_fsm_ready), .ready_in_sha(sha_fsm_ready), .opcode(opcode), .key_addr(key_addr), .text_addr(text_addr), .dest_addr(dest_addr), .instr_aes(instr_aes), .valid_out_aes(valid_out_aes), .ready_out_aes(aes_queue_ready), .instr_sha(instr_sha), .valid_out_sha(valid_out_sha), .ready_out_sha(sha_queue_ready)); + req_queue #(.ADDRW(ADDRW), .OPCODEW(OPCODEW), .QDEPTH(REQ_QDEPTH)) req_queue_inst(.clk(clk), .rst_n(rst_n), .valid_in(req_q_valid), .ready_in_aes(aes_fsm_ready), .ready_in_sha(sha_fsm_ready), .opcode(opcode), .key_addr(key_addr), .text_addr(text_addr), .dest_addr(dest_addr), .instr_aes(instr_aes), .valid_out_aes(valid_out_aes), .ready_out_aes(aes_queue_ready), .instr_sha(instr_sha), .valid_out_sha(valid_out_sha), .ready_out_sha(sha_queue_ready)); wire compq_ready_aes, compq_ready_sha; wire [ADDRW-1:0] compq_aes_data, compq_sha_data; @@ -51,9 +51,11 @@ module tt_um_control_top #( sha_fsm #(.ADDRW(ADDRW)) sha_fsm_inst (.clk(clk), .rst_n(rst_n), .req_valid(valid_out_sha), .req_data(instr_sha), .ready_req_out(sha_fsm_ready), .compq_ready_in(compq_ready_sha), .compq_data_out(compq_sha_data), .valid_compq_out(compq_sha_valid), .arb_req(sha_arb_req), .arb_grant(sha_arb_grant), .ack_in(ack_in), .data_out(sha_fsm_data)); wire aes_arb_req, sha_arb_req; - wire [7:0] aes_fsm_data, sha_fsm_data; + wire [ADDRW+7:0] aes_fsm_data, sha_fsm_data; wire aes_arb_grant, sha_arb_grant; - bus_arbiter #(.ADDRW(ADDRW)) bus_arbiter_inst (.clk(clk), .rst_n(rst_n), .sha_req(sha_arb_req), .aes_req(aes_arb_req), .sha_data_in(sha_fsm_data), .aes_data_in(aes_fsm_data), .bus_ready(bus_ready), .data_out(data_bus_out), .valid_out(data_bus_valid), .aes_grant(aes_arb_grant), .sha_grant(sha_arb_grant)); + wire [1:0] curr_mode_top; + wire [1:0] counter_top; + bus_arbiter #(.ADDRW(ADDRW)) bus_arbiter_inst (.clk(clk), .rst_n(rst_n), .sha_req(sha_arb_req), .aes_req(aes_arb_req), .sha_data_in(sha_fsm_data), .aes_data_in(aes_fsm_data), .bus_ready(bus_ready), .data_out(data_bus_out), .valid_out(data_bus_valid), .aes_grant(aes_arb_grant), .sha_grant(sha_arb_grant), .curr_mode_top(curr_mode_top), .counter_top(counter_top)); wire [ADDRW-1:0] compq_data; wire compq_valid_out; From e4fb2985446a93089e9055ebf6ab8e9dd972e2b5 Mon Sep 17 00:00:00 2001 From: Eva Jin Date: Sun, 15 Feb 2026 20:22:08 -0500 Subject: [PATCH 06/18] Ignore local run docs and helper script (keep local copies) --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 2a0d890..4dd268a 100644 --- a/.gitignore +++ b/.gitignore @@ -32,4 +32,6 @@ queue_test/tb.gtkw # testbench output related only sim.out -output.log \ No newline at end of file +output.log +docs/LOCAL_RUN.md +scripts/run_tt_docker.sh \ No newline at end of file From 27a028294e7a655ec185e1977de4a853f852aee1 Mon Sep 17 00:00:00 2001 From: Eva Jin Date: Sun, 15 Feb 2026 21:14:51 -0500 Subject: [PATCH 07/18] Added uio_in/uio_out/uio_oe --- src/tt_um_control_top.v | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/tt_um_control_top.v b/src/tt_um_control_top.v index 1117894..2a9d702 100644 --- a/src/tt_um_control_top.v +++ b/src/tt_um_control_top.v @@ -17,6 +17,7 @@ module tt_um_control_top #( input wire clk, // clock input wire spi_clk, input wire rst_n, // reset_n - low to reset +<<<<<<< Updated upstream input wire cs_n, input wire [2:0] ack_in, input wire bus_ready, @@ -25,6 +26,38 @@ module tt_um_control_top #( output reg data_bus_valid ); +======= + input wire [7:0] ui_in, // legacy dedicated inputs + output wire [7:0] uo_out, // legacy dedicated outputs + input wire [7:0] uio_in, // user IOs: [0]=mosi, [1]=spi_clk, [2]=cs_n, [3]=bus_ready + output wire [7:0] uio_out, // user IOs: outputs + output wire [7:0] uio_oe // user IOs: output enable (1=output) +); + + // unify input buses (support both dedicated and IO-style ports) + wire [7:0] in_bus = ui_in | uio_in; + wire mosi = in_bus[0]; + wire spi_clk = in_bus[1]; + wire cs_n = in_bus[2]; + wire bus_ready = in_bus[3]; + wire [2:0] ack_in = in_bus[6:4]; // ACK signals + + // Internal signals (will be mapped to uo_out) + wire miso; + wire [7:0] data_bus_out; + wire data_bus_valid; + + // drive both legacy and IO outputs + wire [7:0] out_bus; + assign out_bus[0] = miso; + assign out_bus[6:1] = data_bus_out[6:1]; + assign out_bus[7] = data_bus_valid; + + assign uio_out = out_bus; + assign uo_out = out_bus; + assign uio_oe = 8'b0; + +>>>>>>> Stashed changes localparam AES_INSTRW = 3*ADDRW + OPCODEW; localparam SHA_INSTRW = 2*ADDRW + OPCODEW; From 0172709409133c9c790e0d275d1dce260cab042b Mon Sep 17 00:00:00 2001 From: Eva Jin Date: Sun, 15 Feb 2026 21:17:15 -0500 Subject: [PATCH 08/18] Added IO inputs and outputs --- src/tt_um_control_top.v | 31 ++++++++----------------------- 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/src/tt_um_control_top.v b/src/tt_um_control_top.v index 2a9d702..e6c640d 100644 --- a/src/tt_um_control_top.v +++ b/src/tt_um_control_top.v @@ -11,30 +11,17 @@ module tt_um_control_top #( parameter REQ_QDEPTH = 4, parameter COMP_QDEPTH = 4 ) ( - output wire miso, - input wire mosi, input wire ena, // always 1 when the design is powered, so you can ignore it input wire clk, // clock - input wire spi_clk, input wire rst_n, // reset_n - low to reset -<<<<<<< Updated upstream - input wire cs_n, - input wire [2:0] ack_in, - input wire bus_ready, - - output reg [7:0] data_bus_out, - output reg data_bus_valid -); - -======= - input wire [7:0] ui_in, // legacy dedicated inputs - output wire [7:0] uo_out, // legacy dedicated outputs - input wire [7:0] uio_in, // user IOs: [0]=mosi, [1]=spi_clk, [2]=cs_n, [3]=bus_ready - output wire [7:0] uio_out, // user IOs: outputs - output wire [7:0] uio_oe // user IOs: output enable (1=output) + input wire [7:0] ui_in, + output wire [7:0] uo_out, + input wire [7:0] uio_in, // [0]=mosi, [1]=spi_clk, [2]=cs_n, [3]=bus_ready + output wire [7:0] uio_out, + output wire [7:0] uio_oe // output enable (1=output) ); - // unify input buses (support both dedicated and IO-style ports) + // input wire [7:0] in_bus = ui_in | uio_in; wire mosi = in_bus[0]; wire spi_clk = in_bus[1]; @@ -42,12 +29,12 @@ module tt_um_control_top #( wire bus_ready = in_bus[3]; wire [2:0] ack_in = in_bus[6:4]; // ACK signals - // Internal signals (will be mapped to uo_out) + // internal signals (will be mapped to uo_out) wire miso; wire [7:0] data_bus_out; wire data_bus_valid; - // drive both legacy and IO outputs + // outputs wire [7:0] out_bus; assign out_bus[0] = miso; assign out_bus[6:1] = data_bus_out[6:1]; @@ -56,8 +43,6 @@ module tt_um_control_top #( assign uio_out = out_bus; assign uo_out = out_bus; assign uio_oe = 8'b0; - ->>>>>>> Stashed changes localparam AES_INSTRW = 3*ADDRW + OPCODEW; localparam SHA_INSTRW = 2*ADDRW + OPCODEW; From 41631a077278bda28fbfbb5c58a47d96b6aade11 Mon Sep 17 00:00:00 2001 From: Eva Jin Date: Sun, 15 Feb 2026 21:25:43 -0500 Subject: [PATCH 09/18] More lint fixes --- src/comp_queue.v | 6 +++++- src/req_queue.v | 1 + src/tt_um_control_top.v | 4 ++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/comp_queue.v b/src/comp_queue.v index c114639..1c48ed6 100644 --- a/src/comp_queue.v +++ b/src/comp_queue.v @@ -18,10 +18,12 @@ module comp_queue #( ); // VCD dump for simulation +`ifndef SYNTHESIS initial begin $dumpfile("tb.vcd"); $dumpvars(0, comp_queue); end +`endif // Internal FIFO reg [ADDRW-1:0] mem [0:QDEPTH-1]; @@ -66,11 +68,13 @@ module comp_queue #( valid_out <= 0; data_out <= 0; end else begin - // Debug output around failing cycle + // Debug output around failing cycle (simulation only) +`ifndef SYNTHESIS if ($time >= 2250000 && $time <= 2290000) begin $display("[%0t] rr_select=%0b | valid_in_aes=%b valid_in_sha=%b | aes_sel=%b sha_sel=%b | enq_valid=%b enq_ready=%b | count=%0d | tail=%0d", $time, rr_select, valid_in_aes, valid_in_sha, aes_sel, sha_sel, enq_valid, enq_ready, count, tail); end +`endif // Enqueue logic if (enq_valid && enq_ready) begin diff --git a/src/req_queue.v b/src/req_queue.v index bda92e6..6ed7d5b 100644 --- a/src/req_queue.v +++ b/src/req_queue.v @@ -57,6 +57,7 @@ module req_queue #( assign ready_out_aes = (aesReadIdx != aesWriteIdx || !aesFull) && rst_n; assign ready_out_sha = (shaReadIdx != shaWriteIdx || !shaFull) && rst_n; assign valid_out_aes = (aesReadIdx != aesWriteIdx || aesFull) && rst_n; + assign valid_out_sha = (shaReadIdx != shaWriteIdx || shaFull) && rst_n; assign instr_aes = aesQueue[aesReadIdx]; assign instr_sha = shaQueue[shaReadIdx]; diff --git a/src/tt_um_control_top.v b/src/tt_um_control_top.v index e6c640d..c9672fb 100644 --- a/src/tt_um_control_top.v +++ b/src/tt_um_control_top.v @@ -79,6 +79,6 @@ module tt_um_control_top #( wire compq_valid_out; wire compq_ready_in; comp_queue #(.ADDRW(ADDRW), .QDEPTH(COMP_QDEPTH)) comp_queue_inst (.clk(clk), .rst_n(rst_n), .valid_in_aes(compq_aes_valid), .valid_in_sha(compq_sha_valid), .dest_addr_aes(compq_aes_data), .dest_addr_sha(compq_sha_data), .ready_out_aes(compq_ready_aes), .ready_out_sha(compq_ready_sha), .data_out(compq_data), .valid_out(compq_valid_out), .ready_in(compq_ready_in)); - - serializer #(.ADDRW(ADDRW)) serializer_inst(.clk(clk), .rst_n(rst_n), .n_cs(cs_n), .spi_clk(spi_clk), .valid_in(compq_valid_out), .addr(compq_data), .miso(miso), .ready_out(compq_ready_in), .err()); + wire serializer_err; + serializer #(.ADDRW(ADDRW)) serializer_inst(.clk(clk), .rst_n(rst_n), .n_cs(cs_n), .spi_clk(spi_clk), .valid_in(compq_valid_out), .addr(compq_data), .miso(miso), .ready_out(compq_ready_in), .err(serializer_err)); endmodule From 3242a5efdfc2943593604e667949cd9b71d7d0f2 Mon Sep 17 00:00:00 2001 From: Eva Jin Date: Sun, 15 Feb 2026 21:52:24 -0500 Subject: [PATCH 10/18] More lint fixes --- src/aes_fsm.v | 4 ++-- src/comp_queue.v | 4 +--- src/deserializer.v | 34 +++++++--------------------------- src/req_queue.v | 11 ----------- src/serializer.v | 11 ----------- src/tt_um_control_top.v | 2 +- 6 files changed, 11 insertions(+), 55 deletions(-) diff --git a/src/aes_fsm.v b/src/aes_fsm.v index 3112221..3bc8f6f 100644 --- a/src/aes_fsm.v +++ b/src/aes_fsm.v @@ -162,10 +162,10 @@ module aes_fsm #( end HASHOP: begin arb_req = 1'b1; - data_out = {24'b0, r_req_data[73], 1'b0, ACCEL_ID, 4'b0011}; + data_out = {24'b0, r_req_data[3*ADDRW+1], (r_req_data[3*ADDRW] & 1'b0), ACCEL_ID, 4'b0011}; end WAIT_HASHOP: begin - data_out = {24'b0, r_req_data[73], 1'b0, ACCEL_ID, 4'b0011}; + data_out = {24'b0, r_req_data[3*ADDRW+1], (r_req_data[3*ADDRW] & 1'b0), ACCEL_ID, 4'b0011}; end MEMWR: begin arb_req = 1'b1; diff --git a/src/comp_queue.v b/src/comp_queue.v index 1c48ed6..52200ea 100644 --- a/src/comp_queue.v +++ b/src/comp_queue.v @@ -27,7 +27,6 @@ module comp_queue #( // Internal FIFO reg [ADDRW-1:0] mem [0:QDEPTH-1]; - localparam integer IDXW = $clog2(QDEPTH); reg [31:0] head, tail; // widened to 32 bits to avoid width-expansion warnings wire [31:0] LAST_IDX = QDEPTH - 1; reg [$clog2(QDEPTH+1)-1:0] count; @@ -57,7 +56,6 @@ module comp_queue #( end wire deq_valid = !empty; - wire deq_ready = ready_in && valid_out; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin @@ -102,4 +100,4 @@ module comp_queue #( end end -endmodule \ No newline at end of file +endmodule diff --git a/src/deserializer.v b/src/deserializer.v index 7808f53..93a196a 100644 --- a/src/deserializer.v +++ b/src/deserializer.v @@ -4,7 +4,7 @@ module deserializer #( parameter ADDRW = 24, parameter OPCODEW = 2 ) ( - //INPUTS: clk, rst_n, spi_clk, mosi, cs_n, aes_ready_in, sha_ready_in + // INPUTS: clk, rst_n, spi_clk, mosi, cs_n, aes_ready_in, sha_ready_in input wire clk, input wire rst_n, input wire spi_clk, @@ -12,7 +12,7 @@ module deserializer #( input wire cs_n, input wire aes_ready_in, input wire sha_ready_in, - //OUTPUTS: opcode[1:0], key_addr[ADDRW-1:0], text_addr[ADDRW-1:0], valid_out + // OUTPUTS: opcode[1:0], key_addr[ADDRW-1:0], text_addr[ADDRW-1:0], valid_out output reg valid, output reg [OPCODEW-1:0] opcode, output reg [ADDRW-1:0] key_addr, @@ -21,35 +21,17 @@ module deserializer #( output reg valid_out ); - function integer clog2; - input integer value; - integer v, n; // <-- declare n - begin - if (value <= 1) begin - clog2 = 1; - end else begin - v = value - 1; - n = 0; - while (v > 0) begin - v = v >> 1; - n = n + 1; - end - clog2 = n; - end - end - endfunction localparam integer SHIFT_W = 1 + OPCODEW + (3 * ADDRW); - localparam integer CW = clog2(SHIFT_W + 1); localparam integer CNT_FULL = SHIFT_W - 1; - //Synchronize + // synchronize reg [1:0] r_clk; reg [1:0] r_cs_n; reg [1:0] r_mosi; always @(posedge clk or negedge rst_n) begin - if (!rst_n) begin // Changed to active-low reset - r_clk <= 2'b00; // Changed from 3'b00 + if (!rst_n) begin // active-low reset + r_clk <= 2'b00; r_cs_n <= 2'b11; r_mosi <= 2'b00; end else begin @@ -59,10 +41,8 @@ module deserializer #( end end - //Shift Data + // shift data wire clk_posedge = (r_clk == 2'b01); // detected posedge of spi_clk (0->1) - wire cs_active = ~r_cs_n[1]; // active-low CS - wire mosi_s = r_mosi[1]; reg [31:0] cnt; // how many bits of current word have been collected (widened to avoid width warnings) reg [SHIFT_W-1:0] shift_reg; @@ -129,4 +109,4 @@ module deserializer #( end end -endmodule \ No newline at end of file +endmodule diff --git a/src/req_queue.v b/src/req_queue.v index 6ed7d5b..a5233f9 100644 --- a/src/req_queue.v +++ b/src/req_queue.v @@ -24,16 +24,6 @@ module req_queue #( integer i; - function integer clog2; - input integer value; - integer v, k; - begin - v = value - 1; - for (k = 0; v > 0; k = k + 1) v = v >> 1; - clog2 = (value <= 1) ? 1 : k; - end - endfunction - initial begin $dumpfile("tb.vcd"); for (i = 0; i < QDEPTH; i = i + 1) $dumpvars(0, aesQueue[i]); @@ -42,7 +32,6 @@ module req_queue #( localparam integer SHA_INSTRW = 2 * ADDRW + OPCODEW; localparam integer AES_INSTRW = 3 * ADDRW + OPCODEW; - localparam integer IDXW = clog2(QDEPTH); localparam integer LAST_IDX = QDEPTH - 1; reg [AES_INSTRW - 1:0] aesQueue [QDEPTH - 1:0]; diff --git a/src/serializer.v b/src/serializer.v index cffbe24..a6b0b3d 100644 --- a/src/serializer.v +++ b/src/serializer.v @@ -13,18 +13,7 @@ module serializer #( output reg ready_out, output reg err //Error flag. Deserializer must reject collected data within txn ); - function integer clog2; - input integer value; - integer v, i; - begin - v = value - 1; - for (i = 0; v > 0; i = i + 1) v = v >> 1; - clog2 = (value <= 1) ? 1 : i; - end - endfunction - localparam integer SHIFT_W = ADDRW + 1; // include valid bit + addr - localparam integer CW = clog2(SHIFT_W + 1); // count width localparam integer CNT_INIT = SHIFT_W - 1; diff --git a/src/tt_um_control_top.v b/src/tt_um_control_top.v index c9672fb..2ffac83 100644 --- a/src/tt_um_control_top.v +++ b/src/tt_um_control_top.v @@ -42,7 +42,7 @@ module tt_um_control_top #( assign uio_out = out_bus; assign uo_out = out_bus; - assign uio_oe = 8'b0; + assign uio_oe = 8'b0 & {8{&{1'b0, ena, in_bus[7], data_bus_out[7], data_bus_out[0], valid, serializer_err, curr_mode_top, counter_top}}}; localparam AES_INSTRW = 3*ADDRW + OPCODEW; localparam SHA_INSTRW = 2*ADDRW + OPCODEW; From 69376ed83575676b32bda7713c2e8af8e0009912 Mon Sep 17 00:00:00 2001 From: Eva Jin Date: Sun, 15 Feb 2026 22:12:17 -0500 Subject: [PATCH 11/18] Area optimization --- src/comp_queue.v | 23 +++++++++++++---------- src/deserializer.v | 11 ++++++----- src/req_queue.v | 33 ++++++++++++++++++--------------- src/serializer.v | 5 +++-- 4 files changed, 40 insertions(+), 32 deletions(-) diff --git a/src/comp_queue.v b/src/comp_queue.v index 52200ea..f2ac029 100644 --- a/src/comp_queue.v +++ b/src/comp_queue.v @@ -27,12 +27,15 @@ module comp_queue #( // Internal FIFO reg [ADDRW-1:0] mem [0:QDEPTH-1]; - reg [31:0] head, tail; // widened to 32 bits to avoid width-expansion warnings - wire [31:0] LAST_IDX = QDEPTH - 1; - reg [$clog2(QDEPTH+1)-1:0] count; + localparam integer IDXW = (QDEPTH <= 1) ? 1 : $clog2(QDEPTH); + localparam integer COUNTW = (QDEPTH <= 1) ? 1 : $clog2(QDEPTH + 1); + localparam [IDXW-1:0] LAST_IDX = QDEPTH - 1; + localparam [COUNTW-1:0] COUNT_MAX = QDEPTH; + reg [IDXW-1:0] head, tail; + reg [COUNTW-1:0] count; - wire full = (count == QDEPTH); - wire empty = (count == 0); + wire full = (count == COUNT_MAX); + wire empty = (count == {COUNTW{1'b0}}); // Round-robin selector: 0 = AES, 1 = SHA reg rr_select; @@ -59,9 +62,9 @@ module comp_queue #( always @(posedge clk or negedge rst_n) begin if (!rst_n) begin - head <= 0; - tail <= 0; - count <= 0; + head <= {IDXW{1'b0}}; + tail <= {IDXW{1'b0}}; + count <= {COUNTW{1'b0}}; rr_select <= 0; valid_out <= 0; data_out <= 0; @@ -78,7 +81,7 @@ module comp_queue #( if (enq_valid && enq_ready) begin mem[tail] <= enq_data; // avoid modulo on mixed widths to prevent WIDTHTRUNC warnings - if (tail == LAST_IDX) tail <= 0; + if (tail == LAST_IDX) tail <= {IDXW{1'b0}}; else tail <= tail + 1; count <= count + 1; end @@ -90,7 +93,7 @@ module comp_queue #( // Dequeue logic if (deq_valid && ready_in) begin data_out <= mem[head]; - if (head == LAST_IDX) head <= 0; + if (head == LAST_IDX) head <= {IDXW{1'b0}}; else head <= head + 1; count <= count - 1; end diff --git a/src/deserializer.v b/src/deserializer.v index 93a196a..a030596 100644 --- a/src/deserializer.v +++ b/src/deserializer.v @@ -22,7 +22,8 @@ module deserializer #( ); localparam integer SHIFT_W = 1 + OPCODEW + (3 * ADDRW); - localparam integer CNT_FULL = SHIFT_W - 1; + localparam integer CW = (SHIFT_W <= 1) ? 1 : $clog2(SHIFT_W + 1); + localparam [CW-1:0] CNT_FULL = SHIFT_W - 1; // synchronize reg [1:0] r_clk; @@ -44,13 +45,13 @@ module deserializer #( // shift data wire clk_posedge = (r_clk == 2'b01); // detected posedge of spi_clk (0->1) - reg [31:0] cnt; // how many bits of current word have been collected (widened to avoid width warnings) + reg [CW-1:0] cnt; // how many bits of current word have been collected reg [SHIFT_W-1:0] shift_reg; reg busy; // when pending_valid == 1, ignore new incoming bits always @ (posedge clk or negedge rst_n) begin if (!rst_n) begin // Active-low reset - cnt <= 32'd0; + cnt <= {CW{1'b0}}; shift_reg <= {SHIFT_W{1'b0}}; busy <= 1'b0; valid <= 1'b0; @@ -69,7 +70,7 @@ module deserializer #( shift_reg <= {shift_reg[SHIFT_W-2:0], r_mosi[1]}; if (cnt == CNT_FULL) begin busy <= 1'b1; // full word captured - cnt <= 32'd0; + cnt <= {CW{1'b0}}; end else begin cnt <= cnt + 1'b1; // increment count end @@ -77,7 +78,7 @@ module deserializer #( end else begin // on de-assertion, clear partial word if (!busy) begin - cnt <= 32'd0; + cnt <= {CW{1'b0}}; shift_reg <= {SHIFT_W{1'b0}}; end end diff --git a/src/req_queue.v b/src/req_queue.v index a5233f9..5861ef5 100644 --- a/src/req_queue.v +++ b/src/req_queue.v @@ -32,15 +32,16 @@ module req_queue #( localparam integer SHA_INSTRW = 2 * ADDRW + OPCODEW; localparam integer AES_INSTRW = 3 * ADDRW + OPCODEW; - localparam integer LAST_IDX = QDEPTH - 1; + localparam integer IDXW = (QDEPTH <= 1) ? 1 : $clog2(QDEPTH); + localparam [IDXW-1:0] LAST_IDX = QDEPTH - 1; reg [AES_INSTRW - 1:0] aesQueue [QDEPTH - 1:0]; - reg [31:0] aesReadIdx; - reg [31:0] aesWriteIdx; + reg [IDXW-1:0] aesReadIdx; + reg [IDXW-1:0] aesWriteIdx; reg aesFull; reg [SHA_INSTRW - 1:0] shaQueue [QDEPTH - 1:0]; - reg [31:0] shaReadIdx; - reg [31:0] shaWriteIdx; + reg [IDXW-1:0] shaReadIdx; + reg [IDXW-1:0] shaWriteIdx; reg shaFull; assign ready_out_aes = (aesReadIdx != aesWriteIdx || !aesFull) && rst_n; @@ -53,12 +54,12 @@ module req_queue #( always @(posedge clk or negedge rst_n) begin if (!rst_n) begin for (i = 0; i < QDEPTH; i = i + 1) aesQueue[i] <= {AES_INSTRW{1'b0}}; - aesReadIdx <= 32'd0; - aesWriteIdx <= 32'd0; + aesReadIdx <= {IDXW{1'b0}}; + aesWriteIdx <= {IDXW{1'b0}}; aesFull <= 0; for (i = 0; i < QDEPTH; i = i + 1) shaQueue[i] <= {SHA_INSTRW{1'b0}}; - shaReadIdx <= 32'd0; - shaWriteIdx <= 32'd0; + shaReadIdx <= {IDXW{1'b0}}; + shaWriteIdx <= {IDXW{1'b0}}; shaFull <= 0; end else begin if (valid_in) begin @@ -67,8 +68,8 @@ module req_queue #( aesQueue[aesWriteIdx] <= {opcode, key_addr, text_addr, dest_addr}; // compute next index without using % to avoid width warnings if (aesWriteIdx == LAST_IDX) begin - if (aesReadIdx == 0) aesFull <= 1; - aesWriteIdx <= 0; + if (aesReadIdx == {IDXW{1'b0}}) aesFull <= 1; + aesWriteIdx <= {IDXW{1'b0}}; end else begin if (aesReadIdx == aesWriteIdx + 1) aesFull <= 1; aesWriteIdx <= aesWriteIdx + 1; @@ -79,8 +80,8 @@ module req_queue #( if (opcode[0] == 1) begin shaQueue[shaWriteIdx] <= {opcode, text_addr, dest_addr}; if (shaWriteIdx == LAST_IDX) begin - if (shaReadIdx == 0) shaFull <= 1; - shaWriteIdx <= 0; + if (shaReadIdx == {IDXW{1'b0}}) shaFull <= 1; + shaWriteIdx <= {IDXW{1'b0}}; end else begin if (shaReadIdx == shaWriteIdx + 1) shaFull <= 1; shaWriteIdx <= shaWriteIdx + 1; @@ -89,11 +90,13 @@ module req_queue #( end end if (ready_in_aes) begin - aesReadIdx <= aesReadIdx + 1; + if (aesReadIdx == LAST_IDX) aesReadIdx <= {IDXW{1'b0}}; + else aesReadIdx <= aesReadIdx + 1; aesFull <= 0; end if (ready_in_sha) begin - shaReadIdx <= shaReadIdx + 1; + if (shaReadIdx == LAST_IDX) shaReadIdx <= {IDXW{1'b0}}; + else shaReadIdx <= shaReadIdx + 1; shaFull <= 0; end end diff --git a/src/serializer.v b/src/serializer.v index a6b0b3d..68ac4ed 100644 --- a/src/serializer.v +++ b/src/serializer.v @@ -15,9 +15,10 @@ module serializer #( ); localparam integer SHIFT_W = ADDRW + 1; // include valid bit + addr - localparam integer CNT_INIT = SHIFT_W - 1; + localparam integer CW = (SHIFT_W <= 1) ? 1 : $clog2(SHIFT_W + 1); + localparam [CW-1:0] CNT_INIT = SHIFT_W - 1; - reg [31:0] cnt; //count reg (widened to avoid width warnings) + reg [CW-1:0] cnt; //count reg reg [SHIFT_W-1:0] PISOreg; // [VALID][ADDRW] reg [1:0] clkstat; //clock for spi wire negedgeSPI = (clkstat == 2'b10); //detect edge From ef5f7af42ec4adbef0474ce08c51af9effa265ee Mon Sep 17 00:00:00 2001 From: Eva Jin Date: Sun, 15 Feb 2026 22:20:33 -0500 Subject: [PATCH 12/18] Lint fixes --- src/comp_queue.v | 2 +- src/deserializer.v | 2 +- src/req_queue.v | 2 +- src/serializer.v | 2 +- src/tt_um_control_top.v | 42 +++++++++++++++++++++++++++++++++-------- 5 files changed, 38 insertions(+), 12 deletions(-) diff --git a/src/comp_queue.v b/src/comp_queue.v index f2ac029..6a78612 100644 --- a/src/comp_queue.v +++ b/src/comp_queue.v @@ -29,7 +29,7 @@ module comp_queue #( reg [ADDRW-1:0] mem [0:QDEPTH-1]; localparam integer IDXW = (QDEPTH <= 1) ? 1 : $clog2(QDEPTH); localparam integer COUNTW = (QDEPTH <= 1) ? 1 : $clog2(QDEPTH + 1); - localparam [IDXW-1:0] LAST_IDX = QDEPTH - 1; + localparam integer LAST_IDX = QDEPTH - 1; localparam [COUNTW-1:0] COUNT_MAX = QDEPTH; reg [IDXW-1:0] head, tail; reg [COUNTW-1:0] count; diff --git a/src/deserializer.v b/src/deserializer.v index a030596..e54ab98 100644 --- a/src/deserializer.v +++ b/src/deserializer.v @@ -23,7 +23,7 @@ module deserializer #( localparam integer SHIFT_W = 1 + OPCODEW + (3 * ADDRW); localparam integer CW = (SHIFT_W <= 1) ? 1 : $clog2(SHIFT_W + 1); - localparam [CW-1:0] CNT_FULL = SHIFT_W - 1; + localparam integer CNT_FULL = SHIFT_W - 1; // synchronize reg [1:0] r_clk; diff --git a/src/req_queue.v b/src/req_queue.v index 5861ef5..778758d 100644 --- a/src/req_queue.v +++ b/src/req_queue.v @@ -33,7 +33,7 @@ module req_queue #( localparam integer SHA_INSTRW = 2 * ADDRW + OPCODEW; localparam integer AES_INSTRW = 3 * ADDRW + OPCODEW; localparam integer IDXW = (QDEPTH <= 1) ? 1 : $clog2(QDEPTH); - localparam [IDXW-1:0] LAST_IDX = QDEPTH - 1; + localparam integer LAST_IDX = QDEPTH - 1; reg [AES_INSTRW - 1:0] aesQueue [QDEPTH - 1:0]; reg [IDXW-1:0] aesReadIdx; diff --git a/src/serializer.v b/src/serializer.v index 68ac4ed..9b25ff6 100644 --- a/src/serializer.v +++ b/src/serializer.v @@ -16,7 +16,7 @@ module serializer #( localparam integer SHIFT_W = ADDRW + 1; // include valid bit + addr localparam integer CW = (SHIFT_W <= 1) ? 1 : $clog2(SHIFT_W + 1); - localparam [CW-1:0] CNT_INIT = SHIFT_W - 1; + localparam integer CNT_INIT = SHIFT_W - 1; reg [CW-1:0] cnt; //count reg reg [SHIFT_W-1:0] PISOreg; // [VALID][ADDRW] diff --git a/src/tt_um_control_top.v b/src/tt_um_control_top.v index 2ffac83..3342a39 100644 --- a/src/tt_um_control_top.v +++ b/src/tt_um_control_top.v @@ -42,7 +42,8 @@ module tt_um_control_top #( assign uio_out = out_bus; assign uo_out = out_bus; - assign uio_oe = 8'b0 & {8{&{1'b0, ena, in_bus[7], data_bus_out[7], data_bus_out[0], valid, serializer_err, curr_mode_top, counter_top}}}; + assign uio_oe = 8'b0 & {8{&{1'b0, ena, in_bus[7], data_bus_out[7], data_bus_out[0], + valid, serializer_err, curr_mode_top, counter_top}}}; localparam AES_INSTRW = 3*ADDRW + OPCODEW; localparam SHA_INSTRW = 2*ADDRW + OPCODEW; @@ -52,7 +53,11 @@ module tt_um_control_top #( wire [ADDRW-1:0] text_addr; wire [ADDRW-1:0] dest_addr; wire req_q_valid; - deserializer #(.ADDRW(ADDRW), .OPCODEW(OPCODEW)) deserializer_inst(.clk(clk), .rst_n(rst_n), .spi_clk(spi_clk), .mosi(mosi), .cs_n(cs_n), .aes_ready_in(aes_queue_ready), .sha_ready_in(sha_queue_ready), .valid(valid), .opcode(opcode), .key_addr(key_addr), .text_addr(text_addr), .dest_addr(dest_addr), .valid_out(req_q_valid)); + deserializer #(.ADDRW(ADDRW), .OPCODEW(OPCODEW)) + deserializer_inst(.clk(clk), .rst_n(rst_n), .spi_clk(spi_clk), .mosi(mosi), .cs_n(cs_n), + .aes_ready_in(aes_queue_ready), .sha_ready_in(sha_queue_ready), + .valid(valid), .opcode(opcode), .key_addr(key_addr), .text_addr(text_addr), + .dest_addr(dest_addr), .valid_out(req_q_valid)); wire aes_fsm_ready, sha_fsm_ready; wire [AES_INSTRW-1:0] instr_aes; @@ -60,25 +65,46 @@ module tt_um_control_top #( wire valid_out_aes, valid_out_sha; wire aes_queue_ready, sha_queue_ready; // May need to change deserializer so that it holds instruction until req_queue is ready for aes or sha - req_queue #(.ADDRW(ADDRW), .OPCODEW(OPCODEW), .QDEPTH(REQ_QDEPTH)) req_queue_inst(.clk(clk), .rst_n(rst_n), .valid_in(req_q_valid), .ready_in_aes(aes_fsm_ready), .ready_in_sha(sha_fsm_ready), .opcode(opcode), .key_addr(key_addr), .text_addr(text_addr), .dest_addr(dest_addr), .instr_aes(instr_aes), .valid_out_aes(valid_out_aes), .ready_out_aes(aes_queue_ready), .instr_sha(instr_sha), .valid_out_sha(valid_out_sha), .ready_out_sha(sha_queue_ready)); + req_queue #(.ADDRW(ADDRW), .OPCODEW(OPCODEW), .QDEPTH(REQ_QDEPTH)) + req_queue_inst(.clk(clk), .rst_n(rst_n), .valid_in(req_q_valid), .ready_in_aes(aes_fsm_ready), + .ready_in_sha(sha_fsm_ready), .opcode(opcode), .key_addr(key_addr), .text_addr(text_addr), + .dest_addr(dest_addr), .instr_aes(instr_aes), .valid_out_aes(valid_out_aes), + .ready_out_aes(aes_queue_ready), .instr_sha(instr_sha), .valid_out_sha(valid_out_sha), + .ready_out_sha(sha_queue_ready)); wire compq_ready_aes, compq_ready_sha; wire [ADDRW-1:0] compq_aes_data, compq_sha_data; wire compq_aes_valid, compq_sha_valid; - aes_fsm #(.ADDRW(ADDRW)) aes_fsm_inst (.clk(clk), .rst_n(rst_n), .req_valid(valid_out_aes), .req_data(instr_aes), .ready_req_out(aes_fsm_ready), .compq_ready_in(compq_ready_aes), .compq_data_out(compq_aes_data), .valid_compq_out(compq_aes_valid), .arb_req(aes_arb_req), .arb_grant(aes_arb_grant), .ack_in(ack_in), .data_out(aes_fsm_data)); - sha_fsm #(.ADDRW(ADDRW)) sha_fsm_inst (.clk(clk), .rst_n(rst_n), .req_valid(valid_out_sha), .req_data(instr_sha), .ready_req_out(sha_fsm_ready), .compq_ready_in(compq_ready_sha), .compq_data_out(compq_sha_data), .valid_compq_out(compq_sha_valid), .arb_req(sha_arb_req), .arb_grant(sha_arb_grant), .ack_in(ack_in), .data_out(sha_fsm_data)); + aes_fsm #(.ADDRW(ADDRW)) aes_fsm_inst (.clk(clk), .rst_n(rst_n), .req_valid(valid_out_aes), + .req_data(instr_aes), .ready_req_out(aes_fsm_ready), + .compq_ready_in(compq_ready_aes), .compq_data_out(compq_aes_data), + .valid_compq_out(compq_aes_valid), .arb_req(aes_arb_req), + .arb_grant(aes_arb_grant), .ack_in(ack_in), .data_out(aes_fsm_data)); + sha_fsm #(.ADDRW(ADDRW)) sha_fsm_inst (.clk(clk), .rst_n(rst_n), .req_valid(valid_out_sha), .req_data(instr_sha), + .ready_req_out(sha_fsm_ready), .compq_ready_in(compq_ready_sha), + .compq_data_out(compq_sha_data), .valid_compq_out(compq_sha_valid), + .arb_req(sha_arb_req), .arb_grant(sha_arb_grant), .ack_in(ack_in), + .data_out(sha_fsm_data)); wire aes_arb_req, sha_arb_req; wire [ADDRW+7:0] aes_fsm_data, sha_fsm_data; wire aes_arb_grant, sha_arb_grant; wire [1:0] curr_mode_top; wire [1:0] counter_top; - bus_arbiter #(.ADDRW(ADDRW)) bus_arbiter_inst (.clk(clk), .rst_n(rst_n), .sha_req(sha_arb_req), .aes_req(aes_arb_req), .sha_data_in(sha_fsm_data), .aes_data_in(aes_fsm_data), .bus_ready(bus_ready), .data_out(data_bus_out), .valid_out(data_bus_valid), .aes_grant(aes_arb_grant), .sha_grant(sha_arb_grant), .curr_mode_top(curr_mode_top), .counter_top(counter_top)); + bus_arbiter #(.ADDRW(ADDRW)) + bus_arbiter_inst (.clk(clk), .rst_n(rst_n), .sha_req(sha_arb_req), .aes_req(aes_arb_req), .sha_data_in(sha_fsm_data), + .aes_data_in(aes_fsm_data), .bus_ready(bus_ready), .data_out(data_bus_out), .valid_out(data_bus_valid), + .aes_grant(aes_arb_grant), .sha_grant(sha_arb_grant), .curr_mode_top(curr_mode_top), .counter_top(counter_top)); wire [ADDRW-1:0] compq_data; wire compq_valid_out; wire compq_ready_in; - comp_queue #(.ADDRW(ADDRW), .QDEPTH(COMP_QDEPTH)) comp_queue_inst (.clk(clk), .rst_n(rst_n), .valid_in_aes(compq_aes_valid), .valid_in_sha(compq_sha_valid), .dest_addr_aes(compq_aes_data), .dest_addr_sha(compq_sha_data), .ready_out_aes(compq_ready_aes), .ready_out_sha(compq_ready_sha), .data_out(compq_data), .valid_out(compq_valid_out), .ready_in(compq_ready_in)); + comp_queue #(.ADDRW(ADDRW), .QDEPTH(COMP_QDEPTH)) + comp_queue_inst (.clk(clk), .rst_n(rst_n), .valid_in_aes(compq_aes_valid), .valid_in_sha(compq_sha_valid), + .dest_addr_aes(compq_aes_data), .dest_addr_sha(compq_sha_data), .ready_out_aes(compq_ready_aes), + .ready_out_sha(compq_ready_sha), .data_out(compq_data), .valid_out(compq_valid_out), .ready_in(compq_ready_in)); wire serializer_err; - serializer #(.ADDRW(ADDRW)) serializer_inst(.clk(clk), .rst_n(rst_n), .n_cs(cs_n), .spi_clk(spi_clk), .valid_in(compq_valid_out), .addr(compq_data), .miso(miso), .ready_out(compq_ready_in), .err(serializer_err)); + serializer #(.ADDRW(ADDRW)) + serializer_inst(.clk(clk), .rst_n(rst_n), .n_cs(cs_n), .spi_clk(spi_clk), .valid_in(compq_valid_out), .addr(compq_data), + .miso(miso), .ready_out(compq_ready_in), .err(serializer_err)); endmodule From 17799eed78b8e40e9c23662a6112479d7c313bd8 Mon Sep 17 00:00:00 2001 From: Eva Jin Date: Sun, 15 Feb 2026 22:27:04 -0500 Subject: [PATCH 13/18] Lint fixes --- info.yaml | 2 +- src/comp_queue.v | 8 +++++++- src/deserializer.v | 8 +++++++- src/req_queue.v | 8 +++++++- src/serializer.v | 8 +++++++- 5 files changed, 29 insertions(+), 5 deletions(-) diff --git a/info.yaml b/info.yaml index b2f7d7c..e39e9d0 100644 --- a/info.yaml +++ b/info.yaml @@ -8,7 +8,7 @@ project: clock_hz: 0 # Clock frequency in Hz (or 0 if not applicable) # How many tiles your design occupies? A single tile is about 167x108 uM. - tiles: "1x1" # Valid values: 1x1, 1x2, 2x2, 3x2, 4x2, 6x2 or 8x2 + tiles: "2x2" # 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_control_top" diff --git a/src/comp_queue.v b/src/comp_queue.v index 6a78612..d919166 100644 --- a/src/comp_queue.v +++ b/src/comp_queue.v @@ -29,7 +29,13 @@ module comp_queue #( reg [ADDRW-1:0] mem [0:QDEPTH-1]; localparam integer IDXW = (QDEPTH <= 1) ? 1 : $clog2(QDEPTH); localparam integer COUNTW = (QDEPTH <= 1) ? 1 : $clog2(QDEPTH + 1); - localparam integer LAST_IDX = QDEPTH - 1; + function [IDXW-1:0] idx_const; + input integer value; + begin + idx_const = value[IDXW-1:0]; + end + endfunction + localparam [IDXW-1:0] LAST_IDX = idx_const(QDEPTH - 1); localparam [COUNTW-1:0] COUNT_MAX = QDEPTH; reg [IDXW-1:0] head, tail; reg [COUNTW-1:0] count; diff --git a/src/deserializer.v b/src/deserializer.v index e54ab98..e13795c 100644 --- a/src/deserializer.v +++ b/src/deserializer.v @@ -23,7 +23,13 @@ module deserializer #( localparam integer SHIFT_W = 1 + OPCODEW + (3 * ADDRW); localparam integer CW = (SHIFT_W <= 1) ? 1 : $clog2(SHIFT_W + 1); - localparam integer CNT_FULL = SHIFT_W - 1; + function [CW-1:0] cw_const; + input integer value; + begin + cw_const = value[CW-1:0]; + end + endfunction + localparam [CW-1:0] CNT_FULL = cw_const(SHIFT_W - 1); // synchronize reg [1:0] r_clk; diff --git a/src/req_queue.v b/src/req_queue.v index 778758d..eedb59c 100644 --- a/src/req_queue.v +++ b/src/req_queue.v @@ -33,7 +33,13 @@ module req_queue #( localparam integer SHA_INSTRW = 2 * ADDRW + OPCODEW; localparam integer AES_INSTRW = 3 * ADDRW + OPCODEW; localparam integer IDXW = (QDEPTH <= 1) ? 1 : $clog2(QDEPTH); - localparam integer LAST_IDX = QDEPTH - 1; + function [IDXW-1:0] idx_const; + input integer value; + begin + idx_const = value[IDXW-1:0]; + end + endfunction + localparam [IDXW-1:0] LAST_IDX = idx_const(QDEPTH - 1); reg [AES_INSTRW - 1:0] aesQueue [QDEPTH - 1:0]; reg [IDXW-1:0] aesReadIdx; diff --git a/src/serializer.v b/src/serializer.v index 9b25ff6..80e223c 100644 --- a/src/serializer.v +++ b/src/serializer.v @@ -16,7 +16,13 @@ module serializer #( localparam integer SHIFT_W = ADDRW + 1; // include valid bit + addr localparam integer CW = (SHIFT_W <= 1) ? 1 : $clog2(SHIFT_W + 1); - localparam integer CNT_INIT = SHIFT_W - 1; + function [CW-1:0] cw_const; + input integer value; + begin + cw_const = value[CW-1:0]; + end + endfunction + localparam [CW-1:0] CNT_INIT = cw_const(SHIFT_W - 1); reg [CW-1:0] cnt; //count reg reg [SHIFT_W-1:0] PISOreg; // [VALID][ADDRW] From 1f46f2ca65e3c32d06d26ef00316983640786be0 Mon Sep 17 00:00:00 2001 From: Eva Jin Date: Sun, 15 Feb 2026 22:36:26 -0500 Subject: [PATCH 14/18] Fixes for GL test --- test/tb.v | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/tb.v b/test/tb.v index aebf272..3c2194e 100644 --- a/test/tb.v +++ b/test/tb.v @@ -27,8 +27,8 @@ module tb (); wire VGND = 1'b0; `endif - // Replace tt_um_example with your module name: - tt_um_example user_project ( + // Instantiate the project top module. + tt_um_control_top user_project ( // Include power ports for the Gate Level test: `ifdef GL_TEST From d03076f7affa92562c385ec0f5bf2b1537aa68c1 Mon Sep 17 00:00:00 2001 From: Eva Jin Date: Sun, 15 Feb 2026 22:46:09 -0500 Subject: [PATCH 15/18] Update smoke test --- test/test.py | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/test/test.py b/test/test.py index fa7f92c..c9b16e6 100644 --- a/test/test.py +++ b/test/test.py @@ -8,7 +8,7 @@ @cocotb.test() async def test_project(dut): - dut._log.info("Start") + dut._log.info("Start control_top smoke test") # Set the clock period to 10 us (100 KHz) clock = Clock(dut.clk, 10, units="us") @@ -23,18 +23,28 @@ async def test_project(dut): await ClockCycles(dut.clk, 10) dut.rst_n.value = 1 - dut._log.info("Test project behavior") - - # Set the input values you want to test - dut.ui_in.value = 20 - dut.uio_in.value = 30 - - # Wait for one clock cycle to see the output values - await ClockCycles(dut.clk, 1) - - # The following assersion is just an example of how to check the output values. - # Change it to match the actual expected output of your module: - assert dut.uo_out.value == 50 - - # Keep testing the module by changing the input values, waiting for - # one or more clock cycles, and asserting the expected output values. + dut._log.info("Check top-level wiring invariants") + await ClockCycles(dut.clk, 5) + + # uio_oe is tied low in this design + assert int(dut.uio_oe.value) == 0, f"Expected uio_oe=0, got {dut.uio_oe.value}" + + # uo_out and uio_out are both driven from the same out_bus signal + assert dut.uo_out.value.is_resolvable, f"uo_out has X/Z: {dut.uo_out.value}" + assert dut.uio_out.value.is_resolvable, f"uio_out has X/Z: {dut.uio_out.value}" + assert int(dut.uo_out.value) == int(dut.uio_out.value), ( + f"Expected mirrored outputs, got uo_out={dut.uo_out.value}, uio_out={dut.uio_out.value}" + ) + + # Drive a non-zero pattern and re-check mirrored outputs. + dut.ui_in.value = 0xA5 + dut.uio_in.value = 0x3C + await ClockCycles(dut.clk, 5) + assert dut.uo_out.value.is_resolvable, f"uo_out has X/Z after stimulus: {dut.uo_out.value}" + assert dut.uio_out.value.is_resolvable, f"uio_out has X/Z after stimulus: {dut.uio_out.value}" + assert int(dut.uo_out.value) == int(dut.uio_out.value), ( + f"Expected mirrored outputs after stimulus, got " + f"uo_out={dut.uo_out.value}, uio_out={dut.uio_out.value}" + ) + + dut._log.info("Smoke test passed") From f3a5efb0ebe3b59a983644fd352bd918ef8a94f8 Mon Sep 17 00:00:00 2001 From: Eva Jin Date: Sat, 28 Feb 2026 16:51:52 -0500 Subject: [PATCH 16/18] Update README --- README.md | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/README.md b/README.md index 13ed997..66849bb 100644 --- a/README.md +++ b/README.md @@ -38,14 +38,4 @@ The GitHub action will automatically build the ASIC files using [OpenLane](https - Share your project on your social network of choice: - LinkedIn [#tinytapeout](https://www.linkedin.com/search/results/content/?keywords=%23tinytapeout) [@TinyTapeout](https://www.linkedin.com/company/100708654/) - Mastodon [#tinytapeout](https://chaos.social/tags/tinytapeout) [@matthewvenn](https://chaos.social/@matthewvenn) - - X (formerly Twitter) [#tinytapeout](https://twitter.com/hashtag/tinytapeout) [@tinytapeout](https://twitter.com/tinytapeout) - -## Linting (developer) - -Add convenience scripts for linting Verilog with `verilator` and `yosys`. - -- **Run lint:** `npm run lint` (requires `verilator` and `yosys` on PATH) -- **Verilator only:** `npm run lint:verilator` -- **Yosys only:** `npm run lint:yosys` - -Note: these scripts assume `verilator` and `yosys` are installed on your system. They do not install those tools. + - X (formerly Twitter) [#tinytapeout](https://twitter.com/hashtag/tinytapeout) [@tinytapeout](https://twitter.com/tinytapeout) \ No newline at end of file From 47941b5b44d52165ed9819801d9249ced777f1b8 Mon Sep 17 00:00:00 2001 From: Eva Jin Date: Sat, 28 Feb 2026 20:26:58 -0500 Subject: [PATCH 17/18] Edits --- src/aes_fsm.v | 4 +-- src/comp_queue.v | 11 +++++--- src/deserializer.v | 41 ++++++++++++++++++++--------- src/req_queue.v | 58 ++++++++++++++++++++++++++--------------- src/tt_um_control_top.v | 19 +++++++++++--- 5 files changed, 91 insertions(+), 42 deletions(-) diff --git a/src/aes_fsm.v b/src/aes_fsm.v index 3bc8f6f..a5cd38c 100644 --- a/src/aes_fsm.v +++ b/src/aes_fsm.v @@ -162,10 +162,10 @@ module aes_fsm #( end HASHOP: begin arb_req = 1'b1; - data_out = {24'b0, r_req_data[3*ADDRW+1], (r_req_data[3*ADDRW] & 1'b0), ACCEL_ID, 4'b0011}; + data_out = {24'b0, r_req_data[3*ADDRW+1], 1'b0, ACCEL_ID, 4'b0011}; end WAIT_HASHOP: begin - data_out = {24'b0, r_req_data[3*ADDRW+1], (r_req_data[3*ADDRW] & 1'b0), ACCEL_ID, 4'b0011}; + data_out = {24'b0, r_req_data[3*ADDRW+1], 1'b0, ACCEL_ID, 4'b0011}; end MEMWR: begin arb_req = 1'b1; diff --git a/src/comp_queue.v b/src/comp_queue.v index d919166..a0ccb98 100644 --- a/src/comp_queue.v +++ b/src/comp_queue.v @@ -27,6 +27,8 @@ module comp_queue #( // Internal FIFO reg [ADDRW-1:0] mem [0:QDEPTH-1]; + // Calculate index and count widths based on QDEPTH + // Handles edge cases like QDEPTH <= 1, force min width to be 1 localparam integer IDXW = (QDEPTH <= 1) ? 1 : $clog2(QDEPTH); localparam integer COUNTW = (QDEPTH <= 1) ? 1 : $clog2(QDEPTH + 1); function [IDXW-1:0] idx_const; @@ -37,11 +39,12 @@ module comp_queue #( endfunction localparam [IDXW-1:0] LAST_IDX = idx_const(QDEPTH - 1); localparam [COUNTW-1:0] COUNT_MAX = QDEPTH; + reg [IDXW-1:0] head, tail; reg [COUNTW-1:0] count; wire full = (count == COUNT_MAX); - wire empty = (count == {COUNTW{1'b0}}); + wire empty = (count == {COUNTW{1'b0}}); // zero width // Round-robin selector: 0 = AES, 1 = SHA reg rr_select; @@ -99,8 +102,10 @@ module comp_queue #( // Dequeue logic if (deq_valid && ready_in) begin data_out <= mem[head]; - if (head == LAST_IDX) head <= {IDXW{1'b0}}; - else head <= head + 1; + if (head == LAST_IDX) // (head + 1) % QDEPTH + head <= {IDXW{1'b0}}; + else + head <= head + 1; count <= count - 1; end diff --git a/src/deserializer.v b/src/deserializer.v index e13795c..7f380bd 100644 --- a/src/deserializer.v +++ b/src/deserializer.v @@ -21,15 +21,30 @@ module deserializer #( output reg valid_out ); - localparam integer SHIFT_W = 1 + OPCODEW + (3 * ADDRW); - localparam integer CW = (SHIFT_W <= 1) ? 1 : $clog2(SHIFT_W + 1); - function [CW-1:0] cw_const; + // clog2 helper function for calculating bit widths + function integer clog2; input integer value; + integer v, n; // delacre n begin - cw_const = value[CW-1:0]; + if (value <= 1) begin + clog2 = 1; + end else begin + v = value - 1; + n = 0; + while (v > 0) begin + v = v >> 1; + n = n + 1; + end + clog2 = n; + end end endfunction - localparam [CW-1:0] CNT_FULL = cw_const(SHIFT_W - 1); + + // Total instruction width: [valid(1b), opcode(OPCODEW), key_addr, text_addr, dest_addr] + localparam integer SHIFT_W = 1 + OPCODEW + (3 * ADDRW); + // Bits needed to count from 0 to SHIFT_W-1 + localparam integer CW = clog2(SHIFT_W + 1); + localparam [CW-1:0] CNT_FULL = SHIFT_W - 1; // synchronize reg [1:0] r_clk; @@ -37,9 +52,9 @@ module deserializer #( reg [1:0] r_mosi; always @(posedge clk or negedge rst_n) begin - if (!rst_n) begin // active-low reset - r_clk <= 2'b00; - r_cs_n <= 2'b11; + if (!rst_n) begin // Changed to active-low reset + r_clk <= 2'b00; // Changed from 3'b00 + r_cs_n <= 2'b11; // Inactive r_mosi <= 2'b00; end else begin r_clk <= {r_clk[0], spi_clk}; @@ -51,20 +66,20 @@ module deserializer #( // shift data wire clk_posedge = (r_clk == 2'b01); // detected posedge of spi_clk (0->1) - reg [CW-1:0] cnt; // how many bits of current word have been collected + reg [CNT_W-1:0] cnt; // how many bits of current word have been collected reg [SHIFT_W-1:0] shift_reg; reg busy; // when pending_valid == 1, ignore new incoming bits always @ (posedge clk or negedge rst_n) begin if (!rst_n) begin // Active-low reset - cnt <= {CW{1'b0}}; + cnt <= {CNT_W{1'b0}}; shift_reg <= {SHIFT_W{1'b0}}; busy <= 1'b0; valid <= 1'b0; opcode <= {OPCODEW{1'b0}}; key_addr <= {ADDRW{1'b0}}; text_addr <= {ADDRW{1'b0}}; - dest_addr <= {ADDRW{1'B0}}; + dest_addr <= {ADDRW{1'b0}}; valid_out <= 1'b0; end else begin valid_out <= 1'b0; // one-cycle pulse default @@ -76,7 +91,7 @@ module deserializer #( shift_reg <= {shift_reg[SHIFT_W-2:0], r_mosi[1]}; if (cnt == CNT_FULL) begin busy <= 1'b1; // full word captured - cnt <= {CW{1'b0}}; + cnt <= {CNT_W{1'b0}}; end else begin cnt <= cnt + 1'b1; // increment count end @@ -84,7 +99,7 @@ module deserializer #( end else begin // on de-assertion, clear partial word if (!busy) begin - cnt <= {CW{1'b0}}; + cnt <= {CNT_W{1'b0}}; shift_reg <= {SHIFT_W{1'b0}}; end end diff --git a/src/req_queue.v b/src/req_queue.v index eedb59c..dc23db1 100644 --- a/src/req_queue.v +++ b/src/req_queue.v @@ -22,9 +22,18 @@ module req_queue #( output wire ready_out_sha ); - integer i; + function integer clog2; + input integer value; + integer v, i; + begin + v = value - 1; + for (i = 0; v > 0; i = i + 1) v = v >> 1; + clog2 = (value <= 1) ? 1 : i; + end + endfunction initial begin + integer i; $dumpfile("tb.vcd"); for (i = 0; i < QDEPTH; i = i + 1) $dumpvars(0, aesQueue[i]); for (i = 0; i < QDEPTH; i = i + 1) $dumpvars(0, shaQueue[i]); @@ -32,22 +41,24 @@ module req_queue #( localparam integer SHA_INSTRW = 2 * ADDRW + OPCODEW; localparam integer AES_INSTRW = 3 * ADDRW + OPCODEW; + // Calculate index and count widths based on QDEPTH + // Handles edge cases like QDEPTH <= 1, force min width to be 1 localparam integer IDXW = (QDEPTH <= 1) ? 1 : $clog2(QDEPTH); - function [IDXW-1:0] idx_const; + function [IDXW - 1:0] idx_const; input integer value; begin - idx_const = value[IDXW-1:0]; + idx_const = value[IDXW - 1:0]; end endfunction - localparam [IDXW-1:0] LAST_IDX = idx_const(QDEPTH - 1); + localparam [IDXW - 1:0] LAST_IDX = idx_const(QDEPTH - 1); reg [AES_INSTRW - 1:0] aesQueue [QDEPTH - 1:0]; - reg [IDXW-1:0] aesReadIdx; - reg [IDXW-1:0] aesWriteIdx; + reg [IDXW - 1:0] aesReadIdx; + reg [IDXW - 1:0] aesWriteIdx; reg aesFull; reg [SHA_INSTRW - 1:0] shaQueue [QDEPTH - 1:0]; - reg [IDXW-1:0] shaReadIdx; - reg [IDXW-1:0] shaWriteIdx; + reg [IDXW - 1:0] shaReadIdx; + reg [IDXW - 1:0] shaWriteIdx; reg shaFull; assign ready_out_aes = (aesReadIdx != aesWriteIdx || !aesFull) && rst_n; @@ -59,6 +70,7 @@ module req_queue #( always @(posedge clk or negedge rst_n) begin if (!rst_n) begin + integer i; for (i = 0; i < QDEPTH; i = i + 1) aesQueue[i] <= {AES_INSTRW{1'b0}}; aesReadIdx <= {IDXW{1'b0}}; aesWriteIdx <= {IDXW{1'b0}}; @@ -71,15 +83,15 @@ module req_queue #( if (valid_in) begin if (ready_out_aes) begin if (opcode[0] == 0) begin - aesQueue[aesWriteIdx] <= {opcode, key_addr, text_addr, dest_addr}; - // compute next index without using % to avoid width warnings - if (aesWriteIdx == LAST_IDX) begin - if (aesReadIdx == {IDXW{1'b0}}) aesFull <= 1; - aesWriteIdx <= {IDXW{1'b0}}; - end else begin - if (aesReadIdx == aesWriteIdx + 1) aesFull <= 1; - aesWriteIdx <= aesWriteIdx + 1; - end + aesQueue[aesWriteIdx] <= {opcode, key_addr, text_addr, dest_addr}; + // compute next index without using % to avoid width warnings + if (aesWriteIdx == LAST_IDX) begin + if (aesReadIdx == {IDXW{1'b0}}) aesFull <= 1; + aesWriteIdx <= {IDXW{1'b0}}; + end else begin + if (aesReadIdx == aesWriteIdx + 1) aesFull <= 1; + aesWriteIdx <= aesWriteIdx + 1; + end end end if (ready_out_sha) begin @@ -96,13 +108,17 @@ module req_queue #( end end if (ready_in_aes) begin - if (aesReadIdx == LAST_IDX) aesReadIdx <= {IDXW{1'b0}}; - else aesReadIdx <= aesReadIdx + 1; + if (aesReadIdx == LAST_IDX) + aesReadIdx <= {IDXW{1'b0}}; + else + aesReadIdx <= aesReadIdx + 1; aesFull <= 0; end if (ready_in_sha) begin - if (shaReadIdx == LAST_IDX) shaReadIdx <= {IDXW{1'b0}}; - else shaReadIdx <= shaReadIdx + 1; + if (shaReadIdx == LAST_IDX) + shaReadIdx <= {IDXW{1'b0}}; + else + shaReadIdx <= shaReadIdx + 1; shaFull <= 0; end end diff --git a/src/tt_um_control_top.v b/src/tt_um_control_top.v index 3342a39..598f660 100644 --- a/src/tt_um_control_top.v +++ b/src/tt_um_control_top.v @@ -21,7 +21,13 @@ module tt_um_control_top #( output wire [7:0] uio_oe // output enable (1=output) ); - // input + // Tiny Tapeout wraps discrete pins into 8-bit buses. + // Legacy control_top equivalents: + // in_bus[0] -> mosi + // in_bus[1] -> spi_clk + // in_bus[2] -> cs_n + // in_bus[3] -> bus_ready + // in_bus[6:4] -> ack_in[2:0] wire [7:0] in_bus = ui_in | uio_in; wire mosi = in_bus[0]; wire spi_clk = in_bus[1]; @@ -29,12 +35,19 @@ module tt_um_control_top #( wire bus_ready = in_bus[3]; wire [2:0] ack_in = in_bus[6:4]; // ACK signals - // internal signals (will be mapped to uo_out) + // Internal signals corresponding to old top-level outputs/signals: + // miso <-> old output miso + // data_bus_out <-> old output data_bus_out[7:0] + // data_bus_valid <-> old output data_bus_valid wire miso; wire [7:0] data_bus_out; wire data_bus_valid; - // outputs + // Packed TT outputs carrying old outputs: + // out_bus[0] = miso + // out_bus[6:1] = data_bus_out[6:1] + // out_bus[7] = data_bus_valid + // Note: data_bus_out[0] and [7] are not exported on out_bus. wire [7:0] out_bus; assign out_bus[0] = miso; assign out_bus[6:1] = data_bus_out[6:1]; From 6ade20b5f395f26996d3fd6148be9fee9cf5f155 Mon Sep 17 00:00:00 2001 From: Eva Jin Date: Sat, 28 Feb 2026 20:37:55 -0500 Subject: [PATCH 18/18] Test fixes --- src/deserializer.v | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/deserializer.v b/src/deserializer.v index 7f380bd..5d2356e 100644 --- a/src/deserializer.v +++ b/src/deserializer.v @@ -66,13 +66,13 @@ module deserializer #( // shift data wire clk_posedge = (r_clk == 2'b01); // detected posedge of spi_clk (0->1) - reg [CNT_W-1:0] cnt; // how many bits of current word have been collected + reg [CW-1:0] cnt; // how many bits of current word have been collected reg [SHIFT_W-1:0] shift_reg; reg busy; // when pending_valid == 1, ignore new incoming bits always @ (posedge clk or negedge rst_n) begin if (!rst_n) begin // Active-low reset - cnt <= {CNT_W{1'b0}}; + cnt <= {CW{1'b0}}; shift_reg <= {SHIFT_W{1'b0}}; busy <= 1'b0; valid <= 1'b0; @@ -91,7 +91,7 @@ module deserializer #( shift_reg <= {shift_reg[SHIFT_W-2:0], r_mosi[1]}; if (cnt == CNT_FULL) begin busy <= 1'b1; // full word captured - cnt <= {CNT_W{1'b0}}; + cnt <= {CW{1'b0}}; end else begin cnt <= cnt + 1'b1; // increment count end @@ -99,7 +99,7 @@ module deserializer #( end else begin // on de-assertion, clear partial word if (!busy) begin - cnt <= {CNT_W{1'b0}}; + cnt <= {CW{1'b0}}; shift_reg <= {SHIFT_W{1'b0}}; end end