OpenCores
URL https://opencores.org/ocsvn/spi_master_slave/spi_master_slave/trunk

Subversion Repositories spi_master_slave

[/] [spi_master_slave/] [trunk/] [syn/] [spi_master_atlys_top.vhd] - Blame information for rev 24

Details | Compare with Previous | View Log

Line No. Rev Author Line
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 24 jdoin
-- 2011/07/04   v0.01.0040  [JD]    changed all clocks to clock enables, and use the 100MHz board pclk_i to clock all registers.
25 5 jdoin
--                                  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 13 jdoin
-- 2011/08/02   v1.13.0110  [JD]    testbed for continuous transfer in FPGA hardware.
32 5 jdoin
--
33
--
34
----------------------------------------------------------------------------------
35
library ieee;
36
use ieee.std_logic_1164.all;
37 11 jdoin
use ieee.std_logic_arith.all;
38 5 jdoin
 
39
entity spi_master_atlys_top is
40 22 jdoin
    Generic (
41
        N : positive := 8;                              -- 8bit serial word length is default
42
        CPOL : std_logic := '0';                        -- SPI mode selection (mode 0 default)
43
        CPHA : std_logic := '0';                        -- CPOL = clock polarity, CPHA = clock phase.
44
        PREFETCH : positive := 3;                       -- prefetch lookahead cycles
45 24 jdoin
        CLK_PERIOD : time := 10 ns;                     -- clock period for pclk_i (default 100MHz)
46
        DEBOUNCE_TIME : time := 2 us);                  -- switch debounce time (use 200 us for silicon, 2 us for simulation)
47 5 jdoin
    Port (
48 24 jdoin
        sclk_i : in std_logic := 'X';                   -- board clock input 100MHz
49
        pclk_i : in std_logic := 'X';                   -- board clock input 100MHz
50 12 jdoin
        --- SPI interface ---           
51 22 jdoin
        spi_ssel_o : out std_logic;                     -- spi port SSEL
52
        spi_sck_o : out std_logic;                      -- spi port SCK
53
        spi_mosi_o : out std_logic;                     -- spi port MOSI
54
        spi_miso_o : out std_logic;                     -- spi port MISO
55 12 jdoin
        --- input slide switches ---            
56 22 jdoin
        sw_i : in std_logic_vector (7 downto 0);        -- 8 input slide switches
57 12 jdoin
        --- input buttons ---           
58 22 jdoin
        btn_i : in std_logic_vector (5 downto 0);       -- 6 input push buttons
59 12 jdoin
        --- output LEDs ----            
60 22 jdoin
        led_o : out std_logic_vector (7 downto 0);      -- output leds
61 5 jdoin
        --- debug outputs ---
62 20 jdoin
        s_do_o : out std_logic_vector (7 downto 0);
63
        m_do_o : out std_logic_vector (7 downto 0);
64 22 jdoin
        m_state_o : out std_logic_vector (3 downto 0);  -- master spi fsm state
65
        s_state_o : out std_logic_vector (3 downto 0);  -- slave spi fsm state
66
        dbg_o : out std_logic_vector (11 downto 0)      -- 12 generic debug pins
67 5 jdoin
    );
68
end spi_master_atlys_top;
69
 
70 22 jdoin
architecture rtl of spi_master_atlys_top is
71 5 jdoin
 
72
    --=============================================================================================
73
    -- Constants
74
    --=============================================================================================
75 24 jdoin
    -- clock divider count values from pclk_i (100MHz board clock)
76 5 jdoin
    -- these constants shall not be zero
77 10 jdoin
    constant FSM_CE_DIV         : integer := 1;     -- fsm operates at 100MHz
78 5 jdoin
    constant SPI_2X_CLK_DIV     : integer := 1;     -- 50MHz SPI clock
79 10 jdoin
    constant SAMP_CE_DIV        : integer := 1;     -- board signals sampled at 100MHz
80 5 jdoin
 
81
    -- button definitions
82
    constant btRESET    : integer := 0;             -- these are constants to use as btn_i(x)
83
    constant btUP       : integer := 1;
84
    constant btLEFT     : integer := 2;
85
    constant btDOWN     : integer := 3;
86
    constant btRIGHT    : integer := 4;
87
    constant btCENTER   : integer := 5;
