Skip to content

Commit 75245d6

Browse files
committed
SPI MASTER: Added DIN_LAST input. Lot of optimalizations and small
edits.
1 parent 322384a commit 75245d6

File tree

3 files changed

+84
-49
lines changed

3 files changed

+84
-49
lines changed

example/spi_loopback.vhd

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,9 +233,10 @@ begin
233233
MISO => M_MISO,
234234
-- USER INTERFACE
235235
ADDR => (others => '0'),
236-
READY => open,
237236
DIN => m_din,
237+
DIN_LAST => '1',
238238
DIN_VLD => m_din_vld,
239+
READY => open,
239240
DOUT => m_dout,
240241
DOUT_VLD => m_dout_vld
241242
);
@@ -261,9 +262,9 @@ begin
261262
MOSI => S_MOSI,
262263
MISO => S_MISO,
263264
-- USER INTERFACE
264-
READY => open,
265265
DIN => s_din,
266266
DIN_VLD => s_din_vld,
267+
READY => open,
267268
DOUT => s_dout,
268269
DOUT_VLD => s_dout_vld
269270
);

rtl/spi_master.vhd

Lines changed: 73 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,18 @@ entity SPI_MASTER is
4242
CLK : in std_logic; -- system clock
4343
RST : in std_logic; -- high active synchronous reset
4444
-- SPI MASTER INTERFACE
45-
SCLK : out std_logic;
46-
CS_N : out std_logic_vector(SLAVE_COUNT-1 downto 0);
47-
MOSI : out std_logic;
48-
MISO : in std_logic;
49-
-- USER INTERFACE
50-
ADDR : in std_logic_vector(integer(ceil(log2(real(SLAVE_COUNT))))-1 downto 0); -- slave address
51-
READY : out std_logic; -- when READY = 1, SPI master is ready to accept input data
52-
DIN : in std_logic_vector(7 downto 0); -- input data for slave
53-
DIN_VLD : in std_logic; -- when DIN_VLD = 1, input data are valid and can be accept
54-
DOUT : out std_logic_vector(7 downto 0); -- output data from slave
45+
SCLK : out std_logic; -- SPI clock
46+
CS_N : out std_logic_vector(SLAVE_COUNT-1 downto 0); -- SPI chip select, active in low
47+
MOSI : out std_logic; -- SPI serial data from master to slave
48+
MISO : in std_logic; -- SPI serial data from slave to master
49+
-- INPUT USER INTERFACE
50+
ADDR : in std_logic_vector(integer(ceil(log2(real(SLAVE_COUNT))))-1 downto 0); -- SPI slave address
51+
DIN : in std_logic_vector(7 downto 0); -- input data for SPI slave
52+
DIN_LAST : in std_logic; -- when DIN_LAST = 1, after transmit these input data is asserted CS_N
53+
DIN_VLD : in std_logic; -- when DIN_VLD = 1, input data are valid
54+
READY : out std_logic; -- when READY = 1, valid input data are accept
55+
-- OUTPUT USER INTERFACE
56+
DOUT : out std_logic_vector(7 downto 0); -- output data from SPI slave
5557
DOUT_VLD : out std_logic -- when DOUT_VLD = 1, output data are valid
5658
);
5759
end SPI_MASTER;
@@ -68,6 +70,7 @@ architecture RTL of SPI_MASTER is
6870
signal sys_clk_cnt_rst : std_logic;
6971
signal spi_clk : std_logic;
7072
signal spi_clk_en : std_logic;
73+
signal din_last_reg_n : std_logic;
7174
signal first_edge_en : std_logic;
7275
signal second_edge_en : std_logic;
7376
signal chip_select_n : std_logic;
@@ -80,7 +83,7 @@ architecture RTL of SPI_MASTER is
8083
signal rx_data_vld : std_logic;
8184
signal master_ready : std_logic;
8285

83-
type state is (idle, first_edge, second_edge, transmit_end, disable_cs);
86+
type state is (idle, first_edge, second_edge, transmit_end, transmit_gap);
8487
signal present_state, next_state : state;
8588

8689
begin
@@ -89,9 +92,7 @@ begin
8992

