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 11

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 5 jdoin
----------------------------------------------------------------------------------
2
-- Engineer: Jonny Doin
3
-- 
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 11 jdoin
-- 2011/07/18   v1.12.0105  [JD]    spi_master.vhd changed to fix CPHA='1' clock glitch.  
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
        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 10 jdoin
        spi_miso_o : out std_logic;                 -- spi port MISO
46 5 jdoin
        --- 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
        --- debug outputs ---
53 10 jdoin
        dbg_o : out std_logic_vector (7 downto 0);  -- 10 generic debug pins
54 5 jdoin
        --- spi debug pins ---
55 10 jdoin
        spi_rx_bit_m_o : out std_logic;             -- master rx bit feedback
56
        spi_rx_bit_s_o : out std_logic;             -- slave rx bit feedback
57
        spi_do_valid_o : out std_logic;             -- spi data valid
58 11 jdoin
        spi_di_req_o : out std_logic                -- spi data request
59
--        spi_wren_o : out std_logic;                 -- spi write enable
60
--        spi_wren_ack_o : out std_logic              -- spi write enable ack
61 5 jdoin
    );
62
end spi_master_atlys_top;
63
 
64
architecture behavioral of spi_master_atlys_top is
65
 
66
    --=============================================================================================
67
    -- Constants
68
    --=============================================================================================
69
    -- clock divider count values from gclk_i (100MHz board clock)
70
    -- these constants shall not be zero
71 10 jdoin
    constant FSM_CE_DIV         : integer := 1;     -- fsm operates at 100MHz
72 5 jdoin
    constant SPI_2X_CLK_DIV     : integer := 1;     -- 50MHz SPI clock
73 10 jdoin
    constant SAMP_CE_DIV        : integer := 1;     -- board signals sampled at 100MHz
74 5 jdoin
    -- spi port generics
75 11 jdoin
    constant N      : integer   := 8;               -- 8 bits
76
    constant CPOL   : std_logic := '0';
77
    constant CPHA   : std_logic := '0';
78 5 jdoin
 
79
    -- button definitions
80
    constant btRESET    : integer := 0;             -- these are constants to use as btn_i(x)
81
    constant btUP       : integer := 1;
82
    constant btLEFT     : integer := 2;
83
    constant btDOWN     : integer := 3;
84
    constant btRIGHT    : integer := 4;
85
    constant btCENTER   : integer := 5;
86
 
87
    --=============================================================================================
88
    -- Type definitions
89
    --=============================================================================================
90
    type fsm_state_type is (st_reset, st_wait_spi_idle, st_wait_new_switch,
91 11 jdoin
                            st_send_spi_data, st_wait_spi_ack, st_wait_spi_finish );
92 5 jdoin
 
93
    --=============================================================================================
94
    -- Signals for state machine control
95
    --=============================================================================================
96 10 jdoin
    signal state_reg        : fsm_state_type := st_reset;
97
    signal state_next       : fsm_state_type := st_reset;
98 5 jdoin
 
99
    --=============================================================================================
100
    -- Signals for internal operation
101
    --=============================================================================================
102 10 jdoin
    --- clock enable signals ---
103
    signal samp_ce          : std_logic := '1';         -- clock enable for sample inputs
104
    signal fsm_ce           : std_logic := '1';         -- clock enable for fsm logic
105
    --- switch debouncer signals ---
106
    signal sw_data          : std_logic_vector (7 downto 0) := (others => '0'); -- debounced switch data
107
    signal sw_reg           : std_logic_vector (7 downto 0) := (others => '0'); -- registered switch data 
108
    signal sw_next          : std_logic_vector (7 downto 0) := (others => '0'); -- combinatorial switch data
109
    signal new_switch       : std_logic := '0';                                 -- detector for new switch data
110
    --- pushbutton debouncer signals ---
111
    signal btn_data         : std_logic_vector (5 downto 0) := (others => '0'); -- debounced state of pushbuttons
112
    signal btn_reg          : std_logic_vector (5 downto 0) := (others => '0'); -- registered button data 