88
 
89
    --=============================================================================================
90
    -- Type definitions
91
    --=============================================================================================
92 13 jdoin
    type fsm_master_write_state_type is
93
            (st_reset, st_wait_spi_idle, st_wait_new_switch, st_send_spi_data_sw, st_wait_spi_ack_sw,
94
            st_send_spi_data_1, st_wait_spi_ack_1, st_wait_spi_di_req_2, st_wait_spi_ack_2,
95
            st_wait_spi_di_req_3, st_wait_spi_ack_3);
96 5 jdoin
 
97 13 jdoin
    type fsm_slave_write_state_type is
98 20 jdoin
            (st_reset, st_wait_spi_start, st_wait_spi_di_req_2, st_wait_spi_ack_2, st_wait_spi_do_valid_1,
99 13 jdoin
            st_wait_spi_di_req_3, st_wait_spi_ack_3, st_wait_spi_end);
100
 
101
    type fsm_slave_read_state_type is
102
            (st_reset, st_wait_spi_do_valid_1, st_wait_spi_n_do_valid_1, st_wait_spi_do_valid_2,
103
            st_wait_spi_n_do_valid_2, st_wait_spi_do_valid_3, st_wait_spi_n_do_valid_3);
104
 
105 5 jdoin
    --=============================================================================================
106
    -- Signals for state machine control
107
    --=============================================================================================
108 13 jdoin
    signal m_wr_st_reg  : fsm_master_write_state_type := st_reset;
109
    signal m_wr_st_next : fsm_master_write_state_type := st_reset;
110
    signal s_wr_st_reg  : fsm_slave_write_state_type := st_reset;
111
    signal s_wr_st_next : fsm_slave_write_state_type := st_reset;
112
    signal s_rd_st_reg  : fsm_slave_read_state_type := st_reset;
113
    signal s_rd_st_next : fsm_slave_read_state_type := st_reset;
114 5 jdoin
 
115
    --=============================================================================================
116
    -- Signals for internal operation
117
    --=============================================================================================
118 10 jdoin
    --- clock enable signals ---
119
    signal samp_ce          : std_logic := '1';         -- clock enable for sample inputs
120
    signal fsm_ce           : std_logic := '1';         -- clock enable for fsm logic
121
    --- switch debouncer signals ---
122
    signal sw_data          : std_logic_vector (7 downto 0) := (others => '0'); -- debounced switch data
123
    signal sw_reg           : std_logic_vector (7 downto 0) := (others => '0'); -- registered switch data 
124
    signal sw_next          : std_logic_vector (7 downto 0) := (others => '0'); -- combinatorial switch data
125
    signal new_switch       : std_logic := '0';                                 -- detector for new switch data
126
    --- pushbutton debouncer signals ---
127
    signal btn_data         : std_logic_vector (5 downto 0) := (others => '0'); -- debounced state of pushbuttons
128
    signal btn_reg          : std_logic_vector (5 downto 0) := (others => '0'); -- registered button data 
129
    signal btn_next         : std_logic_vector (5 downto 0) := (others => '0'); -- combinatorial button data
130
    signal new_button       : std_logic := '0';                                 -- detector for new button data
131
    --- spi port signals ---
132
    -- spi bus wires
133
    signal spi_ssel         : std_logic;
134
    signal spi_sck          : std_logic;
135
    signal spi_mosi         : std_logic;
136
    signal spi_miso         : std_logic;
137
    -- spi master port control signals
138
    signal spi_rst_reg      : std_logic := '1';
139
    signal spi_rst_next     : std_logic := '1';
140
    signal spi_ssel_reg     : std_logic;
141
    signal spi_wren_reg_m   : std_logic := '0';
142
    signal spi_wren_next_m  : std_logic := '0';
143
    -- spi master port flow control flags
144
    signal spi_di_req_m     : std_logic;
145
    signal spi_do_valid_m   : std_logic;
146
    -- spi master port parallel data bus
147
    signal spi_di_reg_m     : std_logic_vector (N-1 downto 0) := (others => '0');
148
    signal spi_di_next_m    : std_logic_vector (N-1 downto 0) := (others => '0');
149
    signal spi_do_m         : std_logic_vector (N-1 downto 0);
150
    signal spi_wr_ack_m     : std_logic;