9093
load_data <= master_ready and DIN_VLD;
9194
READY <= master_ready;
92-
DOUT <= shreg;
93-
DOUT_VLD <= rx_data_vld;
94-
95+
9596
-- -------------------------------------------------------------------------
9697
-- SYSTEM CLOCK COUNTER
9798
-- -------------------------------------------------------------------------
@@ -127,6 +128,24 @@ begin
127128

128129
SCLK <= spi_clk;
129130

131+
-- -------------------------------------------------------------------------
132+
-- BIT COUNTER
133+
-- -------------------------------------------------------------------------
134+
135+
bit_cnt_max <= '1' when (bit_cnt = "111") else '0';
136+
bit_cnt_rst <= RST or not spi_clk_en;
137+
138+
bit_cnt_p : process (CLK)
139+
begin
140+
if (rising_edge(CLK)) then
141+
if (bit_cnt_rst = '1') then
142+
bit_cnt <= (others => '0');
143+
elsif (second_edge_en = '1') then
144+
bit_cnt <= bit_cnt + 1;
145+
end if;
146+
end if;
147+
end process;
148+
130149
-- -------------------------------------------------------------------------
131150
-- SPI MASTER ADDRESSING
132151
-- -------------------------------------------------------------------------
@@ -153,6 +172,21 @@ begin
153172
end process;
154173
end generate;
155174

175+
-- -------------------------------------------------------------------------
176+
-- DIN LAST RESISTER
177+
-- -------------------------------------------------------------------------
178+
179+
din_last_reg_n_p : process (CLK)
180+
begin
181+
if (rising_edge(CLK)) then
182+
if (RST = '1') then
183+
din_last_reg_n <= '0';
184+
elsif (load_data = '1') then
185+
din_last_reg_n <= not DIN_LAST;
186+
end if;
187+
end if;
188+
end process;
189+
156190
-- -------------------------------------------------------------------------
157191
-- MISO SAMPLE REGISTER
158192
-- -------------------------------------------------------------------------
@@ -181,22 +215,20 @@ begin
181215
end if;
182216
end process;
183217

218+
DOUT <= shreg;
184219
MOSI <= shreg(7);
185-
220+
186221
-- -------------------------------------------------------------------------
187-
-- BIT COUNTER
222+
-- DATA OUT VALID RESISTER
188223
-- -------------------------------------------------------------------------
189224

190-
bit_cnt_max <= '1' when (bit_cnt = "111") else '0';
191-
bit_cnt_rst <= RST or not spi_clk_en;
192-
193-
bit_cnt_p : process (CLK)
225+
dout_vld_reg_p : process (CLK)
194226
begin
195227
if (rising_edge(CLK)) then
196-
if (bit_cnt_rst = '1') then
197-
bit_cnt <= (others => '0');
198-
elsif (second_edge_en = '1') then
199-
bit_cnt <= bit_cnt + 1;
228+
if (RST = '1') then
229+
DOUT_VLD <= '0';
230+
else
231+
DOUT_VLD <= rx_data_vld;
200232
end if;
201233
end if;
202234
end process;
@@ -221,9 +253,7 @@ begin
221253
fsm_next_state_p : process (present_state, DIN_VLD, sys_clk_cnt_max,
222254
bit_cnt_max)
223255
begin
224-
225256
case present_state is
226-
227257
when idle =>
228258
if (DIN_VLD = '1') then
229259
next_state <= first_edge;
@@ -239,43 +269,42 @@ begin
239269
end if;
240270

241271
when second_edge =>
242-
if (sys_clk_cnt_max = '1' and bit_cnt_max = '0') then
243-
next_state <= first_edge;
244-
elsif (sys_clk_cnt_max = '1' and bit_cnt_max = '1') then
245-
next_state <= transmit_end;
272+
if (sys_clk_cnt_max = '1') then
273+
if (bit_cnt_max = '1') then
274+
next_state <= transmit_end;
275+
else
276+
next_state <= first_edge;
277+
end if;
246278
else
247279
next_state <= second_edge;
248280
end if;
249281

250282
when transmit_end =>
251-
if (DIN_VLD = '1') then
252-
next_state <= first_edge;
283+
if (sys_clk_cnt_max = '1') then
284+
next_state <= transmit_gap;
253285
else
254-
next_state <= disable_cs;
286+
next_state <= transmit_end;
255287
end if;
256288