113
    signal btn_next         : std_logic_vector (5 downto 0) := (others => '0'); -- combinatorial button data
114
    signal new_button       : std_logic := '0';                                 -- detector for new button data
115
    --- spi port signals ---
116
    -- spi bus wires
117
    signal spi_ssel         : std_logic;
118
    signal spi_sck          : std_logic;
119
    signal spi_mosi         : std_logic;
120
    signal spi_miso         : std_logic;
121
    -- spi master port control signals
122
    signal spi_rst_reg      : std_logic := '1';
123
    signal spi_rst_next     : std_logic := '1';
124
    signal spi_ssel_reg     : std_logic;
125
    signal spi_wren_reg_m   : std_logic := '0';
126
    signal spi_wren_next_m  : std_logic := '0';
127
    -- spi master port flow control flags
128
    signal spi_di_req_m     : std_logic;
129
    signal spi_do_valid_m   : std_logic;
130
    -- spi master port parallel data bus
131
    signal spi_di_reg_m     : std_logic_vector (N-1 downto 0) := (others => '0');
132
    signal spi_di_next_m    : std_logic_vector (N-1 downto 0) := (others => '0');
133
    signal spi_do_m         : std_logic_vector (N-1 downto 0);
134
    -- spi master port debug flags
135
    signal spi_rx_bit_m     : std_logic;
136
    signal spi_wr_ack_m     : std_logic;
137
    -- spi slave port control signals
138
    signal spi_wren_reg_s   : std_logic := '1';
139
    signal spi_wren_next_s  : std_logic := '0';
140
    -- spi slave port flow control flags
141
    signal spi_di_req_s     : std_logic;
142
    signal spi_do_valid_s   : std_logic;
143
    -- spi slave port parallel data bus
144
    signal spi_di_reg_s     : std_logic_vector (N-1 downto 0) := (7 => '1', 6 => '0', 5 => '1', others => '0');
145
    signal spi_di_next_s    : std_logic_vector (N-1 downto 0) := (others => '0');
146
    signal spi_do_s         : std_logic_vector (N-1 downto 0);
147
    -- spi slave port debug flags
148
    signal spi_rx_bit_s     : std_logic;
149
    signal spi_wr_ack_s     : std_logic;
150 5 jdoin
    -- other signals
151 10 jdoin
    signal clear            : std_logic := '0';
152
    -- debug output signals
153
    signal leds_reg         : std_logic_vector (7 downto 0) := (others => '0');
154
    signal dbg              : std_logic_vector (7 downto 0) := (others => '0');
155 5 jdoin
begin
156
 
157
    --=============================================================================================
158 10 jdoin
    -- COMPONENT INSTANTIATIONS FOR THE CORES UNDER TEST
159 5 jdoin
    --=============================================================================================
160 10 jdoin
    -- spi master port: 
161
    --      receives parallel data from the slide switches, transmits to slave port.
162
    --      receives serial data from slave port, sends to 8bit parallel debug port.
163
    Inst_spi_master_port: entity work.spi_master(rtl)
164 11 jdoin
        generic map (N => N, CPOL => CPOL, CPHA => CPHA, PREFETCH => 3, SPI_2X_CLK_DIV => SPI_2X_CLK_DIV)
165 5 jdoin
        port map(
166 10 jdoin
            sclk_i => gclk_i,                   -- system clock is used for serial and parallel ports
167
            pclk_i => gclk_i,
168 5 jdoin
            rst_i => spi_rst_reg,
169
            spi_ssel_o => spi_ssel,
170
            spi_sck_o => spi_sck,
171
            spi_mosi_o => spi_mosi,
172 10 jdoin
            spi_miso_i => spi_miso,
173
            di_req_o => spi_di_req_m,
174
            di_i => spi_di_reg_m,
175
            do_valid_o => spi_do_valid_m,
176
            do_o => spi_do_m,
177
            rx_bit_reg_o => spi_rx_bit_m,
178
            wren_i => spi_wren_reg_m,
179 11 jdoin
--            wren_o => spi_wren_o,
180 10 jdoin
            wren_ack_o => spi_wr_ack_m          -- monitor wren ack from inside spi port
181 5 jdoin
        );
