forked from SJTU-YONGFU-RESEARCH-GRP/core
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathspi_master.v
More file actions
executable file
·154 lines (142 loc) · 4.79 KB
/
spi_master.v
File metadata and controls
executable file
·154 lines (142 loc) · 4.79 KB
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/**
* SPI Master Controller
*
* This module implements a Serial Peripheral Interface (SPI) master controller
* that can communicate with SPI slave devices. SPI is a synchronous serial
* communication protocol commonly used for interfacing with sensors, memory,
* and other peripheral devices.
*
* Key Features:
* - Full-duplex communication: Simultaneous transmit and receive
* - 8-bit data width: Standard 8-bit SPI transfers
* - Ready/Valid handshake: Standard flow control interface
* - State machine: IDLE, ACTIVE, DONE states
* - Chip select control: Automatic CS_N management
*
* SPI Protocol:
* - Clock generation: Generates SPI clock (SPI_CLK)
* - MOSI: Master Out Slave In (data output)
* - MISO: Master In Slave Out (data input)
* - CS_N: Chip Select (active low)
* - MSB first: Transmits/receives MSB first
*
* Operation:
* - IDLE: Waiting for transaction start
* - ACTIVE: Actively transferring data
* - DONE: Transfer complete, data available
*
* Timing:
* - Clock toggles during ACTIVE state
* - Data sampled on clock edges
* - CS_N asserted during transfer
*
* Use Cases:
* - Sensor interfaces
* - Memory interfaces
* - Peripheral communication
* - Data acquisition systems
*
* @input clk Clock signal
* @input rst_n Active-low reset signal
* @input tx_data[7:0] Transmit data
* @input tx_valid Transmit data valid
* @output tx_ready Ready to accept transmit data
* @output rx_data[7:0] Receive data
* @output rx_valid Receive data valid
*
* SPI Interface:
* @output spi_clk SPI clock signal
* @output spi_mosi SPI Master Out Slave In
* @input spi_miso SPI Master In Slave Out
* @output spi_cs_n SPI Chip Select (active low)
*/
module spi_master (
input wire clk,
input wire rst_n,
input wire [7:0] tx_data,
input wire tx_valid,
output reg tx_ready,
output reg [7:0] rx_data,
output reg rx_valid,
output reg spi_clk,
output reg spi_mosi,
input wire spi_miso,
output reg spi_cs_n
);
// State definitions
localparam IDLE = 2'b00;
localparam ACTIVE = 2'b01;
localparam DONE = 2'b10;
// Registers
/* verilator lint_off UNUSEDSIGNAL */
reg [1:0] state;
reg [3:0] bit_count;
reg [7:0] tx_shift;
reg [7:0] rx_shift;
/* verilator lint_on UNUSEDSIGNAL */
// Debug register to store MISO samples
reg [7:0] debug_miso_samples;
// Main state machine
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
state <= IDLE;
bit_count <= 0;
spi_clk <= 0;
spi_mosi <= 0;
spi_cs_n <= 1;
tx_ready <= 1;
rx_valid <= 0;
rx_data <= 0;
tx_shift <= 0;
rx_shift <= 0;
debug_miso_samples <= 0;
end else begin
case (state)
IDLE: begin
spi_clk <= 0;
spi_cs_n <= 1;
tx_ready <= 1;
rx_valid <= 0;
debug_miso_samples <= 0;
if (tx_valid) begin
tx_ready <= 0;
tx_shift <= tx_data;
bit_count <= 0;
spi_cs_n <= 0;
spi_mosi <= tx_data[7]; // MSB first
state <= ACTIVE;
end
end
ACTIVE: begin
// Toggle SPI clock
spi_clk <= ~spi_clk;
if (spi_clk == 1) begin
// On falling edge (next cycle)
if (bit_count < 7) begin
// Prepare next bit to transmit
spi_mosi <= tx_shift[6]; // Next bit
tx_shift <= {tx_shift[6:0], 1'b0}; // Shift left
end
end else begin
// On rising edge
// Sample MISO
debug_miso_samples[7-bit_count] <= spi_miso; // Store in debug register
rx_shift <= {rx_shift[6:0], spi_miso};
bit_count <= bit_count + 1;
if (bit_count == 7) begin
state <= DONE;
end
end
end
DONE: begin
spi_cs_n <= 1;
spi_clk <= 0;
rx_data <= debug_miso_samples; // Use debug register to ensure correct bit order
rx_valid <= 1;
state <= IDLE;
end
default: state <= IDLE;
endcase
end
end
endmodule