257-
when disable_cs =>
289+
when transmit_gap =>
258290
if (sys_clk_cnt_max = '1') then
259291
next_state <= idle;
260292
else
261-
next_state <= disable_cs;
293+
next_state <= transmit_gap;
262294
end if;
263295

264296
when others =>
265297
next_state <= idle;
266-
267298
end case;
268299
end process;
269300

270301
-- OUTPUTS LOGIC
271-
fsm_outputs_p : process (present_state, sys_clk_cnt_max)
302+
fsm_outputs_p : process (present_state, din_last_reg_n, sys_clk_cnt_max)
272303
begin
273-
274304
case present_state is
275-
276305
when idle =>
277306
master_ready <= '1';
278-
chip_select_n <= '1';
307+
chip_select_n <= not din_last_reg_n;
279308
spi_clk_en <= '0';
280309
first_edge_en <= '0';
281310
second_edge_en <= '0';
@@ -298,16 +327,16 @@ begin
298327
rx_data_vld <= '0';
299328

300329
when transmit_end =>
301-
master_ready <= '1';
330+
master_ready <= '0';
302331
chip_select_n <= '0';
303332
spi_clk_en <= '0';
304333
first_edge_en <= '0';
305334
second_edge_en <= '0';
306-
rx_data_vld <= '1';
335+
rx_data_vld <= sys_clk_cnt_max;
307336

308-
when disable_cs =>
337+
when transmit_gap =>
309338
master_ready <= '0';
310-
chip_select_n <= '0';
339+
chip_select_n <= not din_last_reg_n;
311340
spi_clk_en <= '0';
312341
first_edge_en <= '0';
313342
second_edge_en <= '0';
@@ -320,7 +349,6 @@ begin
320349
first_edge_en <= '0';
321350
second_edge_en <= '0';
322351
rx_data_vld <= '0';
323-
324352
end case;
325353
end process;
326354

sim/spi_tb.vhd

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ architecture SIM of SPI_TB is
4848

4949
signal m_addr : std_logic_vector(integer(ceil(log2(real(SLAVE_COUNT))))-1 downto 0);
5050
signal m_din : std_logic_vector(7 downto 0);
51+
signal m_din_last : std_logic;
5152
signal m_din_vld : std_logic;
5253
signal m_ready : std_logic;
5354
signal m_dout : std_logic_vector(7 downto 0);
@@ -77,9 +78,10 @@ begin
7778
MISO => miso,
7879
-- USER INTERFACE
7980
ADDR => m_addr,
80-
READY => m_ready,
8181
DIN => m_din,
82+
DIN_LAST => m_din_last,
8283
DIN_VLD => m_din_vld,
84+
READY => m_ready,
8385
DOUT => m_dout,
8486
DOUT_VLD => m_dout_vld
8587
);
@@ -94,9 +96,9 @@ begin
9496
MOSI => mosi,
9597
MISO => miso,
9698
-- USER INTERFACE
97-
READY => s_ready,
9899
DIN => s_din,
99100
DIN_VLD => s_din_vld,
101+
READY => s_ready,
100102
DOUT => s_dout,
101103
DOUT_VLD => s_dout_vld
102104
);
@@ -122,13 +124,15 @@ begin
122124
m_addr <= (others => '0');
123125
m_din <= (others => 'Z');
124126
m_din_vld <= '0';
127+
m_din_last <= '0';
125128

126129
wait until RST = '0';
127130
wait for 30 ns;
128131
wait until rising_edge(CLK);
129132

130133
m_din <= X"12";
131134
m_din_vld <= '1';
135+
m_din_last <= '0';
132136
wait until m_ready = '0';
133137

134138
m_din <= (others => '0');
@@ -140,10 +144,12 @@ begin
140144

141145
m_din <= X"F4";
142146
m_din_vld <= '1';
147+
m_din_last <= '1';
143148
wait until m_ready = '0';
144149

145150
m_din <= X"47";
146151
m_din_vld <= '1';
152+
m_din_last <= '1';
147153
wait until m_ready = '0';
148154

149155
m_din <= (others => '0');

0 commit comments

Comments
 (0)