182
 
183 10 jdoin
    dbg(7 downto 0) <= spi_do_m(7 downto 0);    -- connect master received data to 8bit debug port
184
    spi_rx_bit_m_o  <= spi_rx_bit_m;            -- connect rx_bit monitor for master port
185
 
186
    -- spi slave port
187
    --      receives parallel data from the pushbuttons, transmits to master port.
188
    --      receives serial data from master port, sends to the 8 LEDs.
189
    Inst_spi_slave_port: entity work.spi_slave(rtl)
190 11 jdoin
        generic map (N => N, CPOL => CPOL, CPHA => CPHA, PREFETCH => 3)
191 10 jdoin
        port map(
192
            clk_i => gclk_i,
193
            spi_ssel_i => spi_ssel,             -- generated by the spi master
194
            spi_sck_i => spi_sck,               -- generated by the spi master
195
            spi_mosi_i => spi_mosi,
196
            spi_miso_o => spi_miso,
197
            di_req_o => spi_di_req_s,
198
            di_i => spi_di_reg_s,
199
            wren_i => spi_wren_reg_s,
200
            rx_bit_reg_o => spi_rx_bit_s,
201
            do_valid_o => spi_do_valid_s,
202
            do_o => spi_do_s
203
        );
204
 
205 11 jdoin
    spi_di_reg_s(7) <= btn_data(btLEFT);        -- get the slave transmit data from pushbuttons
206
    spi_di_reg_s(6) <= btn_data(btCENTER);
207
    spi_di_reg_s(5 downto 1) <= B"10101";
208
    spi_di_reg_s(0) <= btn_data(btRIGHT);
209
    spi_wren_reg_s <= '1';                      -- fix wren to '1', for continuous load of transmit data
210
    spi_rx_bit_s_o <= spi_rx_bit_s;             -- connect rx_bit monitor for slave port
211 10 jdoin
 
212 5 jdoin
    -- debounce for the input switches, with new data strobe output
213
    Inst_sw_debouncer: entity work.grp_debouncer(rtl)
214
        generic map (N => 8, CNT_VAL => 10000)  -- debounce 8 inputs with 100 us settling time
215
        port map(
216 10 jdoin
            clk_i => gclk_i,                    -- system clock
217 5 jdoin
            data_i => sw_i,                     -- noisy input data
218 10 jdoin
            data_o => sw_data                   -- registered stable output data
219
--            strb_o => dbg(0)                    -- monitor the debounced data strobe
220 5 jdoin
        );
221
 
222
    -- debounce for the input pushbuttons, with new data strobe output
223
    Inst_btn_debouncer: entity work.grp_debouncer(rtl)
224
        generic map (N => 6, CNT_VAL => 50000)  -- debounce 6 inputs with 500 us settling time
225
        port map(
226 10 jdoin
            clk_i => gclk_i,                    -- system clock
227 5 jdoin
            data_i => btn_i,                    -- noisy input data
228 10 jdoin
            data_o => btn_data                  -- registered stable output data
229
--            strb_o => dbg(3)                    -- monitor the debounced data strobe
230 5 jdoin
        );
231
 
232
    --=============================================================================================
233
    --  CONSTANTS CONSTRAINTS CHECKING
234
    --=============================================================================================
235
    -- clock dividers shall not be zero
236 11 jdoin
    assert FSM_CE_DIV > 0
237
    report "Constant 'FSM_CE_DIV' should not be zero"
238 5 jdoin
    severity FAILURE;
239
    -- minimum prefetch lookahead check
240 11 jdoin
    assert SPI_2X_CLK_DIV > 0
241
    report "Constant 'SPI_2X_CLK_DIV' should not be zero"
242 5 jdoin
    severity FAILURE;
243
    -- maximum prefetch lookahead check
244 11 jdoin
    assert SAMP_CE_DIV > 0
245
    report "Constant 'SAMP_CE_DIV' should not be zero"
246 5 jdoin
    severity FAILURE;
247
 
248
    --=============================================================================================
