1 |
5 |
jdoin |
----------------------------------------------------------------------------------
|
2 |
12 |
jdoin |
-- Author: Jonny Doin, jdoin@opencores.org, jonnydoin@gmail.com
|
3 |
5 |
jdoin |
--
|
4 |
|
|
-- Create Date: 01:21:32 06/30/2011
|
5 |
|
|
-- Design Name:
|
6 |
|
|
-- Module Name: spi_master_atlys_top
|
7 |
|
|
-- Project Name: spi_master_slave
|
8 |
|
|
-- Target Devices: Spartan-6 LX45
|
9 |
|
|
-- Tool versions: ISE 13.1
|
10 |
|
|
-- Description:
|
11 |
10 |
jdoin |
-- This is a verification project for the Digilent Atlys board, to test the SPI_MASTER, SPI_SLAVE and GRP_DEBOUNCE cores.
|
12 |
5 |
jdoin |
-- It uses the board's 100MHz clock input, and clocks all sequential logic at this clock.
|
13 |
|
|
--
|
14 |
10 |
jdoin |
-- See the "spi_master_atlys.ucf" file for pin assignments.
|
15 |
5 |
jdoin |
-- The test circuit uses the VHDCI connector on the Atlys to implement a 16-pin debug port to be used
|
16 |
|
|
-- with a Tektronix MSO2014. The 16 debug pins are brought to 2 8x2 headers that form a umbilical
|
17 |
|
|
-- digital pod port.
|
18 |
|
|
--
|
19 |
|
|
------------------------------ REVISION HISTORY -----------------------------------------------------------------------
|
20 |
|
|
--
|
21 |
|
|
-- 2011/07/02 v0.01.0010 [JD] implemented a wire-through from switches to LEDs, just to test the toolchain. It worked!
|
22 |
|
|
-- 2011/07/03 v0.01.0020 [JD] added clock input, and a simple LED blinker for each LED.
|
23 |
|
|
-- 2011/07/03 v0.01.0030 [JD] added clear input, and instantiated a SPI_MASTER from my OpenCores project.
|
24 |
|
|
-- 2011/07/04 v0.01.0040 [JD] changed all clocks to clock enables, and use the 100MHz board gclk_i to clock all registers.
|
25 |
|
|
-- this change made the design go up to 288MHz, after synthesis.
|
26 |
|
|
-- 2011/07/07 v0.03.0050 [JD] implemented a 16pin umbilical port for the MSO2014 in the Atlys VmodBB board, and moved all
|
27 |
|
|
-- external monitoring pins to the VHDCI ports.
|
28 |
|
|
-- 2011/07/10 v1.10.0075 [JD] verified spi_master_slave at 50MHz, 25MHz, 16.666MHz, 12.5MHz, 10MHz, 8.333MHz, 7.1428MHz,
|
29 |
|
|
-- 6.25MHz, 1MHz and 500kHz
|
30 |
12 |
jdoin |
-- 2011/07/29 v1.12.0105 [JD] spi_master.vhd and spi_slave_vhd changed to fix CPHA='1' bug.
|
31 |
5 |
jdoin |
--
|
32 |
|
|
--
|
33 |
|
|
----------------------------------------------------------------------------------
|
34 |
|
|
library ieee;
|
35 |
|
|
use ieee.std_logic_1164.all;
|
36 |
11 |
jdoin |
use ieee.std_logic_arith.all;
|
37 |
5 |
jdoin |
|
38 |
|
|
entity spi_master_atlys_top is
|
39 |
|
|
Port (
|
40 |
12 |
jdoin |
gclk_i : in std_logic := 'X'; -- board clock input 100MHz
|
41 |
|
|
--- SPI interface ---
|
42 |
|
|
spi_ssel_o : out std_logic; -- spi port SSEL
|
43 |
|
|
spi_sck_o : out std_logic; -- spi port SCK
|
44 |
|
|
spi_mosi_o : out std_logic; -- spi port MOSI
|
45 |
|
|
spi_miso_o : out std_logic; -- spi port MISO
|
46 |
|
|
--- input slide switches ---
|
47 |
|
|
sw_i : in std_logic_vector (7 downto 0); -- 8 input slide switches
|
48 |
|
|
--- input buttons ---
|
49 |
|
|
btn_i : in std_logic_vector (5 downto 0); -- 6 input push buttons
|
50 |
|
|
--- output LEDs ----
|
51 |
|
|
led_o : out std_logic_vector (7 downto 0); -- output leds
|
52 |
5 |
jdoin |
--- debug outputs ---
|
53 |
12 |
jdoin |
dbg_o : out std_logic_vector (11 downto 0) -- 12 generic debug pins
|
54 |
5 |
jdoin |
);
|
55 |
|
|
end spi_master_atlys_top;
|
56 |
|
|
|
57 |
|
|
architecture behavioral of spi_master_atlys_top is
|
58 |
|
|
|
59 |
|
|
--=============================================================================================
|
60 |
|
|
-- Constants
|
61 |
|
|
--=============================================================================================
|
62 |
|
|
-- clock divider count values from gclk_i (100MHz board clock)
|
63 |
|
|
-- these constants shall not be zero
|
64 |
10 |
jdoin |
constant FSM_CE_DIV : integer := 1; -- fsm operates at 100MHz
|
65 |
5 |
jdoin |
constant SPI_2X_CLK_DIV : integer := 1; -- 50MHz SPI clock
|
66 |
10 |
jdoin |
constant SAMP_CE_DIV : integer := 1; -- board signals sampled at 100MHz
|
67 |
5 |
jdoin |
-- spi port generics
|
68 |
11 |
jdoin |
constant N : integer := 8; -- 8 bits
|
69 |
12 |
jdoin |
constant CPOL : std_logic := '1';
|
70 |
|
|
constant CPHA : std_logic := '1';
|
71 |
5 |
jdoin |
|
72 |
|
|
-- button definitions
|
73 |
|
|
constant btRESET : integer := 0; -- these are constants to use as btn_i(x)
|
74 |
|
|
constant btUP : integer := 1;
|
75 |
|
|
constant btLEFT : integer := 2;
|
76 |
|
|
constant btDOWN : integer := 3;
|
77 |
|
|
constant btRIGHT : integer := 4;
|
78 |
|
|
constant btCENTER : integer := 5;
|
79 |
|
|
|
80 |
|
|
--=============================================================================================
|
81 |
|
|
-- Type definitions
|
82 |
|
|
--=============================================================================================
|
83 |
|
|
type fsm_state_type is (st_reset, st_wait_spi_idle, st_wait_new_switch,
|
84 |
12 |
jdoin |
st_send_spi_data, st_wait_spi_ack );
|
85 |
5 |
jdoin |
|
86 |
|
|
--=============================================================================================
|
87 |
|
|
-- Signals for state machine control
|
88 |
|
|
--=============================================================================================
|
89 |
10 |
jdoin |
signal state_reg : fsm_state_type := st_reset;
|
90 |
|
|
signal state_next : fsm_state_type := st_reset;
|
91 |
5 |
jdoin |
|
92 |
|
|
--=============================================================================================
|
93 |
|
|
-- Signals for internal operation
|
94 |
|
|
--=============================================================================================
|
95 |
10 |
jdoin |
--- clock enable signals ---
|
96 |
|
|
signal samp_ce : std_logic := '1'; -- clock enable for sample inputs
|
97 |
|
|
signal fsm_ce : std_logic := '1'; -- clock enable for fsm logic
|
98 |
|
|
--- switch debouncer signals ---
|
99 |
|
|
signal sw_data : std_logic_vector (7 downto 0) := (others => '0'); -- debounced switch data
|
100 |
|
|
signal sw_reg : std_logic_vector (7 downto 0) := (others => '0'); -- registered switch data
|
101 |
|
|
signal sw_next : std_logic_vector (7 downto 0) := (others => '0'); -- combinatorial switch data
|
102 |
|
|
signal new_switch : std_logic := '0'; -- detector for new switch data
|
103 |
|
|
--- pushbutton debouncer signals ---
|
104 |
|
|
signal btn_data : std_logic_vector (5 downto 0) := (others => '0'); -- debounced state of pushbuttons
|
105 |
|
|
signal btn_reg : std_logic_vector (5 downto 0) := (others => '0'); -- registered button data
|
106 |
|
|
signal btn_next : std_logic_vector (5 downto 0) := (others => '0'); -- combinatorial button data
|
107 |
|
|
signal new_button : std_logic := '0'; -- detector for new button data
|
108 |
|
|
--- spi port signals ---
|
109 |
|
|
-- spi bus wires
|
110 |
|
|
signal spi_ssel : std_logic;
|
111 |
|
|
signal spi_sck : std_logic;
|
112 |
|
|
signal spi_mosi : std_logic;
|
113 |
|
|
signal spi_miso : std_logic;
|
114 |
|
|
-- spi master port control signals
|
115 |
|
|
signal spi_rst_reg : std_logic := '1';
|
116 |
|
|
signal spi_rst_next : std_logic := '1';
|
117 |
|
|
signal spi_ssel_reg : std_logic;
|
118 |
|
|
signal spi_wren_reg_m : std_logic := '0';
|
119 |
|
|
signal spi_wren_next_m : std_logic := '0';
|
120 |
|
|
-- spi master port flow control flags
|
121 |
|
|
signal spi_di_req_m : std_logic;
|
122 |
|
|
signal spi_do_valid_m : std_logic;
|
123 |
|
|
-- spi master port parallel data bus
|
124 |
|
|
signal spi_di_reg_m : std_logic_vector (N-1 downto 0) := (others => '0');
|
125 |
|
|
signal spi_di_next_m : std_logic_vector (N-1 downto 0) := (others => '0');
|
126 |
|
|
signal spi_do_m : std_logic_vector (N-1 downto 0);
|
127 |
|
|
-- spi master port debug flags
|
128 |
|
|
signal spi_rx_bit_m : std_logic;
|
129 |
|
|
signal spi_wr_ack_m : std_logic;
|
130 |
12 |
jdoin |
signal state_dbg_m : std_logic_vector (5 downto 0);
|
131 |
10 |
jdoin |
-- spi slave port control signals
|
132 |
|
|
signal spi_wren_reg_s : std_logic := '1';
|
133 |
12 |
jdoin |
signal spi_wren_next_s : std_logic := '1';
|
134 |
10 |
jdoin |
-- spi slave port flow control flags
|
135 |
|
|
signal spi_di_req_s : std_logic;
|
136 |
|
|
signal spi_do_valid_s : std_logic;
|
137 |
|
|
-- spi slave port parallel data bus
|
138 |
12 |
jdoin |
signal spi_di_reg_s : std_logic_vector (N-1 downto 0) := (others => '0');
|
139 |
10 |
jdoin |
signal spi_di_next_s : std_logic_vector (N-1 downto 0) := (others => '0');
|
140 |
|
|
signal spi_do_s : std_logic_vector (N-1 downto 0);
|
141 |
|
|
-- spi slave port debug flags
|
142 |
|
|
signal spi_rx_bit_s : std_logic;
|
143 |
|
|
signal spi_wr_ack_s : std_logic;
|
144 |
12 |
jdoin |
signal state_dbg_s : std_logic_vector (5 downto 0);
|
145 |
5 |
jdoin |
-- other signals
|
146 |
10 |
jdoin |
signal clear : std_logic := '0';
|
147 |
|
|
-- debug output signals
|
148 |
|
|
signal leds_reg : std_logic_vector (7 downto 0) := (others => '0');
|
149 |
12 |
jdoin |
signal dbg : std_logic_vector (11 downto 0) := (others => '0');
|
150 |
5 |
jdoin |
begin
|
151 |
|
|
|
152 |
|
|
--=============================================================================================
|
153 |
10 |
jdoin |
-- COMPONENT INSTANTIATIONS FOR THE CORES UNDER TEST
|
154 |
5 |
jdoin |
--=============================================================================================
|
155 |
10 |
jdoin |
-- spi master port:
|
156 |
|
|
-- receives parallel data from the slide switches, transmits to slave port.
|
157 |
|
|
-- receives serial data from slave port, sends to 8bit parallel debug port.
|
158 |
|
|
Inst_spi_master_port: entity work.spi_master(rtl)
|
159 |
11 |
jdoin |
generic map (N => N, CPOL => CPOL, CPHA => CPHA, PREFETCH => 3, SPI_2X_CLK_DIV => SPI_2X_CLK_DIV)
|
160 |
5 |
jdoin |
port map(
|
161 |
10 |
jdoin |
sclk_i => gclk_i, -- system clock is used for serial and parallel ports
|
162 |
|
|
pclk_i => gclk_i,
|
163 |
5 |
jdoin |
rst_i => spi_rst_reg,
|
164 |
|
|
spi_ssel_o => spi_ssel,
|
165 |
|
|
spi_sck_o => spi_sck,
|
166 |
|
|
spi_mosi_o => spi_mosi,
|
167 |
10 |
jdoin |
spi_miso_i => spi_miso,
|
168 |
|
|
di_req_o => spi_di_req_m,
|
169 |
|
|
di_i => spi_di_reg_m,
|
170 |
12 |
jdoin |
wren_i => spi_wren_reg_m,
|
171 |
10 |
jdoin |
do_valid_o => spi_do_valid_m,
|
172 |
|
|
do_o => spi_do_m,
|
173 |
12 |
jdoin |
------------ debug pins ------------
|
174 |
|
|
-- rx_bit_reg_o => spi_rx_bit_m,
|
175 |
|
|
-- state_dbg_o => state_dbg_m, -- monitor internal master state register
|
176 |
|
|
-- sck_ena_o => sck_ena_m, -- monitor internal sck_ena register
|
177 |
11 |
jdoin |
-- wren_o => spi_wren_o,
|
178 |
12 |
jdoin |
wr_ack_o => spi_wr_ack_m -- monitor wren ack from inside spi port
|
179 |
5 |
jdoin |
);
|
180 |
|
|
|
181 |
12 |
jdoin |
-- state_dbg_o(3 downto 0) <= state_dbg_m(3 downto 0); -- connect master state debug port
|
182 |
|
|
-- sck_ena_o <= sck_ena_m; -- sck_ena debug port
|
183 |
|
|
-- spi_rx_bit_m_o <= spi_rx_bit_m; -- connect rx_bit monitor for master port
|
184 |
10 |
jdoin |
|
185 |
|
|
-- spi slave port
|
186 |
|
|
-- receives parallel data from the pushbuttons, transmits to master port.
|
187 |
|
|
-- receives serial data from master port, sends to the 8 LEDs.
|
188 |
|
|
Inst_spi_slave_port: entity work.spi_slave(rtl)
|
189 |
11 |
jdoin |
generic map (N => N, CPOL => CPOL, CPHA => CPHA, PREFETCH => 3)
|
190 |
10 |
jdoin |
port map(
|
191 |
|
|
clk_i => gclk_i,
|
192 |
|
|
spi_ssel_i => spi_ssel, -- generated by the spi master
|
193 |
|
|
spi_sck_i => spi_sck, -- generated by the spi master
|
194 |
|
|
spi_mosi_i => spi_mosi,
|
195 |
|
|
spi_miso_o => spi_miso,
|
196 |
|
|
di_req_o => spi_di_req_s,
|
197 |
|
|
di_i => spi_di_reg_s,
|
198 |
|
|
wren_i => spi_wren_reg_s,
|
199 |
|
|
do_valid_o => spi_do_valid_s,
|
200 |
12 |
jdoin |
do_o => spi_do_s,
|
201 |
|
|
------------ debug pins ------------
|
202 |
|
|
state_dbg_o => state_dbg_s, -- monitor internal state register
|
203 |
|
|
rx_bit_next_o => spi_rx_bit_s,
|
204 |
|
|
wr_ack_o => dbg(5),
|
205 |
|
|
do_transfer_o => dbg(4)
|
206 |
10 |
jdoin |
);
|
207 |
|
|
|
208 |
12 |
jdoin |
-- connect debug port pins to slave instance interface signals
|
209 |
|
|
dbg(7) <= spi_rx_bit_s;
|
210 |
|
|
dbg(6) <= spi_wren_reg_s;
|
211 |
|
|
dbg(3) <= spi_do_valid_s;
|
212 |
|
|
dbg(2) <= spi_di_req_s;
|
213 |
|
|
dbg(1) <= '0';
|
214 |
|
|
dbg(0) <= '0';
|
215 |
|
|
|
216 |
|
|
dbg(11 downto 8) <= state_dbg_s(3 downto 0);-- connect state register
|
217 |
|
|
|
218 |
11 |
jdoin |
spi_di_reg_s(7) <= btn_data(btLEFT); -- get the slave transmit data from pushbuttons
|
219 |
|
|
spi_di_reg_s(6) <= btn_data(btCENTER);
|
220 |
|
|
spi_di_reg_s(5 downto 1) <= B"10101";
|
221 |
|
|
spi_di_reg_s(0) <= btn_data(btRIGHT);
|
222 |
|
|
spi_wren_reg_s <= '1'; -- fix wren to '1', for continuous load of transmit data
|
223 |
10 |
jdoin |
|
224 |
5 |
jdoin |
-- debounce for the input switches, with new data strobe output
|
225 |
|
|
Inst_sw_debouncer: entity work.grp_debouncer(rtl)
|
226 |
12 |
jdoin |
generic map (N => 8, CNT_VAL => 20000) -- debounce 8 inputs with 200 us settling time
|
227 |
5 |
jdoin |
port map(
|
228 |
10 |
jdoin |
clk_i => gclk_i, -- system clock
|
229 |
5 |
jdoin |
data_i => sw_i, -- noisy input data
|
230 |
10 |
jdoin |
data_o => sw_data -- registered stable output data
|
231 |
12 |
jdoin |
);
|
232 |
5 |
jdoin |
|
233 |
|
|
-- debounce for the input pushbuttons, with new data strobe output
|
234 |
|
|
Inst_btn_debouncer: entity work.grp_debouncer(rtl)
|
235 |
12 |
jdoin |
generic map (N => 6, CNT_VAL => 20000) -- debounce 6 inputs with 200 us settling time
|
236 |
5 |
jdoin |
port map(
|
237 |
10 |
jdoin |
clk_i => gclk_i, -- system clock
|
238 |
5 |
jdoin |
data_i => btn_i, -- noisy input data
|
239 |
10 |
jdoin |
data_o => btn_data -- registered stable output data
|
240 |
12 |
jdoin |
);
|
241 |
5 |
jdoin |
|
242 |
|
|
--=============================================================================================
|
243 |
|
|
-- CONSTANTS CONSTRAINTS CHECKING
|
244 |
|
|
--=============================================================================================
|
245 |
|
|
-- clock dividers shall not be zero
|
246 |
11 |
jdoin |
assert FSM_CE_DIV > 0
|
247 |
|
|
report "Constant 'FSM_CE_DIV' should not be zero"
|
248 |
5 |
jdoin |
severity FAILURE;
|
249 |
|
|
-- minimum prefetch lookahead check
|
250 |
11 |
jdoin |
assert SPI_2X_CLK_DIV > 0
|
251 |
|
|
report "Constant 'SPI_2X_CLK_DIV' should not be zero"
|
252 |
5 |
jdoin |
severity FAILURE;
|
253 |
|
|
-- maximum prefetch lookahead check
|
254 |
11 |
jdoin |
assert SAMP_CE_DIV > 0
|
255 |
|
|
report "Constant 'SAMP_CE_DIV' should not be zero"
|
256 |
5 |
jdoin |
severity FAILURE;
|
257 |
|
|
|
258 |
|
|
--=============================================================================================
|
259 |
|
|
-- CLOCK GENERATION
|
260 |
|
|
--=============================================================================================
|
261 |
|
|
-- The clock generation block derives 3 internal clocks, divided down from the 100MHz input clock
|
262 |
|
|
-- core clock,
|
263 |
|
|
-- spi 2x base clock,
|
264 |
|
|
-- fsm clock,
|
265 |
|
|
-----------------------------------------------------------------------------------------------
|
266 |
|
|
-- generate the sampling clock enable from the 100MHz board input clock
|
267 |
|
|
samp_ce_gen_proc: process (gclk_i) is
|
268 |
|
|
variable clk_cnt : integer range SAMP_CE_DIV-1 downto 0 := 0;
|
269 |
|
|
begin
|
270 |
|
|
if gclk_i'event and gclk_i = '1' then
|
271 |
|
|
if clk_cnt = SAMP_CE_DIV-1 then
|
272 |
|
|
samp_ce <= '1';
|
273 |
|
|
clk_cnt := 0;
|
274 |
|
|
else
|
275 |
|
|
samp_ce <= '0';
|
276 |
|
|
clk_cnt := clk_cnt + 1;
|
277 |
|
|
end if;
|
278 |
|
|
end if;
|
279 |
|
|
end process samp_ce_gen_proc;
|
280 |
|
|
-- generate the fsm clock enable from the 100MHz board input clock
|
281 |
|
|
fsm_ce_gen_proc: process (gclk_i) is
|
282 |
|
|
variable clk_cnt : integer range FSM_CE_DIV-1 downto 0 := 0;
|
283 |
|
|
begin
|
284 |
|
|
if gclk_i'event and gclk_i = '1' then
|
285 |
|
|
if clk_cnt = FSM_CE_DIV-1 then
|
286 |
|
|
fsm_ce <= '1';
|
287 |
|
|
clk_cnt := 0;
|
288 |
|
|
else
|
289 |
|
|
fsm_ce <= '0';
|
290 |
|
|
clk_cnt := clk_cnt + 1;
|
291 |
|
|
end if;
|
292 |
|
|
end if;
|
293 |
|
|
end process fsm_ce_gen_proc;
|
294 |
|
|
|
295 |
|
|
--=============================================================================================
|
296 |
|
|
-- INPUTS LOGIC
|
297 |
|
|
--=============================================================================================
|
298 |
|
|
-- registered inputs
|
299 |
10 |
jdoin |
samp_inputs_proc: process (gclk_i) is
|
300 |
5 |
jdoin |
begin
|
301 |
10 |
jdoin |
if gclk_i'event and gclk_i = '1' then
|
302 |
5 |
jdoin |
if samp_ce = '1' then
|
303 |
10 |
jdoin |
clear <= btn_data(btUP); -- clear is button UP
|
304 |
|
|
leds_reg <= spi_do_s; -- update LEDs with spi_slave received data
|
305 |
5 |
jdoin |
end if;
|
306 |
|
|
end if;
|
307 |
|
|
end process samp_inputs_proc;
|
308 |
|
|
|
309 |
|
|
--=============================================================================================
|
310 |
10 |
jdoin |
-- REGISTER TRANSFER PROCESSES
|
311 |
5 |
jdoin |
--=============================================================================================
|
312 |
|
|
-- fsm state and data registers: synchronous to the spi base reference clock
|
313 |
10 |
jdoin |
fsm_reg_proc : process (gclk_i) is
|
314 |
5 |
jdoin |
begin
|
315 |
|
|
-- FFD registers clocked on rising edge and cleared on sync 'clear'
|
316 |
10 |
jdoin |
if gclk_i'event and gclk_i = '1' then
|
317 |
5 |
jdoin |
if clear = '1' then -- sync reset
|
318 |
|
|
state_reg <= st_reset; -- only provide local reset for the state register
|
319 |
|
|
else
|
320 |
|
|
if fsm_ce = '1' then
|
321 |
|
|
state_reg <= state_next; -- state register
|
322 |
|
|
end if;
|
323 |
|
|
end if;
|
324 |
|
|
end if;
|
325 |
|
|
-- FFD registers clocked on rising edge, with no reset
|
326 |
10 |
jdoin |
if gclk_i'event and gclk_i = '1' then
|
327 |
5 |
jdoin |
if fsm_ce = '1' then
|
328 |
10 |
jdoin |
spi_wren_reg_m <= spi_wren_next_m;
|
329 |
|
|
spi_di_reg_m <= spi_di_next_m;
|
330 |
5 |
jdoin |
spi_rst_reg <= spi_rst_next;
|
331 |
|
|
spi_ssel_reg <= spi_ssel;
|
332 |
|
|
sw_reg <= sw_next;
|
333 |
|
|
btn_reg <= btn_next;
|
334 |
|
|
end if;
|
335 |
|
|
end if;
|
336 |
|
|
end process fsm_reg_proc;
|
337 |
|
|
|
338 |
|
|
--=============================================================================================
|
339 |
10 |
jdoin |
-- COMBINATORIAL NEXT-STATE LOGIC PROCESSES
|
340 |
5 |
jdoin |
--=============================================================================================
|
341 |
|
|
-- edge detector for new switch data
|
342 |
10 |
jdoin |
new_switch_proc: new_switch <= '1' when sw_data /= sw_reg else '0'; -- '1' for difference
|
343 |
5 |
jdoin |
-- edge detector for new button data
|
344 |
10 |
jdoin |
new_button_proc: new_button <= '1' when btn_data /= btn_reg else '0'; -- '1' for difference
|
345 |
5 |
jdoin |
-- fsm state and combinatorial logic
|
346 |
|
|
-- the sequencer will wait for a new switch combination, and send the switch data to the spi port
|
347 |
10 |
jdoin |
fsm_combi_proc: process ( state_reg, spi_wren_reg_m, spi_di_reg_m, spi_di_req_m, spi_wr_ack_m, -- spi_di_reg_s,
|
348 |
|
|
spi_wren_reg_s, spi_ssel_reg, spi_rst_reg, sw_data,
|
349 |
|
|
sw_reg, new_switch, btn_data, btn_reg, new_button) is
|
350 |
5 |
jdoin |
begin
|
351 |
|
|
spi_rst_next <= spi_rst_reg;
|
352 |
10 |
jdoin |
spi_di_next_m <= spi_di_reg_m;
|
353 |
|
|
spi_wren_next_m <= spi_wren_reg_m;
|
354 |
5 |
jdoin |
sw_next <= sw_reg;
|
355 |
|
|
btn_next <= btn_reg;
|
356 |
|
|
state_next <= state_reg;
|
357 |
|
|
case state_reg is
|
358 |
|
|
when st_reset =>
|
359 |
|
|
spi_rst_next <= '1'; -- place spi interface on reset
|
360 |
10 |
jdoin |
spi_di_next_m <= (others => '0'); -- clear spi data port
|
361 |
|
|
spi_di_next_s <= (others => '0'); -- clear spi data port
|
362 |
|
|
spi_wren_next_m <= '0'; -- deassert write enable
|
363 |
|
|
spi_wren_next_s <= '0'; -- deassert write enable
|
364 |
5 |
jdoin |
state_next <= st_wait_spi_idle;
|
365 |
|
|
|
366 |
|
|
when st_wait_spi_idle =>
|
367 |
12 |
jdoin |
spi_wren_next_m <= '0'; -- remove write strobe on next clock
|
368 |
5 |
jdoin |
if spi_ssel_reg = '1' then
|
369 |
|
|
spi_rst_next <= '0'; -- remove reset when interface is idle
|
370 |
|
|
state_next <= st_wait_new_switch;
|
371 |
|
|
end if;
|
372 |
|
|
|
373 |
|
|
when st_wait_new_switch =>
|
374 |
|
|
if new_switch = '1' then -- wait for new stable switch data
|
375 |
|
|
sw_next <= sw_data; -- load new switch data (end the mismatch condition)
|
376 |
|
|
state_next <= st_send_spi_data;
|
377 |
|
|
elsif new_button = '1' then
|
378 |
|
|
btn_next <= btn_data; -- load new button data (end the mismatch condition)
|
379 |
10 |
jdoin |
if btn_data /= B"000001" then
|
380 |
5 |
jdoin |
state_next <= st_send_spi_data;
|
381 |
|
|
end if;
|
382 |
|
|
end if;
|
383 |
|
|
|
384 |
|
|
when st_send_spi_data =>
|
385 |
10 |
jdoin |
spi_di_next_m <= sw_reg; -- load switch register to the spi port
|
386 |
|
|
spi_wren_next_m <= '1'; -- write data on next clock
|
387 |
5 |
jdoin |
state_next <= st_wait_spi_ack;
|
388 |
|
|
|
389 |
|
|
when st_wait_spi_ack => -- the actual write happens on this state
|
390 |
10 |
jdoin |
spi_di_next_m <= sw_reg; -- load switch register to the spi port
|
391 |
12 |
jdoin |
spi_wren_next_m <= '0'; -- remove write strobe on next clock
|
392 |
|
|
state_next <= st_wait_spi_idle;
|
393 |
5 |
jdoin |
|
394 |
|
|
when others =>
|
395 |
|
|
state_next <= st_reset; -- state st_reset is safe state
|
396 |
|
|
end case;
|
397 |
|
|
end process fsm_combi_proc;
|
398 |
|
|
|
399 |
|
|
--=============================================================================================
|
400 |
|
|
-- OUTPUT LOGIC PROCESSES
|
401 |
|
|
--=============================================================================================
|
402 |
|
|
-- connect the spi output wires
|
403 |
10 |
jdoin |
spi_ssel_o_proc: spi_ssel_o <= spi_ssel;
|
404 |
|
|
spi_sck_o_proc: spi_sck_o <= spi_sck;
|
405 |
|
|
spi_mosi_o_proc: spi_mosi_o <= spi_mosi;
|
406 |
|
|
spi_miso_o_proc: spi_miso_o <= spi_miso;
|
407 |
12 |
jdoin |
-- connect leds_reg signal to LED outputs
|
408 |
|
|
led_o_proc: led_o <= leds_reg;
|
409 |
5 |
jdoin |
|
410 |
|
|
--=============================================================================================
|
411 |
|
|
-- DEBUG LOGIC PROCESSES
|
412 |
|
|
--=============================================================================================
|
413 |
|
|
-- connect the debug vector outputs
|
414 |
10 |
jdoin |
dbg_o_proc: dbg_o <= dbg;
|
415 |
|
|
|
416 |
5 |
jdoin |
end behavioral;
|
417 |
|
|
|