Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 13 additions & 9 deletions src/bus_arbiter.v
Original file line number Diff line number Diff line change
Expand Up @@ -86,16 +86,20 @@ always @(posedge clk or negedge rst_n) begin
if (bus_ready) counter <= counter + 1;
end else begin
// Counter should always be 0 when curr_mode == 2'b00
if (sha_req && aes_req) begin
curr_mode <= last_serviced ? 2'b10 : 2'b01;
end else if (aes_req) begin
curr_mode <= 2'b01;
end else if (sha_req) begin
curr_mode <= 2'b10;
end else begin
curr_mode <= 2'b00;
counter <= 2'b00;

if (bus_ready) begin
if (sha_req && aes_req) begin
curr_mode <= last_serviced ? 2'b10 : 2'b01;
end else if (aes_req) begin
curr_mode <= 2'b01;
end else if (sha_req) begin
curr_mode <= 2'b10;
end else begin
curr_mode <= 2'b00;
counter <= 2'b00;
end
end

end

if (counter == 2'b11) begin
Expand Down
38 changes: 12 additions & 26 deletions src/comp_queue.v
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,11 @@ 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);
localparam [IDXW-1:0] LAST_IDX = IDXW'(QDEPTH - 1);
localparam [COUNTW-1:0] COUNT_MAX = QDEPTH;

