-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathspi.v
73 lines (64 loc) · 1.49 KB
/
spi.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
module spi #(
parameter [31:0] ADDR = 32'hffff_ffff
) (
input clk,
input resetn,
output spi_clk,
input spi_miso,
output spi_mosi,
input mem_valid,
input [31:0] mem_addr,
input [31:0] mem_wdata,
input [3:0] mem_wstrb,
output spi_ready,
output spi_sel,
output [31:0] spi_rdata
);
// layout:
// ADDR -- SPI transmit/receive data
wire mem_sel = mem_valid && (mem_addr == ADDR);
wire mem_read = mem_sel && (mem_wstrb == 4'b0000);
wire mem_write = mem_sel && mem_wstrb[0];
wire [7:0] tx_byte;
wire tx_dv;
wire tx_ready;
wire rx_dv;
wire [7:0] rx_byte;
reg rx_has_data;
reg [7:0] rx_data;
wire read_ready;
// rx logic
always @(posedge clk) begin
if (~resetn) begin
rx_has_data <= 0;
rx_data <= 8'h0;
end else begin
if (read_ready && ~rx_dv) begin
rx_has_data <= 0;
end else if (rx_dv) begin
rx_data <= rx_byte;
rx_has_data <= 1;
end
end
end
assign spi_rdata = {24'h0, rx_data};
assign read_ready = rx_has_data && mem_read;
// tx logic
assign tx_byte = mem_wdata[7:0];
assign tx_dv = tx_ready && mem_write;
wire write_ready = tx_dv;
SPI_Master spi_master(
.i_Rst_L (resetn),
.i_Clk (clk),
.i_TX_Byte (tx_byte),
.i_TX_DV (tx_dv),
.o_TX_Ready (tx_ready),
.o_RX_DV (rx_dv),
.o_RX_Byte (rx_byte),
.o_SPI_Clk (spi_clk),
.i_SPI_MISO (spi_miso),
.o_SPI_MOSI (spi_mosi)
);
assign spi_ready = read_ready || write_ready;
assign spi_sel = mem_sel;
endmodule