249
    --  CLOCK GENERATION
250
    --=============================================================================================
251
    -- The clock generation block derives 3 internal clocks, divided down from the 100MHz input clock 
252
    --      core clock, 
253
    --      spi 2x base clock,
254
    --      fsm clock,
255
    -----------------------------------------------------------------------------------------------
256
    -- generate the sampling clock enable from the 100MHz board input clock 
257
    samp_ce_gen_proc: process (gclk_i) is
258
        variable clk_cnt : integer range SAMP_CE_DIV-1 downto 0 := 0;
259
    begin
260
        if gclk_i'event and gclk_i = '1' then
261
            if clk_cnt = SAMP_CE_DIV-1 then
262
                samp_ce <= '1';
263
                clk_cnt := 0;
264
            else
265
                samp_ce <= '0';
266
                clk_cnt := clk_cnt + 1;
267
            end if;
268
        end if;
269
    end process samp_ce_gen_proc;
270
    -- generate the fsm clock enable from the 100MHz board input clock 
271
    fsm_ce_gen_proc: process (gclk_i) is
272
        variable clk_cnt : integer range FSM_CE_DIV-1 downto 0 := 0;
273
    begin
274
        if gclk_i'event and gclk_i = '1' then
275
            if clk_cnt = FSM_CE_DIV-1 then
276
                fsm_ce <= '1';
277
                clk_cnt := 0;
278
            else
279
                fsm_ce <= '0';
280
                clk_cnt := clk_cnt + 1;
281
            end if;
282
        end if;
283
    end process fsm_ce_gen_proc;
284
 
285
    --=============================================================================================
286
    -- INPUTS LOGIC
287
    --=============================================================================================
288
    -- registered inputs
289 10 jdoin
    samp_inputs_proc: process (gclk_i) is
290 5 jdoin
    begin
291 10 jdoin
        if gclk_i'event and gclk_i = '1' then
292 5 jdoin
            if samp_ce = '1' then
293 10 jdoin
                clear <= btn_data(btUP);        -- clear is button UP
294
                leds_reg <= spi_do_s;           -- update LEDs with spi_slave received data
295 5 jdoin
            end if;
296
        end if;
297
    end process samp_inputs_proc;
298
 
299
    --=============================================================================================
300 10 jdoin
    --  REGISTER TRANSFER PROCESSES
301 5 jdoin
    --=============================================================================================
302
    -- fsm state and data registers: synchronous to the spi base reference clock
303 10 jdoin
    fsm_reg_proc : process (gclk_i) is
304 5 jdoin
    begin
305
        -- FFD registers clocked on rising edge and cleared on sync 'clear'
306 10 jdoin
        if gclk_i'event and gclk_i = '1' then
307 5 jdoin
            if clear = '1' then                 -- sync reset
308
                state_reg <= st_reset;          -- only provide local reset for the state register
309
            else
310
                if fsm_ce = '1' then
311
                    state_reg <= state_next;    -- state register
312
                end if;
313
            end if;
314
        end if;
315
        -- FFD registers clocked on rising edge, with no reset
316 10 jdoin
        if gclk_i'event and gclk_i = '1' then
317 5 jdoin
            if fsm_ce = '1' then
318 10 jdoin
                spi_wren_reg_m <= spi_wren_next_m;
319
                spi_di_reg_m <= spi_di_next_m;
320
--                spi_wren_reg_s <= spi_wren_next_s;
321
--                spi_di_reg_s <= spi_di_next_s;
322 5 jdoin
                spi_rst_reg <= spi_rst_next;
323
                spi_ssel_reg <= spi_ssel;
324
                sw_reg <= sw_next;
325
                btn_reg <= btn_next;
326
            end if;
327
        end if;
328
    end process fsm_reg_proc;
329
 
330
    --=============================================================================================
331 10 jdoin
    --  COMBINATORIAL NEXT-STATE LOGIC PROCESSES
332 5 jdoin
    --=============================================================================================
333
    -- edge detector for new switch data
334 10 jdoin
    new_switch_proc: new_switch <= '1' when sw_data /= sw_reg else '0';     -- '1' for difference
