@@ -57,6 +57,12 @@ architecture RTL of SPI_SLAVE is
57
57
58
58
constant BIT_CNT_WIDTH : natural := natural (ceil (log2 (real (WORD_SIZE))));
59
59
60
+ signal sclk_meta : std_logic ;
61
+ signal cs_n_meta : std_logic ;
62
+ signal mosi_meta : std_logic ;
63
+ signal sclk_reg : std_logic ;
64
+ signal cs_n_reg : std_logic ;
65
+ signal mosi_reg : std_logic ;
60
66
signal spi_clk_reg : std_logic ;
61
67
signal spi_clk_redge_en : std_logic ;
62
68
signal spi_clk_fedge_en : std_logic ;
@@ -71,6 +77,23 @@ architecture RTL of SPI_SLAVE is
71
77
72
78
begin
73
79
80
+ -- -------------------------------------------------------------------------
81
+ -- INPUT SYNCHRONIZATION REGISTERS
82
+ -- -------------------------------------------------------------------------
83
+
84
+ -- Synchronization registers to eliminate possible metastability.
85
+ sync_ffs_p : process (CLK)
86
+ begin
87
+ if (rising_edge (CLK)) then
88
+ sclk_meta <= SCLK;
89
+ cs_n_meta <= CS_N;
90
+ mosi_meta <= MOSI;
91
+ sclk_reg <= sclk_meta;
92
+ cs_n_reg <= cs_n_meta;
93
+ mosi_reg <= mosi_meta;
94
+ end if ;
95
+ end process ;
96
+
74
97
-- -------------------------------------------------------------------------
75
98
-- SPI CLOCK REGISTER
76
99
-- -------------------------------------------------------------------------
82
105
if (RST = '1' ) then
83
106
spi_clk_reg <= '0' ;
84
107
else
85
- spi_clk_reg <= SCLK ;
108
+ spi_clk_reg <= sclk_reg ;
86
109
end if ;
87
110
end if ;
88
111
end process ;
@@ -91,23 +114,23 @@ begin
91
114
-- SPI CLOCK EDGES FLAGS
92
115
-- -------------------------------------------------------------------------
93
116
94
- -- Falling edge is detect when SCLK =0 and spi_clk_reg=1.
95
- spi_clk_fedge_en <= not SCLK and spi_clk_reg;
96
- -- Rising edge is detect when SCLK =1 and spi_clk_reg=0.
97
- spi_clk_redge_en <= SCLK and not spi_clk_reg;
117
+ -- Falling edge is detect when sclk_reg =0 and spi_clk_reg=1.
118
+ spi_clk_fedge_en <= not sclk_reg and spi_clk_reg;
119
+ -- Rising edge is detect when sclk_reg =1 and spi_clk_reg=0.
120
+ spi_clk_redge_en <= sclk_reg and not spi_clk_reg;
98
121
99
122
-- -------------------------------------------------------------------------
100
123
-- RECEIVED BITS COUNTER
101
124
-- -------------------------------------------------------------------------
102
125
103
126
-- The counter counts received bits from the master. Counter is enabled when
104
- -- falling edge of SPI clock is detected and not asserted CS_N .
127
+ -- falling edge of SPI clock is detected and not asserted cs_n_reg .
105
128
bit_cnt_p : process (CLK)
106
129
begin
107
130
if (rising_edge (CLK)) then
108
131
if (RST = '1' ) then
109
132
bit_cnt <= (others => '0' );
110
- elsif (spi_clk_fedge_en = '1' and CS_N = '0' ) then
133
+ elsif (spi_clk_fedge_en = '1' and cs_n_reg = '0' ) then
111
134
if (bit_cnt_max = '1' ) then
112
135
bit_cnt <= (others => '0' );
113
136
else
@@ -156,7 +179,7 @@ begin
156
179
if (RST = '1' ) then
157
180
shreg_busy <= '0' ;
158
181
else
159
- if (DIN_VLD = '1' and (CS_N = '1' or rx_data_vld = '1' )) then
182
+ if (DIN_VLD = '1' and (cs_n_reg = '1' or rx_data_vld = '1' )) then
160
183
shreg_busy <= '1' ;
161
184
elsif (rx_data_vld = '1' ) then
162
185
shreg_busy <= '0' ;
@@ -167,9 +190,9 @@ begin
167
190
end if ;
168
191
end process ;
169
192
170
- -- The SPI slave is ready for accept new input data when CS_N is assert and
193
+ -- The SPI slave is ready for accept new input data when cs_n_reg is assert and
171
194
-- shift register not busy or when received data are valid.
172
- slave_ready <= (CS_N and not shreg_busy) or rx_data_vld;
195
+ slave_ready <= (cs_n_reg and not shreg_busy) or rx_data_vld;
173
196
174
197
-- The new input data is loaded into the shift register when the SPI slave
175
198
-- is ready and input data are valid.
@@ -186,8 +209,8 @@ begin
186
209
if (rising_edge (CLK)) then
187
210
if (load_data_en = '1' ) then
188
211
data_shreg <= DIN;
189
- elsif (spi_clk_redge_en = '1' and CS_N = '0' ) then
190
- data_shreg <= data_shreg(WORD_SIZE- 2 downto 0 ) & MOSI ;
212
+ elsif (spi_clk_redge_en = '1' and cs_n_reg = '0' ) then
213
+ data_shreg <= data_shreg(WORD_SIZE- 2 downto 0 ) & mosi_reg ;
191
214
end if ;
192
215
end if ;
193
216
end process ;
@@ -197,13 +220,13 @@ begin
197
220
-- -------------------------------------------------------------------------
198
221
199
222
-- The output MISO register ensures that the bits are transmit to the master
200
- -- when is not assert CS_N and falling edge of SPI clock is detected.
223
+ -- when is not assert cs_n_reg and falling edge of SPI clock is detected.
201
224
miso_p : process (CLK)
202
225
begin
203
226
if (rising_edge (CLK)) then
204
227
if (load_data_en = '1' ) then
205
228
MISO <= DIN(WORD_SIZE- 1 );
206
- elsif (spi_clk_fedge_en = '1' and CS_N = '0' ) then
229
+ elsif (spi_clk_fedge_en = '1' and cs_n_reg = '0' ) then
207
230
MISO <= data_shreg(WORD_SIZE- 1 );
208
231
end if ;
209
232
end if ;
0 commit comments