WORKING PROGRESS. revamped the files and naming, so git is a bit confused

mem_hub.sv -> hub.sv
spi_slave.sv -> interface.sv
This commit is contained in:
2025-05-17 22:06:41 -04:00
parent a83a8f9f95
commit 1f7c47a1fb
5 changed files with 392 additions and 149 deletions

84
fabric/src/hub.sv Normal file
View File

@ -0,0 +1,84 @@
module hub (
input logic rst,
input logic sys_clk,
input logic [31:0] rx_cmd, // for routing-related commands
input logic [3:0] rx_cmd_valid,
input logic [31:0] rx_byte,
input logic [3:0] rx_valid,
input logic [7:0] rx2tx_dest, // rx byte's destination
input logic [3:0] tx_ready, // if tx_byte is ready to be read
output logic [3:0] rx_ready, // if rx_byte is ready to be read
output logic [7:0] tx_src, // tell the tx where the stream is comming from
output logic [31:0] tx_byte,
output logic [3:0] tx_valid,
output logic [1:0] packet_size); // 4 states for 4 fixed packet sizes
timeunit 1ns;
timeprecision 1ps;
// TBD: pre-agree on packet size
// use the round-robin strat to poll since the routing is much faster
// NOTE: To expand to more connected_devices, use a hierarchical design
logic [1:0] curr_service = 0;
logic [1:0] last_dest = 0;
// src dest byte
typedef struct {
logic [1:0] dest;
logic [7:0] payload;
} svc_buffer;
svc_buffer service_buffer [3:0];
svc_buffer curr_buffer;
assign curr_buffer = service_buffer[curr_service];
logic [3:0] in_buffer;
assign rx_ready = ~in_buffer;
always_ff @ (posedge sys_clk) begin
if (rst) begin
in_buffer <= '0;
tx_src <= '0;
tx_valid <= '0;
packet_size <= '0;
curr_service <= '0;
last_dest <= '0;
for (int i = 0; i < 4; i++) begin
service_buffer[i] <= '0;
end
end else begin // if (rst)
// Handle RX side logic
for (int i = 0; i < 4; i++) begin
if (rx_valid[i]) begin
if (!in_buffer[i]) begin
service_buffer[i].dest <= get_dest(rx2tx_dest, i[1:0]);
service_buffer[i].payload <= get_byte(rx_byte, i[1:0]);
in_buffer[i] <= 1;
end
end
end
// Handle TX side logic
if (in_buffer[curr_service] && tx_ready[curr_buffer.dest]) begin
tx_byte[{curr_buffer.dest, 3'b000} +: 8]
<= curr_buffer.payload;
tx_src[{curr_buffer.dest, 1'b0} +: 2]
<= curr_service;
in_buffer[curr_service] <= 0;
tx_valid[curr_buffer.dest] <= 1;
end
tx_valid[last_dest] <= 0;
last_dest <= service_buffer[curr_service].dest;
curr_service <= curr_service + 1;
end // else: !if(rst)
end // always_ff @ (posedge sys_clk)
endmodule // hub
function automatic logic [1:0] get_dest(input logic [7:0] dest_map,
input logic [1:0] idx);
return dest_map[{idx, 1'b0} +: 2];
endfunction // get_dest
function automatic logic [7:0] get_byte(input logic [31:0] byte_arr,
input logic [1:0] idx);
return byte_arr[{idx, 3'b000} +: 8];
endfunction // get_byte

188
fabric/src/interface.sv Normal file
View File

@ -0,0 +1,188 @@
// NOTE: The first byte is used for syncing due to using different clock domains
`define SYNC_2FF
module spi_interface(
input logic rst,
input logic sys_clk,
input logic mosi,
input logic cs,
input logic sclk,
input logic rx_ready,
input logic tx_valid,
input logic [7:0] tx_byte,
input logic [1:0] tx_src,
output logic miso,
output logic tx_ready,
output logic rx_valid,
output logic [7:0] rx_byte,
output logic [1:0] rx_dest,
output logic [7:0] rx_cmd,
output logic rx_cmd_valid);
timeunit 1ns;
timeprecision 1ps;
// SPI logic
logic sclk_rising_edge;
logic sclk_falling_edge;
async_get_clk_edges sync (.rst(rst),
.ext_clk(sclk),
.sys_clk(sys_clk),
.clk_rising_edge(sclk_rising_edge),
.clk_falling_edge(sclk_falling_edge));
int bit_cnt = 0;
logic [7:0] rx_shift;
logic [7:0] tx_shift = 8'b00101010;
logic [7:0] tx_buff = '0;
logic byte_ready = 0;
always_ff @ (posedge sclk_rising_edge or posedge rst) begin
if (rst) begin
rx_shift <= '0;
tx_buff <= '0;
bit_cnt <= '0;
byte_ready <= 0;
end
else begin
if (cs) begin
rx_shift <= 0;
tx_buff <= 0;
bit_cnt <= 0;
end else begin
rx_shift <= {rx_shift[6:0], mosi};
bit_cnt <= bit_cnt + 1;
if (bit_cnt == 7) begin
bit_cnt <= 0;
tx_buff <= {rx_shift[6:0], mosi};
byte_ready <= 1;
end else
byte_ready <= 0;
end // else: !if(cs)
end // else: !if(rst)
$display("[%0d] current rx_shift: %b", $time, rx_shift);
$display("[%0d] current bit_cnt: %0d", $time, bit_cnt);
$display("[%0d] current tx_buff: %b", $time, tx_buff);
end // always_ff @ (posedge sclk)
always_ff @ (posedge sclk_falling_edge) begin
if (rst) begin
tx_shift <= 0;
end
else begin
if (cs) begin
tx_shift <= 0;
end else begin
if (bit_cnt == 0) begin
tx_shift <= tx_buff[7:0];
end else begin
tx_shift <= {tx_shift[6:0], 1'b0};
end
end
end // else: !if(rst)
$display("last bit sent: %b", miso);
$display("[%0d] current tx_shift: %b", $time, tx_shift);
$display("-----------------------------------------");
end // always_ff @ (negedge sclk)
assign miso = tx_shift[7];
shortint packet_size = 64;
// RX and TX logic
logic [9:0] rx_queue_head = 0;
logic [9:0] rx_queue_tail = 0;
logic [10:0] rx_size = 0;
logic rx_queue_write = 0;
logic [7:0] rx_read;
logic packet_in;
logic rx_queue_empty;
assign rx_size = (rx_queue_tail + 11'd1024 - rx_queue_head) & 11'h3FF;
assign rx_queue_empty = ~(|rx_size);
bram_1024B rx_queue (.sys_clk(sys_clk),
.write_enable(rx_queue_write),
.read_addr(rx_queue_head),
.write_addr(rx_queue_tail),
.write_data(tx_buff),
.read_data(rx_read));
always_ff @ (posedge sys_clk) begin
if (rst) begin
rx_queue_head <= '0;
rx_queue_tail <= '0;
rx_queue_write <= '0;
rx_read <= '0;
packet_in <= 0;
end else begin
if (byte_ready)
rx_queue_write <= 1;
else
rx_queue_write <= 0;
if (!packet_in && rx_size > 2) begin
// CONSULT internal routing table for directions
end
end
end
endmodule // spi_interface
module async_get_clk_edges(
input logic rst,
input logic ext_clk,
input logic sys_clk,
output logic clk_rising_edge,
output logic clk_falling_edge);
timeunit 1ns;
timeprecision 1ps;
`ifdef SYNC_2FF
logic sync_0 = 0;
logic sync_1 = 0;
always_ff @ (posedge sys_clk) begin
if (rst) begin
sync_0 <= 0;
sync_1 <= 0;
end else begin
sync_0 <= ext_clk;
sync_1 <= sync_0;
end
end
assign clk_rising_edge = sync_0 & ~sync_1;
assign clk_falling_edge = ~sync_0 & sync_1;
`else // !`ifdef SYNC_2FF
logic [2:0] clk_sync = 0;
always_ff @ (posedge sys_clk) begin
if (rst)
clk_sync <= {clk_sync[1:0], ext_clk};
end
assign clk_rising_edge = (clk_sync[2:1] == 2'b01);
assign clk_falling_edge = (clk_sync[2:1] == 2'b10);
`endif // !`ifdef SYNC_2FF
endmodule // async_get_clk_edges
module bram_1024B (
input logic sys_clk,
input logic write_enable,
input logic [9:0] read_addr,
input logic [9:0] write_addr,
input logic [7:0] write_data,
output logic [7:0] read_data);
timeunit 1ns;
timeprecision 1ps;
logic [7:0] mem [0:1023];
always_ff @(posedge sys_clk) begin
if (write_enable)
mem[write_addr] <= write_data;
read_data <= mem[read_addr];
end
endmodule // bram_1024B

View File

@ -1,43 +0,0 @@
module mem_hub (input logic rst,
input logic sys_clk,
input logic [3:0] connected_devices, // manually configured
input logic [3:0][7:0] rx_cmd, // for routing-related commands
input logic [3:0] rx_cmd_valid,
input logic [3:0][7:0] rx_byte,
input logic [3:0] rx_valid,
input logic [3:0][1:0] rx2tx_dest, // rx byte's destination
input logic [3:0] tx_ready, // if tx_byte was read
output logic [3:0] rx_ready, // if rx_byte was read
output logic [3:0][1:0] tx_src, // tell the tx where the stream is comming from
output logic [3:0][7:0] tx_byte,
output logic [3:0] tx_valid,
output logic [1:0] packet_size); // 4 states for 4 fixed packet sizes
timeunit 1ns;
timeprecision 1ps;
// TBD: pre-agree on packet size
// use the round-robin strat to poll since the routing is much faster
// NOTE: To expand to more connected_devices, use a hierarchical design
logic [1:0] curr_service = 0;
// src dest byte
logic [1:0][1:0][7:0] service_buffer;
logic [3:0] in_buffer;
// Core service logic
always_ff @ (posedge sys_clk) begin
if (rst) begin
rx_ready <= '1;
tx_src <= '0;
tx_valid <= '0;
packet_size <= '0;
service_buffer <= '0;
curr_service <= '0;
end else if (rx_valid[curr_service]) begin
end
curr_service <= curr_service + 1;
end
endmodule // mem_hub

View File

@ -1,106 +0,0 @@
// NOTE: The first byte is used for syncing due to using different clock domains
`define SYNC_2FF
module spi_slave(
input logic sys_clk,
input logic mosi,
input logic cs,
input logic sclk,
input logic rst,
output logic miso);
timeunit 1ns;
timeprecision 1ps;
logic sclk_rising_edge;
logic sclk_falling_edge;
async_get_clk_edges sync (.ext_clk(sclk),
.sys_clk(sys_clk),
.clk_rising_edge(sclk_rising_edge),
.clk_falling_edge(sclk_falling_edge));
int bit_cnt = 0;
logic [7:0] rx_shift;
logic [7:0] tx_shift = 8'b00101010;
logic [8:0] tx_buff = '0;
logic byte_ready = 0;
always_ff @ (posedge sclk_rising_edge or posedge rst) begin
if (rst) begin
rx_shift <= 0;
tx_buff <= 0;
bit_cnt <= 0;
end
else begin
if (cs) begin
rx_shift <= 0;
tx_buff <= 0;
bit_cnt <= 0;
end else begin
rx_shift <= {rx_shift[6:0], mosi};
bit_cnt <= bit_cnt + 1;
if (bit_cnt == 7) begin
bit_cnt <= 0;
tx_buff <= {rx_shift[6:0], mosi} + 1;
end
end // else: !if(cs)
end // else: !if(rst)
$display("[%0d] current rx_shift: %b", $time, rx_shift);
$display("[%0d] current bit_cnt: %0d", $time, bit_cnt);
$display("[%0d] current tx_buff: %b", $time, tx_buff);
end // always_ff @ (posedge sclk)
always_ff @ (posedge sclk_falling_edge) begin
if (rst) begin
tx_shift <= 0;
end
else begin
if (cs) begin
tx_shift <= 0;
end else begin
if (bit_cnt == 0) begin
tx_shift <= tx_buff[7:0];
end else begin
tx_shift <= {tx_shift[6:0], 1'b0};
end
end
end // else: !if(rst)
$display("last bit sent: %b", miso);
$display("[%0d] current tx_shift: %b", $time, tx_shift);
$display("-----------------------------------------");
end // always_ff @ (negedge sclk)
assign miso = tx_shift[7];
endmodule // spi_slave
module async_get_clk_edges(
input logic ext_clk,
input logic sys_clk,
output logic clk_rising_edge,
output logic clk_falling_edge);
timeunit 1ns;
timeprecision 1ps;
`ifdef SYNC_2FF
logic sync_0;
logic sync_1;
always_ff @ (posedge sys_clk) begin
sync_0 <= ext_clk;
sync_1 <= sync_0;
end
assign clk_rising_edge = sync_0 & ~sync_1;
assign clk_falling_edge = ~sync_0 & sync_1;
`else // !`ifdef SYNC_2FF
logic [2:0] clk_sync;
always_ff @ (posedge sys_clk) begin
clk_sync <= {clk_sync[1:0], ext_clk};
end
assign clk_rising_edge = (clk_sync[2:1] == 2'b01);
assign clk_falling_edge = (clk_sync[2:1] == 2'b10);
`endif // !`ifdef SYNC_2FF
endmodule