function [IDXW-1:0] increment_ptr;
input [IDXW-1:0] val;
increment_ptr = (val == LAST_IDX) ? {IDXW{1'b0}} : val + 1'b1;
endfunction

reg [IDXW-1:0] head, tail;
reg [COUNTW-1:0] count;

wire full = (count == COUNT_MAX);
wire empty = (count == {COUNTW{1'b0}}); // zero width
reg [$clog2(QDEPTH)-1:0] head, tail;
reg [$clog2(QDEPTH+1)-1:0] count;

wire full = (count == QDEPTH);
wire empty = (count == 0);

// Round-robin selector: 0 = AES, 1 = SHA
reg rr_select;
Expand Down Expand Up @@ -69,25 +57,23 @@ module comp_queue #(

always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
head <= {IDXW{1'b0}};
tail <= {IDXW{1'b0}};
count <= {COUNTW{1'b0}};
head <= 0;
tail <= 0;
count <= 0;
rr_select <= 0;
valid_out <= 0;
data_out <= 0;
end else begin
// Debug output around failing cycle (simulation only)
`ifndef SYNTHESIS
// Debug output around failing cycle
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 (do_enq) begin
mem[tail] <= enq_data;
tail <= increment_ptr(tail);
tail <= (tail + 1);
end

// Toggle round-robin if both inputs are valid — regardless of enqueue
Expand All @@ -102,7 +88,7 @@ module comp_queue #(

// Dequeue on handshake
if (do_deq) begin
head <= increment_ptr(head);
head <= (head + 1);
valid_out <= 0;
end

Expand All @@ -116,4 +102,4 @@ module comp_queue #(
end
end

endmodule
endmodule
4 changes: 3 additions & 1 deletion src/control_top.v
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,7 @@ module control_top #(
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 ser_ready_out;
assign compq_ready_in = ser_ready_out & ~cs_n;
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(ser_ready_out), .err());
endmodule
48 changes: 21 additions & 27 deletions src/req_queue.v
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ module req_queue #(
output wire ready_out_sha
);

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

// integer i;
integer j, k;

Expand All @@ -34,10 +44,7 @@ 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);
localparam [IDXW - 1:0] LAST_IDX = IDXW'(QDEPTH - 1);
localparam integer IDXW = clog2(QDEPTH);

reg [AES_INSTRW - 1:0] aesQueue [QDEPTH - 1:0];
reg [IDXW - 1:0] aesReadIdx;
Expand Down Expand Up @@ -70,41 +77,28 @@ module req_queue #(
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;
aesWriteIdx <= (aesWriteIdx + 1);
if (aesReadIdx == (aesWriteIdx + 1)) begin
aesFull <= 1;
end
end
end
if (ready_out_sha) begin
if (opcode[0] == 1) begin
shaQueue[shaWriteIdx] <= {opcode, text_addr, dest_addr};
if (shaWriteIdx == LAST_IDX) begin
if (shaReadIdx == {IDXW{1'b0}}) shaFull <= 1;
shaWriteIdx <= {IDXW{1'b0}};
end else begin
if (shaReadIdx == shaWriteIdx + 1) shaFull <= 1;
shaWriteIdx <= shaWriteIdx + 1;
shaWriteIdx <= (shaWriteIdx + 1);
if (shaReadIdx == (shaWriteIdx + 1)) begin
shaFull <= 1;
end
end
end
end
if (ready_in_aes) begin
if (aesReadIdx == LAST_IDX)
aesReadIdx <= {IDXW{1'b0}};
else
aesReadIdx <= aesReadIdx + 1;
if (ready_in_aes && valid_out_aes) begin
aesReadIdx <= aesReadIdx + 1;
aesFull <= 0;
end
if (ready_in_sha) begin
if (shaReadIdx == LAST_IDX)
shaReadIdx <= {IDXW{1'b0}};
else
shaReadIdx <= shaReadIdx + 1;
if (ready_in_sha && valid_out_sha) begin
shaReadIdx <= shaReadIdx + 1;
shaFull <= 0;
end
end
Expand Down
3 changes: 2 additions & 1 deletion src/serializer.v
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ module serializer #(
err <= 1'b0;
end
else if (~valid_ncs) begin
if (valid_in && ready_out == 1 && negedgeSPI) begin
if (valid_in && ready_out) begin
PISOreg <= {1'b1 , addr};
ready_out <= 0;
cnt <= CNT_INIT;
Expand All @@ -107,6 +107,7 @@ module serializer #(
miso <= 1'b0;
end else begin
err <= 1'b0;
//ready_out <= 0;
end
end

Expand Down
169 changes: 169 additions & 0 deletions test/control_top_tb.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
`timescale 1ns/1ps

module control_top_tb;

parameter ADDRW = 24;
parameter OPCODEW = 2;
parameter REQ_QDEPTH = 4;
parameter COMP_QDEPTH = 4;

reg clk, rst_n;
reg spi_clk, mosi, cs_n;
reg [2:0] ack_in;
reg bus_ready;
reg ena;

wire miso;
wire [7:0] data_bus_out;
wire data_bus_valid;


control_top #(
.ADDRW(ADDRW), .OPCODEW(OPCODEW),
.REQ_QDEPTH(REQ_QDEPTH), .COMP_QDEPTH(COMP_QDEPTH)
) dut (
.clk(clk), .rst_n(rst_n), .ena(ena),
.spi_clk(spi_clk), .mosi(mosi), .cs_n(cs_n),
.miso(miso),
.ack_in(ack_in), .bus_ready(bus_ready),
.data_bus_out(data_bus_out), .data_bus_valid(data_bus_valid)
);

always #5 clk = ~clk;

initial begin
$dumpfile("control_top_tb.vcd");
$dumpvars(0, control_top_tb);
end

task spi_bit(input b);
begin
mosi = b;
spi_clk = 0; #25;
spi_clk = 1; #25;
end
endtask

task spi_frame(
input v, input ed, input as,
input [ADDRW-1:0] key,
input [ADDRW-1:0] text,
input [ADDRW-1:0] dest
);
integer i;
begin
cs_n = 0;
#500;
spi_bit(v); spi_bit(ed); spi_bit(as);
for (i = ADDRW-1; i >= 0; i = i-1) spi_bit(key[i]);
for (i = ADDRW-1; i >= 0; i = i-1) spi_bit(text[i]);
for (i = ADDRW-1; i >= 0; i = i-1) spi_bit(dest[i]);
spi_clk = 0;
#50;
cs_n = 1;
#100;
end
endtask

task arb_transaction(input [2:0] ack_val);
begin
wait (dut.bus_arbiter_inst.curr_mode != 2'b00);
wait (dut.bus_arbiter_inst.counter == 2'b11);
@(posedge clk);
wait (dut.bus_arbiter_inst.curr_mode == 2'b00);
@(posedge clk);
ack_in = ack_val;
@(posedge clk);
ack_in = 0;
repeat (2) @(posedge clk);
end
endtask

task drive_aes_full;
begin
arb_transaction(3'b100);
arb_transaction(3'b100);
arb_transaction(3'b110);
arb_transaction(3'b100);
end
endtask

task do_reset;
begin
rst_n = 0; cs_n = 1; mosi = 0; spi_clk = 0;
ack_in = 0; bus_ready = 0;
#20 rst_n = 1;
repeat (4) @(posedge clk);
end
endtask

initial begin
clk = 0; rst_n = 0; spi_clk = 0; mosi = 0; cs_n = 1;
ack_in = 0; bus_ready = 0; ena = 1;
#20 rst_n = 1; #50;

// =============================================
// TEST 1: single AES end-to-end
// =============================================
spi_frame(1, 0, 0, 24'hAA_0001, 24'hBB_0001, 24'hCC_0001);

bus_ready = 1;
drive_aes_full;

repeat (10) @(posedge clk);

// read SPI output
cs_n = 0; #500;
repeat (300) @(posedge clk);
cs_n = 1; #100;

repeat (20) @(posedge clk);

do_reset;

// =============================================
// TEST 2: back-to-back AES requests
// =============================================
spi_frame(1, 0, 0, 24'hAA_0002, 24'hBB_0002, 24'hCC_0002);
spi_frame(1, 0, 0, 24'hAA_0003, 24'hBB_0003, 24'hCC_0003);

bus_ready = 1;
drive_aes_full;
drive_aes_full;

repeat (10) @(posedge clk);

cs_n = 0; #500;
repeat (700) @(posedge clk);
cs_n = 1; #100;

repeat (20) @(posedge clk);

do_reset;

// =============================================
// TEST 3: pipeline stress — 4 AES requests
// =============================================
spi_frame(1, 0, 0, 24'hAA_0010, 24'hBB_0010, 24'hCC_0010);
spi_frame(1, 0, 0, 24'hAA_0020, 24'hBB_0020, 24'hCC_0020);
spi_frame(1, 0, 0, 24'hAA_0030, 24'hBB_0030, 24'hCC_0030);
spi_frame(1, 0, 0, 24'hAA_0040, 24'hBB_0040, 24'hCC_0040);

bus_ready = 1;
drive_aes_full;
drive_aes_full;
drive_aes_full;
drive_aes_full;

repeat (10) @(posedge clk);

cs_n = 0; #500;
repeat (1500) @(posedge clk);
cs_n = 1; #100;

repeat (20) @(posedge clk);

$finish;
end

endmodule
Loading