Files
rose/fabric/src/interface.sv

147 lines
5.0 KiB
Systemverilog

// NOTE: The first byte is used for syncing due to using different clock domains
`include <params.svh>
module spi_interface(
input logic rst,
input logic sys_clk,
input logic mosi,
input logic cs,
input logic sclk,
output logic miso,
output logic [7:0] rx_byte,
output logic rx_valid,
input logic rx_ready,
output logic [PACKET_ADDR_LEN - 1:0] rx_pkt_addr,
input logic [7:0] tx_byte,
input logic tx_valid,
output logic tx_ready,
output logic [PACKET_ADDR_LEN - 1:0] tx_pkt_addr,
output logic [QUEUE_ADDR_LEN - 1:0] tx_queue_addr,
input logic [QUEUE_ADDR_LEN - 1:0] tx_new_queue,
input logic tx_new_queue_valid,
output logic tx_new_queue_ready,
input logic free_queue_empty);
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));
shortint bit_cnt = 0;
logic [7:0] rx_shift;
logic [7:0] tx_shift = 8'b00101010;
logic [7:0] rx_buff = '0;
logic byte_ready = 0;
always_ff @ (posedge sclk_rising_edge or posedge rst) begin
if (rst) begin
rx_shift <= '0;
rx_buff <= '0;
bit_cnt <= '0;
byte_ready <= 0;
end
else begin
if (cs) begin
rx_shift <= 0;
rx_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;
rx_buff <= {rx_shift[6:0], mosi};
byte_ready <= 1;
end else begin
byte_ready <= 0;
end
end // else: !if(cs)
end // else: !if(rst)
end // always_ff @ (posedge sclk)
shortint idle_cntdn;
logic rx_drained;
always_ff @ (posedge sys_clk or rst) begin
if (rst) begin
rx_drained <= 0;
rx_pkt_addr <= '1;
rx_byte <= '0;
rx_valid <= 0;
idle_cntdn <= 0;
end else begin
if (!rx_drained && byte_ready) begin
rx_byte <= rx_buff;
rx_valid <= 1;
idle_cntdn <= INTERFACE_IDLE_COUNTDOWN;
rx_drained <= 1;
rx_pkt_addr <= rx_pkt_addr + 1;
end else if (!byte_ready) begin
rx_drained <= 0;
if (!(|idle_cntdn)) begin
rx_valid <= 0;
end else begin
idle_cntdn <= idle_cntdn - 1;
end
end
end
end
always_ff @ (posedge sclk_falling_edge or rst) begin
if (rst) begin
tx_shift <= 8'b00101010;
end else begin
if (cs) begin
tx_shift <= 0;
end else begin
if (bit_cnt == 0) begin
tx_shift <= rx_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_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;
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;
endmodule // async_get_clk_edges