335 5 jdoin
    -- edge detector for new button data
336 10 jdoin
    new_button_proc: new_button <= '1' when btn_data /= btn_reg else '0';   -- '1' for difference
337 5 jdoin
    -- fsm state and combinatorial logic
338
    -- the sequencer will wait for a new switch combination, and send the switch data to the spi port
339 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, 
340
                                spi_wren_reg_s, spi_ssel_reg, spi_rst_reg, sw_data,
341
                                sw_reg, new_switch, btn_data, btn_reg, new_button) is
342 5 jdoin
    begin
343
        spi_rst_next <= spi_rst_reg;
344 10 jdoin
        spi_di_next_m <= spi_di_reg_m;
345
        spi_wren_next_m <= spi_wren_reg_m;
346
--        spi_di_next_s <= spi_di_reg_s;
347
--        spi_wren_next_s <= spi_wren_reg_s;
348 5 jdoin
        sw_next <= sw_reg;
349
        btn_next <= btn_reg;
350
        state_next <= state_reg;
351
        case state_reg is
352
            when st_reset =>
353
                spi_rst_next <= '1';                        -- place spi interface on reset
354 10 jdoin
                spi_di_next_m <= (others => '0');           -- clear spi data port
355
                spi_di_next_s <= (others => '0');           -- clear spi data port
356
                spi_wren_next_m <= '0';                     -- deassert write enable
357
                spi_wren_next_s <= '0';                     -- deassert write enable
358 5 jdoin
                state_next <= st_wait_spi_idle;
359
 
360
            when st_wait_spi_idle =>
361
                if spi_ssel_reg = '1' then
362
                    spi_rst_next <= '0';                    -- remove reset when interface is idle
363
                    state_next <= st_wait_new_switch;
364
                end if;
365
 
366
            when st_wait_new_switch =>
367
                if new_switch = '1' then                    -- wait for new stable switch data
368
                    sw_next <= sw_data;                     -- load new switch data (end the mismatch condition)
369
                    state_next <= st_send_spi_data;
370
                elsif new_button = '1' then
371
                    btn_next <= btn_data;                   -- load new button data (end the mismatch condition)
372 10 jdoin
                    if btn_data /= B"000001" then
373 5 jdoin
                        state_next <= st_send_spi_data;
374
                    end if;
375
                end if;
376
 
377
            when st_send_spi_data =>
378 10 jdoin
                spi_di_next_m <= sw_reg;                    -- load switch register to the spi port
379
                spi_wren_next_m <= '1';                     -- write data on next clock
380 5 jdoin
                state_next <= st_wait_spi_ack;
381
 
382
            when st_wait_spi_ack =>                         -- the actual write happens on this state
383 10 jdoin
                spi_di_next_m <= sw_reg;                    -- load switch register to the spi port
384
                if spi_wr_ack_m = '1' then                  -- wait acknowledge
385
                    spi_wren_next_m <= '0';                 -- remove write strobe on next clock
386 5 jdoin
                    state_next <= st_wait_spi_finish;
387
                end if;
388
 
389
            when st_wait_spi_finish =>
390
                if spi_ssel_reg = '1' then
391
                    state_next <= st_wait_new_switch;
392
                end if;
393
 
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
    spi_do_valid_o_proc:    spi_do_valid_o  <= spi_do_valid_m;
408
    spi_di_req_o_proc:      spi_di_req_o    <= spi_di_req_m;
409 11 jdoin
--    spi_wren_ack_o_proc:    spi_wren_ack_o  <= spi_wr_ack_m;
410 10 jdoin
    led_o_proc:             led_o           <= leds_reg;        -- connect leds_reg signal to LED outputs
411 5 jdoin
 
412
    --=============================================================================================
413
    --  DEBUG LOGIC PROCESSES
414
    --=============================================================================================
415
    -- connect the debug vector outputs
416 10 jdoin
    dbg_o_proc:             dbg_o <= dbg;
417
 
418 5 jdoin
end behavioral;
419
 

powered by: WebSVN 2.1.0

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