151
    -- spi slave port control signals
152
    signal spi_wren_reg_s   : std_logic := '1';
153 12 jdoin
    signal spi_wren_next_s  : std_logic := '1';
154 10 jdoin
    -- spi slave port flow control flags
155
    signal spi_di_req_s     : std_logic;
156
    signal spi_do_valid_s   : std_logic;
157
    -- spi slave port parallel data bus
158 12 jdoin
    signal spi_di_reg_s     : std_logic_vector (N-1 downto 0) := (others => '0');
159 10 jdoin
    signal spi_di_next_s    : std_logic_vector (N-1 downto 0) := (others => '0');
160
    signal spi_do_s         : std_logic_vector (N-1 downto 0);
161 13 jdoin
    signal spi_wr_ack_s     : std_logic;
162 10 jdoin
    signal spi_rx_bit_s     : std_logic;
163 20 jdoin
    -- spi debug data --
164
    signal spi_state_m      : std_logic_vector (3 downto 0);
165
    signal spi_state_s      : std_logic_vector (3 downto 0);
166 13 jdoin
    -- slave data output regs --
167
    signal s_do_1_reg       : std_logic_vector (N-1 downto 0) := (others => '0');
168
    signal s_do_1_next      : std_logic_vector (N-1 downto 0) := (others => '0');
169
    signal s_do_2_reg       : std_logic_vector (N-1 downto 0) := (others => '0');
170
    signal s_do_2_next      : std_logic_vector (N-1 downto 0) := (others => '0');
171
    signal s_do_3_reg       : std_logic_vector (N-1 downto 0) := (others => '0');
172
    signal s_do_3_next      : std_logic_vector (N-1 downto 0) := (others => '0');
173 5 jdoin
    -- other signals
174 10 jdoin
    signal clear            : std_logic := '0';
175
    -- debug output signals
176 13 jdoin
    signal leds_reg         : std_logic_vector (7 downto 0);
177
    signal leds_next        : std_logic_vector (7 downto 0) := (others => '0');
178 12 jdoin
    signal dbg              : std_logic_vector (11 downto 0) := (others => '0');
179 5 jdoin
begin
180
 
181
    --=============================================================================================
182 10 jdoin
    -- COMPONENT INSTANTIATIONS FOR THE CORES UNDER TEST
183 5 jdoin
    --=============================================================================================
184 13 jdoin
    -- spi master port: data and control signals driven by the master fsm
185 10 jdoin
    Inst_spi_master_port: entity work.spi_master(rtl)
186 22 jdoin
        generic map (N => N, CPOL => CPOL, CPHA => CPHA, PREFETCH => PREFETCH, SPI_2X_CLK_DIV => SPI_2X_CLK_DIV)
187 5 jdoin
        port map(
188 24 jdoin
            sclk_i => sclk_i,                   -- system clock is used for serial and parallel ports
189
            pclk_i => pclk_i,
190 5 jdoin
            rst_i => spi_rst_reg,
191
            spi_ssel_o => spi_ssel,
192
            spi_sck_o => spi_sck,
193
            spi_mosi_o => spi_mosi,
194 13 jdoin
            spi_miso_i => spi_miso,             -- driven by the spi slave 
195 10 jdoin
            di_req_o => spi_di_req_m,
196
            di_i => spi_di_reg_m,
197 12 jdoin
            wren_i => spi_wren_reg_m,
198 13 jdoin
            wr_ack_o => spi_wr_ack_m,
199 10 jdoin
            do_valid_o => spi_do_valid_m,
200 20 jdoin
            do_o => spi_do_m,
201 12 jdoin
            ------------ debug pins ------------
202 20 jdoin
            state_dbg_o => spi_state_m          -- debug: internal state register
203 5 jdoin
        );
204
 
205 13 jdoin
    -- spi slave port: data and control signals driven by the slave fsm
206 10 jdoin
    Inst_spi_slave_port: entity work.spi_slave(rtl)
207 22 jdoin
        generic map (N => N, CPOL => CPOL, CPHA => CPHA, PREFETCH => PREFETCH)
