initial commit: figuring out SPI on the Tang Primer 20K, already 3 devlogs, will commit on a per-devlog/document change basis
This commit is contained in:
1
fabric/src/.gitignore
vendored
Normal file
1
fabric/src/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
obj_dir/
|
106
fabric/src/spi_slave.sv
Normal file
106
fabric/src/spi_slave.sv
Normal file
@ -0,0 +1,106 @@
|
||||
// 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
|
58
fabric/src/tb.sv
Normal file
58
fabric/src/tb.sv
Normal file
@ -0,0 +1,58 @@
|
||||
module tb;
|
||||
timeunit 1ns;
|
||||
timeprecision 1ps;
|
||||
|
||||
logic sys_clk = 0;
|
||||
|
||||
always #3.703 sys_clk = ~sys_clk;
|
||||
|
||||
logic sclk = 0;
|
||||
logic cs = 1;
|
||||
logic mosi = 0;
|
||||
logic miso;
|
||||
logic rst_n = 0;
|
||||
string hello = {'b1111_0000_1111_0000, "_ABCD"};
|
||||
|
||||
spi_slave dut (.sys_clk(sys_clk),
|
||||
.mosi(mosi),
|
||||
.cs(cs),
|
||||
.sclk(sclk),
|
||||
.miso(miso));
|
||||
initial begin
|
||||
#20 rst_n = 1;
|
||||
end
|
||||
|
||||
task spi_test (input logic [7:0] tx_byte,
|
||||
output logic [7:0] rx_byte);
|
||||
begin
|
||||
cs = 0;
|
||||
#30;
|
||||
for(int idx = 1; idx < hello.len(); idx = idx + 1) begin
|
||||
tx_byte = hello[idx];
|
||||
$display("%0d=================================================", $time);
|
||||
for (int i = 7; i >= 0; i = i - 1) begin
|
||||
mosi = tx_byte[i];
|
||||
sclk = 1;
|
||||
#10;
|
||||
sclk = 0;
|
||||
rx_byte[i] = miso;
|
||||
#10;
|
||||
$display("[%0d] received bit: %b", $time, miso);
|
||||
end // for (int i = 7; i >= 0; i = i - 1)
|
||||
$display("[%0d] Sent: %c | %b", $time, tx_byte, tx_byte);
|
||||
$display("[%0d] Received: %c (expected %c)", $time, rx_byte, hello[idx - 1] + 8'd1);
|
||||
$display("[%0d] Received: %b (expected %b)", $time, rx_byte, hello[idx - 1] + 8'd1);
|
||||
$display("%0d=================================================", $time);
|
||||
end
|
||||
cs = 1;
|
||||
#40;
|
||||
end
|
||||
endtask // spi_test
|
||||
|
||||
logic [7:0] tx_data = 8'd65;
|
||||
logic [7:0] rx_data;
|
||||
|
||||
initial begin
|
||||
spi_test(tx_data, rx_data);
|
||||
end
|
||||
endmodule // tb
|
Reference in New Issue
Block a user