208 10 jdoin
        port map(
209 24 jdoin
            clk_i => pclk_i,
210 13 jdoin
            spi_ssel_i => spi_ssel,             -- driven by the spi master
211
            spi_sck_i => spi_sck,               -- driven by the spi master
212
            spi_mosi_i => spi_mosi,             -- driven by the spi master
213 10 jdoin
            spi_miso_o => spi_miso,
214
            di_req_o => spi_di_req_s,
215
            di_i => spi_di_reg_s,
216
            wren_i => spi_wren_reg_s,
217 13 jdoin
            wr_ack_o => spi_wr_ack_s,
218 10 jdoin
            do_valid_o => spi_do_valid_s,
219 20 jdoin
            do_o => spi_do_s,
220 12 jdoin
            ------------ debug pins ------------
221 20 jdoin
            state_dbg_o => spi_state_s          -- debug: internal state register
222 10 jdoin
        );
223
 
224 5 jdoin
    -- debounce for the input switches, with new data strobe output
225
    Inst_sw_debouncer: entity work.grp_debouncer(rtl)
226 22 jdoin
        generic map (N => 8, CNT_VAL => DEBOUNCE_TIME / CLK_PERIOD) -- debounce 8 inputs with selected settling time
227 5 jdoin
        port map(
228 24 jdoin
            clk_i => pclk_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 22 jdoin
        generic map (N => 6, CNT_VAL => DEBOUNCE_TIME / CLK_PERIOD) -- debounce 6 inputs with selected settling time
236 5 jdoin
        port map(
237 24 jdoin
            clk_i => pclk_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 13 jdoin
    -- All registers are clocked directly from the 100MHz system clock.
262
    -- The clock generation block derives 2 clock enable signals, divided down from the 100MHz input 
263
    -- clock. 
264
    --      input sample clock enable, 
265
    --      fsm clock enable,
266 5 jdoin
    -----------------------------------------------------------------------------------------------
267
    -- generate the sampling clock enable from the 100MHz board input clock 
268 24 jdoin
    samp_ce_gen_proc: process (pclk_i) is
269 5 jdoin
        variable clk_cnt : integer range SAMP_CE_DIV-1 downto 0 := 0;
270
    begin
271 24 jdoin
        if pclk_i'event and pclk_i = '1' then
272 5 jdoin
            if clk_cnt = SAMP_CE_DIV-1 then
273 13 jdoin
                samp_ce <= '1';                 -- generate a single pulse every SAMP_CE_DIV clocks
274 5 jdoin
                clk_cnt := 0;
275
            else
276
                samp_ce <= '0';
277
                clk_cnt := clk_cnt + 1;
278
            end if;
279
        end if;
280
    end process samp_ce_gen_proc;
281
    -- generate the fsm clock enable from the 100MHz board input clock 
282 24 jdoin
    fsm_ce_gen_proc: process (pclk_i) is
283 5 jdoin
        variable clk_cnt : integer range FSM_CE_DIV-1 downto 0 := 0;
284
    begin
285 24 jdoin
        if pclk_i'event and pclk_i = '1' then
286 5 jdoin
            if clk_cnt = FSM_CE_DIV-1 then
287 13 jdoin
                fsm_ce <= '1';                  -- generate a single pulse every FSM_CE_DIV clocks
288 5 jdoin
                clk_cnt := 0;
289
            else
290
                fsm_ce <= '0';
291
                clk_cnt := clk_cnt + 1;
292
            end if;
293
        end if;
294
    end process fsm_ce_gen_proc;
295
 
296
    --=============================================================================================
297
    -- INPUTS LOGIC
298
    --=============================================================================================
299
    -- registered inputs
300 24 jdoin
    samp_inputs_proc: process (pclk_i) is
301 5 jdoin
    begin
302 24 jdoin
        if pclk_i'event and pclk_i = '1' then
303 5 jdoin
            if samp_ce = '1' then
304 10 jdoin
                clear <= btn_data(btUP);        -- clear is button UP
305 13 jdoin
                leds_reg <= leds_next;          -- update LEDs with spi_slave received data
306 5 jdoin
            end if;
307
        end if;
308
    end process samp_inputs_proc;
309
 
310
    --=============================================================================================
311 10 jdoin
    --  REGISTER TRANSFER PROCESSES
312 5 jdoin
    --=============================================================================================
313 13 jdoin
    -- fsm state and data registers: synchronous to the system clock
314 24 jdoin
    fsm_reg_proc : process (pclk_i) is
315 5 jdoin
    begin
316
        -- FFD registers clocked on rising edge and cleared on sync 'clear'
317 24 jdoin
        if pclk_i'event and pclk_i = '1' then
318 13 jdoin
            if clear = '1' then                     -- sync reset
319
                m_wr_st_reg <= st_reset;            -- only provide local reset for the state registers
320 5 jdoin
            else
321
                if fsm_ce = '1' then
322 13 jdoin
                    m_wr_st_reg <= m_wr_st_next;    -- master write state register update
323 5 jdoin
                end if;
324
            end if;
325
        end if;
326 13 jdoin
        -- FFD registers clocked on rising edge and cleared on ssel = '1'
327 24 jdoin
        if pclk_i'event and pclk_i = '1' then
328 13 jdoin
            if spi_ssel = '1' then                  -- sync reset
329
                s_wr_st_reg <= st_reset;            -- only provide local reset for the state registers
330
                s_rd_st_reg <= st_reset;
331
            else
332
                if fsm_ce = '1' then
333
                    s_wr_st_reg <= s_wr_st_next;    -- slave write state register update
334
                    s_rd_st_reg <= s_rd_st_next;    -- slave read state register update
335
                end if;
336
            end if;
337
        end if;
338 5 jdoin
        -- FFD registers clocked on rising edge, with no reset
339 24 jdoin
        if pclk_i'event and pclk_i = '1' then
340 5 jdoin
            if fsm_ce = '1' then
341 13 jdoin
                --------- master write fsm signals -----------
342 10 jdoin
                spi_wren_reg_m <= spi_wren_next_m;
343
                spi_di_reg_m <= spi_di_next_m;
344 5 jdoin
                spi_rst_reg <= spi_rst_next;
345
                spi_ssel_reg <= spi_ssel;
346
                sw_reg <= sw_next;
347
                btn_reg <= btn_next;
348 13 jdoin
                --------- slave write fsm signals -----------
349
                spi_wren_reg_s <= spi_wren_next_s;
350
                spi_di_reg_s <= spi_di_next_s;
351
                --------- slave read fsm signals -----------
352
                s_do_1_reg <= s_do_1_next;
353
                s_do_2_reg <= s_do_2_next;
354
                s_do_3_reg <= s_do_3_next;
355 5 jdoin
            end if;
356
        end if;
357
    end process fsm_reg_proc;
358
 
359
    --=============================================================================================
360 10 jdoin
    --  COMBINATORIAL NEXT-STATE LOGIC PROCESSES
361 5 jdoin
    --=============================================================================================
362
    -- edge detector for new switch data
363 22 jdoin
    new_switch_proc: new_switch <= '1' when sw_data /= sw_reg else '0';     -- '1' for change edge
364 13 jdoin
 
365 5 jdoin
    -- edge detector for new button data
366 22 jdoin
    new_button_proc: new_button <= '1' when btn_data /= btn_reg else '0';   -- '1' for change edge
367 13 jdoin
 
368 22 jdoin
    -- master port write fsmd logic
369 13 jdoin
    fsm_m_wr_combi_proc: process ( m_wr_st_reg, spi_wren_reg_m, spi_di_reg_m, spi_di_req_m, spi_wr_ack_m,
370
                                spi_ssel_reg, spi_rst_reg, sw_data, sw_reg, new_switch, btn_data, btn_reg,
371 20 jdoin
                                new_button, clear) is
372 5 jdoin
    begin
373
        spi_rst_next <= spi_rst_reg;
374 10 jdoin
        spi_di_next_m <= spi_di_reg_m;
375
        spi_wren_next_m <= spi_wren_reg_m;
376 5 jdoin
        sw_next <= sw_reg;
377
        btn_next <= btn_reg;
378 13 jdoin
        m_wr_st_next <= m_wr_st_reg;
379
        case m_wr_st_reg is
380 5 jdoin
            when st_reset =>
381
                spi_rst_next <= '1';                        -- place spi interface on reset
382 10 jdoin
                spi_di_next_m <= (others => '0');           -- clear spi data port
383
                spi_wren_next_m <= '0';                     -- deassert write enable
384 13 jdoin
                m_wr_st_next <= st_wait_spi_idle;
385 5 jdoin
 
386
            when st_wait_spi_idle =>
387 12 jdoin
                spi_wren_next_m <= '0';                     -- remove write strobe on next clock
388 5 jdoin
                if spi_ssel_reg = '1' then
389
                    spi_rst_next <= '0';                    -- remove reset when interface is idle
390 13 jdoin
                    m_wr_st_next <= st_wait_new_switch;
391 5 jdoin
                end if;
392
 
393
            when st_wait_new_switch =>
394
                if new_switch = '1' then                    -- wait for new stable switch data
395
                    sw_next <= sw_data;                     -- load new switch data (end the mismatch condition)
396 13 jdoin
                    m_wr_st_next <= st_send_spi_data_sw;
397 5 jdoin
                elsif new_button = '1' then
398
                    btn_next <= btn_data;                   -- load new button data (end the mismatch condition)
399 20 jdoin
                    if clear = '0' then
400 13 jdoin
                        if btn_data(btDOWN) = '1' then
401
                            m_wr_st_next <= st_send_spi_data_sw;
402
                        elsif btn_data(btLEFT) = '1' then
403
                            m_wr_st_next <= st_send_spi_data_1;
404
                        elsif btn_data(btCENTER) = '1' then
405
                            m_wr_st_next <= st_send_spi_data_1;
406
                        elsif btn_data(btRIGHT) = '1' then
407
                            m_wr_st_next <= st_send_spi_data_1;
408
                        end if;
409 5 jdoin
                    end if;
410
                end if;
411
 
412 13 jdoin
            when st_send_spi_data_sw =>
413 10 jdoin
                spi_di_next_m <= sw_reg;                    -- load switch register to the spi port
414
                spi_wren_next_m <= '1';                     -- write data on next clock
415 13 jdoin
                m_wr_st_next <= st_wait_spi_ack_sw;
416 5 jdoin
 
417 13 jdoin
            when st_wait_spi_ack_sw =>                      -- the actual write happens on this state
418
                if spi_wr_ack_m = '1' then
419
                    spi_wren_next_m <= '0';                 -- remove write strobe on next clock
420
                    m_wr_st_next <= st_wait_spi_di_req_2;
421
                end if;
422
 
423
            when st_send_spi_data_1 =>
424
                spi_di_next_m <= X"A1";                     -- load switch register to the spi port
425
                spi_wren_next_m <= '1';                     -- write data on next clock
426
                m_wr_st_next <= st_wait_spi_ack_1;
427
 
428
            when st_wait_spi_ack_1 =>                       -- the actual write happens on this state
429
                if spi_wr_ack_m = '1' then
430
                    spi_wren_next_m <= '0';                 -- remove write strobe on next clock
431
                    m_wr_st_next <= st_wait_spi_di_req_2;
432
                end if;
433
 
434
            when st_wait_spi_di_req_2 =>
435
                if spi_di_req_m = '1' then
436
                    spi_di_next_m <= X"A2";
437
                    spi_wren_next_m <= '1';
438
                    m_wr_st_next <= st_wait_spi_ack_2;
439
                end if;
440 5 jdoin
 
441 13 jdoin
            when st_wait_spi_ack_2 =>                       -- the actual write happens on this state
442
                if spi_wr_ack_m = '1' then
443
                    spi_wren_next_m <= '0';                 -- remove write strobe on next clock
444
                    m_wr_st_next <= st_wait_spi_di_req_3;
445
                end if;
446
 
447
            when st_wait_spi_di_req_3 =>
448
                if spi_di_req_m = '1' then
449
                    spi_di_next_m <= X"A3";
450
                    spi_wren_next_m <= '1';
451
                    m_wr_st_next <= st_wait_spi_ack_3;
452
                end if;
453
 
454
            when st_wait_spi_ack_3 =>                       -- the actual write happens on this state
455
                if spi_wr_ack_m = '1' then
456
                    spi_wren_next_m <= '0';                 -- remove write strobe on next clock
457
                    m_wr_st_next <= st_wait_spi_idle;       -- wait transmission end
458
                end if;
459
 
460 5 jdoin
            when others =>
461 13 jdoin
                m_wr_st_next <= st_reset;                   -- state st_reset is safe state
462
 
463 5 jdoin
        end case;
464 13 jdoin
    end process fsm_m_wr_combi_proc;
465 5 jdoin
 
466 22 jdoin
    -- slave port write fsmd logic
467 20 jdoin
    fsm_s_wr_combi_proc: process (  s_wr_st_reg, spi_di_req_s, spi_wr_ack_s, spi_do_valid_s,
468 13 jdoin
                                    spi_di_reg_s, spi_wren_reg_s, spi_ssel_reg) is
469
    begin
470
        spi_wren_next_s <= spi_wren_reg_s;
471
        spi_di_next_s <= spi_di_reg_s;
472
        s_wr_st_next <= s_wr_st_reg;
473
        case s_wr_st_reg is
474
            when st_reset =>
475 22 jdoin
                spi_di_next_s <= X"51";                     -- write first data word
476 13 jdoin
                spi_wren_next_s <= '1';                     -- set write enable
477
                s_wr_st_next <= st_wait_spi_start;
478
 
479
            when st_wait_spi_start =>
480
                if spi_ssel_reg = '0' then                  -- wait for slave select
481
                    spi_wren_next_s <= '0';                 -- remove write enable
482
                    s_wr_st_next <= st_wait_spi_di_req_2;
483
                end if;
484
 
485
            when st_wait_spi_di_req_2 =>
486
                if spi_di_req_s = '1' then
487 20 jdoin
--                    spi_di_next_s <= X"D2";               -- do not write on this cycle (cycle miss)
488
--                    spi_wren_next_s <= '1';
489 22 jdoin
--                    s_wr_st_next <= st_wait_spi_ack_2;
490 20 jdoin
                    s_wr_st_next <= st_wait_spi_do_valid_1;
491 13 jdoin
                end if;
492
 
493
            when st_wait_spi_ack_2 =>                       -- the actual write happens on this state
494
                if spi_wr_ack_s = '1' then
495
                    spi_wren_next_s <= '0';                 -- remove write strobe on next clock
496
                    s_wr_st_next <= st_wait_spi_di_req_3;
497
                end if;
498
 
499 20 jdoin
            when st_wait_spi_do_valid_1 =>
500
                if spi_do_valid_s = '1' then
501
                    s_wr_st_next <= st_wait_spi_di_req_3;
502
                end if;
503
 
504 13 jdoin
            when st_wait_spi_di_req_3 =>
505
                if spi_di_req_s = '1' then
506
                    spi_di_next_s <= X"D3";
507
                    spi_wren_next_s <= '1';
508
                    s_wr_st_next <= st_wait_spi_ack_3;
509
                end if;
510
 
511
            when st_wait_spi_ack_3 =>                       -- the actual write happens on this state
512
                if spi_wr_ack_s = '1' then
513
                    spi_wren_next_s <= '0';                 -- remove write strobe on next clock
514
                    s_wr_st_next <= st_wait_spi_end;        -- wait transmission end
515
                end if;
516
 
517
            when st_wait_spi_end =>                         -- wait interface to be deselected
518
                if spi_ssel_reg = '1' then
519
                    s_wr_st_next <= st_reset;               -- wait transmission start
520
                end if;
521
 
522
            when others =>
523
                s_wr_st_next <= st_reset;                   -- state st_reset is safe state
524
 
525
        end case;
526
    end process fsm_s_wr_combi_proc;
527
 
528 22 jdoin
    -- slave port read fsmd logic
529 13 jdoin
    fsm_s_rd_combi_proc: process ( s_rd_st_reg, spi_do_valid_s, spi_do_s, s_do_1_reg, s_do_2_reg, s_do_3_reg) is
530
    begin
531
        s_do_1_next <= s_do_1_reg;
532
        s_do_2_next <= s_do_2_reg;
533
        s_do_3_next <= s_do_3_reg;
534
        s_rd_st_next <= s_rd_st_reg;
535
        case s_rd_st_reg is
536
            when st_reset =>
537
                s_rd_st_next <= st_wait_spi_do_valid_1;
538
 
539
            when st_wait_spi_do_valid_1 =>
540
                if spi_do_valid_s = '1' then                -- wait for receive data ready
541
                    s_do_1_next <= spi_do_s;                -- read data from output port
542
                    s_rd_st_next <= st_wait_spi_n_do_valid_1;
543
                end if;
544
 
545
            when st_wait_spi_n_do_valid_1 =>
546
                if spi_do_valid_s = '0' then
547
                    s_rd_st_next <= st_wait_spi_do_valid_2;
548
                end if;
549
 
550
            when st_wait_spi_do_valid_2 =>
551
                if spi_do_valid_s = '1' then                -- wait for receive data ready
552
                    s_do_2_next <= spi_do_s;                -- read data from output port
553
                    s_rd_st_next <= st_wait_spi_n_do_valid_2;
554
                end if;
555
 
556
            when st_wait_spi_n_do_valid_2 =>
557
                if spi_do_valid_s = '0' then
558
                    s_rd_st_next <= st_wait_spi_do_valid_3;
559
                end if;
560
 
561
            when st_wait_spi_do_valid_3 =>
562
                if spi_do_valid_s = '1' then                -- wait for receive data ready
563
                    s_do_3_next <= spi_do_s;                -- read data from output port
564
                    s_rd_st_next <= st_wait_spi_n_do_valid_3;
565
                end if;
566
 
567
            when st_wait_spi_n_do_valid_3 =>
568
                if spi_do_valid_s = '0' then
569
                    s_rd_st_next <= st_reset;
570
                end if;
571
 
572
            when others =>
573
                s_rd_st_next <= st_reset;                   -- state st_reset is safe state
574
 
575
        end case;
576
    end process fsm_s_rd_combi_proc;
577
 
578
    leds_combi_proc: process (btn_data, leds_reg, s_do_1_reg, s_do_2_reg, s_do_3_reg) is
579
    begin
580
        leds_next <= leds_reg;
581
        if btn_data(btRIGHT) = '1' then
582
            leds_next <= s_do_3_reg;
583
        elsif btn_data(btCENTER) = '1' then
584
            leds_next <= s_do_2_reg;
585
        elsif btn_data(btLEFT) = '1' then
586
            leds_next <= s_do_1_reg;
587
        elsif btn_data(btDOWN) = '1' then
588
            leds_next <= s_do_1_reg;
589
        end if;
590
    end process leds_combi_proc;
591
 
592 5 jdoin
    --=============================================================================================
593
    --  OUTPUT LOGIC PROCESSES
594
    --=============================================================================================
595
    -- connect the spi output wires
596 10 jdoin
    spi_ssel_o_proc:        spi_ssel_o      <= spi_ssel;
597
    spi_sck_o_proc:         spi_sck_o       <= spi_sck;
598
    spi_mosi_o_proc:        spi_mosi_o      <= spi_mosi;
599
    spi_miso_o_proc:        spi_miso_o      <= spi_miso;
600 12 jdoin
    -- connect leds_reg signal to LED outputs
601 13 jdoin
    led_o_proc:             led_o           <= leds_reg;
602 5 jdoin
 
603
    --=============================================================================================
604
    --  DEBUG LOGIC PROCESSES
605
    --=============================================================================================
606
    -- connect the debug vector outputs
607 10 jdoin
    dbg_o_proc:             dbg_o <= dbg;
608 13 jdoin
 
609
    -- connect debug port pins to spi ports instances interface signals
610
    -- master signals mapped on dbg
611
    dbg(11) <= spi_wren_reg_m;
612
    dbg(10) <= spi_wr_ack_m;
613
    dbg(9)  <= spi_di_req_m;
614
    dbg(8)  <= spi_do_valid_m;
615
    -- slave signals mapped on dbg
616
    dbg(7)  <= spi_wren_reg_s;
617
    dbg(6)  <= spi_wr_ack_s;
618
    dbg(5)  <= spi_di_req_s;
619
    dbg(4)  <= spi_do_valid_s;
620 22 jdoin
    dbg(3 downto 0) <= spi_state_s;
621 20 jdoin
    -- specific ports to test on testbench
622
    s_do_o <= spi_do_s;
623
    m_do_o <= spi_do_m;
624
    m_state_o <= spi_state_m;  -- master spi fsm state
625
    s_state_o <= spi_state_s;  -- slave spi fsm state
626 10 jdoin
 
627 22 jdoin
end rtl;
628 5 jdoin
 

powered by: WebSVN 2.1.0

© copyright 1999-2020 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.