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 5

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
--          This is a test project for the Atlys board, to test the spi_master and grp_debounce cores.
12
--          It uses the board's 100MHz clock input, and clocks all sequential logic at this clock.
13
--
14
--          See the "spi_master_atlys.ucf" file for pin assignments. 
15
--          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
--
31
--
32
----------------------------------------------------------------------------------
33
library ieee;
34
use ieee.std_logic_1164.all;
35
use ieee.std_logic_arith.all;
36
 
37
entity spi_master_atlys_top is
38
    Port (
39
        gclk_i : in std_logic := 'X';               -- board clock input 100MHz
40
        clear_i : in std_logic := '0';              -- btn used as clear signal
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
        --- input slide switches ---
46
        sw_i : in std_logic_vector (7 downto 0);    -- 8 input slide switches
47
        --- input buttons ---
48
        btn_i : in std_logic_vector (5 downto 0);   -- 6 input push buttons
49
        --- output LEDs ----
50
        led_o : out std_logic_vector (7 downto 0);  -- output leds
51
        --- debug outputs ---
52
        dbg_o : out std_logic_vector (9 downto 0);  -- 10 generic debug pins
53
        --- spi debug pins ---
54
        spi_di_req_o : out std_logic;               -- spi data request
55
        spi_wren_o : out std_logic;                 -- spi write enable
56
        spi_wren_ack_o : out std_logic              -- spi write enable ack
57
    );
58
end spi_master_atlys_top;
59
 
60
architecture behavioral of spi_master_atlys_top is
61
 
62
    --=============================================================================================
63
    -- Constants
64
    --=============================================================================================
65
    -- clock divider count values from gclk_i (100MHz board clock)
66
    -- these constants shall not be zero
67
    constant FSM_CE_DIV         : integer := 1;
68
    constant SPI_2X_CLK_DIV     : integer := 1;     -- 50MHz SPI clock
69
    constant SAMP_CE_DIV        : integer := 1;
70
    -- spi port generics
71
    constant N : integer := 8;                      -- 8 bits
72
 
73
    -- button definitions
74
    constant btRESET    : integer := 0;             -- these are constants to use as btn_i(x)
75
    constant btUP       : integer := 1;
76
    constant btLEFT     : integer := 2;
77
    constant btDOWN     : integer := 3;
78
    constant btRIGHT    : integer := 4;
79
    constant btCENTER   : integer := 5;
80
 
81
    --=============================================================================================
82
    -- Type definitions
83
    --=============================================================================================
84
    type fsm_state_type is (st_reset, st_wait_spi_idle, st_wait_new_switch,
85
                            st_send_spi_data, st_wait_spi_ack, st_wait_spi_finish );
86
 
87
    --=============================================================================================
88
    -- Signals for state machine control
89
    --=============================================================================================
90
    signal state_reg    : fsm_state_type := st_reset;
91
    signal state_next   : fsm_state_type := st_reset;
92
 
93
    --=============================================================================================
94
    -- Signals for internal operation
95
    --=============================================================================================
96
    -- clock signals
97
    signal core_clk     : std_logic := '0';         -- core clock, direct copy of board clock
98
    signal spi_2x_clk   : std_logic := '0';         -- spi_2x clock, 50% clock divided-down from board clock
99
    -- clock enable signals
100
    signal samp_ce      : std_logic := '1';         -- clock enable for sample inputs
101
    signal fsm_ce       : std_logic := '1';         -- clock enable for fsm logic
102
    -- switch debouncer signals
103
    signal sw_data      : std_logic_vector (7 downto 0) := (others => '0'); -- debounced switch data
104
    signal sw_reg       : std_logic_vector (7 downto 0) := (others => '0'); -- registered switch data 
105
    signal sw_next      : std_logic_vector (7 downto 0) := (others => '0'); -- combinatorial switch data
106
    signal new_switch   : std_logic := '0';                                 -- detector for new switch data
107
    -- pushbutton debouncer signals
108
    signal btn_data     : std_logic_vector (5 downto 0) := (others => '0'); -- debounced state of pushbuttons
109
    signal btn_reg      : std_logic_vector (5 downto 0) := (others => '0'); -- registered button data 
110
    signal btn_next     : std_logic_vector (5 downto 0) := (others => '0'); -- combinatorial button data
111
    signal new_button   : std_logic := '0';                                 -- detector for new button data
112
    -- spi port signals
113
    signal spi_ssel     : std_logic;
114
    signal spi_sck      : std_logic;
115
    signal spi_mosi     : std_logic;
116
    signal spi_di_req   : std_logic;
117
    signal spi_ssel_reg : std_logic;
118
    signal spi_wr_ack   : std_logic;
119
    signal spi_rst_reg  : std_logic := '1';
120
    signal spi_rst_next : std_logic := '1';
121
    signal spi_di_reg   : std_logic_vector (N-1 downto 0) := (others => '0');
122
    signal spi_di_next  : std_logic_vector (N-1 downto 0) := (others => '0');
123
    signal spi_wren_reg : std_logic := '0';
124
    signal spi_wren_next : std_logic := '0';
125
    -- other signals
126
    signal clear        : std_logic := '0';
127
    -- output signals
128
    signal leds_reg : std_logic_vector (7 downto 0) := (others => '0');     -- registered led outputs
129
    signal dbg      : std_logic_vector (9 downto 0) := (others => '0');     -- we have 10 debug pins available
130
begin
131
 
132
    --=============================================================================================
133
    -- Component instantiation for the SPI port
134
    --=============================================================================================
135
    -- spi_port is the spi output port
136
    Inst_spi_port: entity work.spi_master(rtl)
137
        generic map (N => N, CPOL => '0', CPHA => '0', PREFETCH => 3, SPI_2X_CLK_DIV => SPI_2X_CLK_DIV)
138
        port map(
139
            sclk_i => core_clk,                 -- system clock is used for serial and parallel ports
140
            pclk_i => core_clk,
141
            rst_i => spi_rst_reg,
142
            spi_ssel_o => spi_ssel,
143
            spi_sck_o => spi_sck,
144
            spi_mosi_o => spi_mosi,
145
            di_req_o => spi_di_req,
146
            di_i => spi_di_reg,
147
            wren_i => spi_wren_reg,
148
            wren_o => spi_wren_o,
149
            wren_ack_o => spi_wr_ack,           -- monitor wren ack from inside spi port
150
            core_ce_o => dbg(8),                -- monitor the internal core clock enable lines
151
            core_n_ce_o => dbg(9)
152
        );
153
 
154
    spi_di_req_o <= spi_di_req;                 -- monitor data request
155
    spi_wren_ack_o <= spi_wr_ack;
156
 
157
    -- debounce for the input switches, with new data strobe output
158
    Inst_sw_debouncer: entity work.grp_debouncer(rtl)
159
        generic map (N => 8, CNT_VAL => 10000)  -- debounce 8 inputs with 100 us settling time
160
        port map(
161
            clk_i => core_clk,                  -- system clock
162
            data_i => sw_i,                     -- noisy input data
163
            data_o => sw_data,                  -- registered stable output data
164
            strb_o => dbg(0)                    -- monitor the debounced data strobe
165
        );
166
 
167
    -- debounce for the input pushbuttons, with new data strobe output
168
    Inst_btn_debouncer: entity work.grp_debouncer(rtl)
169
        generic map (N => 6, CNT_VAL => 50000)  -- debounce 6 inputs with 500 us settling time
170
        port map(
171
            clk_i => core_clk,                  -- system clock
172
            data_i => btn_i,                    -- noisy input data
173
            data_o => btn_data,                 -- registered stable output data
174
            strb_o => dbg(3)                    -- monitor the debounced data strobe
175
        );
176
 
177
    dbg1_proc:  dbg(1) <= new_switch;           -- monitor new_switch signal
178
    dbg2_proc:  dbg(2) <= sw_i(0);              -- monitor raw input (rightmost switch)
179
    dbg4_proc:  dbg(4) <= new_button;           -- monitor new_button signal
180
    dbg5_proc:  dbg(5) <= btn_i(5);             -- monitor raw input (center btn)
181
 
182
    --=============================================================================================
183
    --  CONSTANTS CONSTRAINTS CHECKING
184
    --=============================================================================================
185
    -- clock dividers shall not be zero
186
    assert FSM_CE_DIV > 0
187
    report "Constant 'FSM_CE_DIV' should not be zero"
188
    severity FAILURE;
189
    -- minimum prefetch lookahead check
190
    assert SPI_2X_CLK_DIV > 0
191
    report "Constant 'SPI_2X_CLK_DIV' should not be zero"
192
    severity FAILURE;
193
    -- maximum prefetch lookahead check
194
    assert SAMP_CE_DIV > 0
195
    report "Constant 'SAMP_CE_DIV' should not be zero"
196
    severity FAILURE;
197
 
198
    --=============================================================================================
199
    --  CLOCK GENERATION
200
    --=============================================================================================
201
    -- The clock generation block derives 3 internal clocks, divided down from the 100MHz input clock 
202
    --      core clock, 
203
    --      spi 2x base clock,
204
    --      fsm clock,
205
    -----------------------------------------------------------------------------------------------
206
    -- generate the core clock from the 100MHz board input clock 
207
    core_clock_gen_proc: core_clk <= gclk_i;
208
    -- generate the sampling clock enable from the 100MHz board input clock 
209
    samp_ce_gen_proc: process (gclk_i) is
210
        variable clk_cnt : integer range SAMP_CE_DIV-1 downto 0 := 0;
211
    begin
212
        if gclk_i'event and gclk_i = '1' then
213
            if clk_cnt = SAMP_CE_DIV-1 then
214
                samp_ce <= '1';
215
                clk_cnt := 0;
216
            else
217
                samp_ce <= '0';
218
                clk_cnt := clk_cnt + 1;
219
            end if;
220
        end if;
221
    end process samp_ce_gen_proc;
222
    -- generate the fsm clock enable from the 100MHz board input clock 
223
    fsm_ce_gen_proc: process (gclk_i) is
224
        variable clk_cnt : integer range FSM_CE_DIV-1 downto 0 := 0;
225
    begin
226
        if gclk_i'event and gclk_i = '1' then
227
            if clk_cnt = FSM_CE_DIV-1 then
228
                fsm_ce <= '1';
229
                clk_cnt := 0;
230
            else
231
                fsm_ce <= '0';
232
                clk_cnt := clk_cnt + 1;
233
            end if;
234
        end if;
235
    end process fsm_ce_gen_proc;
236
    -- generate the spi base clock from the 100MHz board input clock
237
--    spi_2x_clk_div_proc: spi_2x_clk <= gclk_i;  -- generate 50MHz SPI SCK
238
 
239
    spi_2x_clk_div_proc: process (gclk_i) is
240
        variable clk_cnt : integer range SPI_2X_CLK_DIV-1 downto 0:= 0;
241
    begin
242
        if gclk_i'event and gclk_i = '1' then
243
            if clk_cnt = SPI_2X_CLK_DIV-1 then
244
                spi_2x_clk <= not spi_2x_clk;
245
                clk_cnt := 0;
246
            else
247
                clk_cnt := clk_cnt + 1;
248
            end if;
249
        end if;
250
    end process spi_2x_clk_div_proc;
251
 
252
    --=============================================================================================
253
    -- INPUTS LOGIC
254
    --=============================================================================================
255
    -- registered inputs
256
    samp_inputs_proc: process (core_clk) is
257
    begin
258
        if core_clk'event and core_clk = '1' then
259
            if samp_ce = '1' then
260
--                clear <= btn_data(btRESET);     -- sample reset input
261
                leds_reg <= sw_data;            -- update LEDs with debounced switches
262
            end if;
263
        end if;
264
    end process samp_inputs_proc;
265
 
266
    --=============================================================================================
267
    --  FSM REGISTER PROCESSES
268
    --=============================================================================================
269
    -- fsm state and data registers: synchronous to the spi base reference clock
270
    fsm_reg_proc : process (core_clk) is
271
    begin
272
        -- FFD registers clocked on rising edge and cleared on sync 'clear'
273
        if core_clk'event and core_clk = '1' then
274
            if clear = '1' then                 -- sync reset
275
                state_reg <= st_reset;          -- only provide local reset for the state register
276
            else
277
                if fsm_ce = '1' then
278
                    state_reg <= state_next;    -- state register
279
                end if;
280
            end if;
281
        end if;
282
        -- FFD registers clocked on rising edge, with no reset
283
        if core_clk'event and core_clk = '1' then
284
            if fsm_ce = '1' then
285
                spi_wren_reg <= spi_wren_next;
286
                spi_di_reg <= spi_di_next;
287
                spi_rst_reg <= spi_rst_next;
288
                spi_ssel_reg <= spi_ssel;
289
                sw_reg <= sw_next;
290
                btn_reg <= btn_next;
291
            end if;
292
        end if;
293
    end process fsm_reg_proc;
294
 
295
    --=============================================================================================
296
    --  FSM COMBINATORIAL NEXT-STATE LOGIC PROCESSES
297
    --=============================================================================================
298
    -- edge detector for new switch data
299
    new_switch_proc: new_switch <= '1' when sw_data /= sw_reg else '0'; -- '1' for difference
300
    -- edge detector for new button data
301
    new_button_proc: new_button <= '1' when btn_data /= btn_reg else '0'; -- '1' for difference
302
    -- fsm state and combinatorial logic
303
    -- the sequencer will wait for a new switch combination, and send the switch data to the spi port
304
    fsm_combi_proc: process (   state_reg, spi_wren_reg, spi_di_reg, spi_di_req, spi_wr_ack,
305
                                spi_ssel_reg, spi_rst_reg, sw_data, sw_reg, new_switch,
306
                                btn_data, btn_reg, new_button) is
307
    begin
308
        spi_di_next <= spi_di_reg;
309
        spi_rst_next <= spi_rst_reg;
310
        spi_wren_next <= spi_wren_reg;
311
        sw_next <= sw_reg;
312
        btn_next <= btn_reg;
313
        state_next <= state_reg;
314
        case state_reg is
315
            when st_reset =>
316
                spi_rst_next <= '1';                        -- place spi interface on reset
317
                spi_di_next <= (others => '0');             -- clear spi data port
318
                spi_wren_next <= '0';                       -- deassert write enable
319
                state_next <= st_wait_spi_idle;
320
 
321
            when st_wait_spi_idle =>
322
                if spi_ssel_reg = '1' then
323
                    spi_rst_next <= '0';                    -- remove reset when interface is idle
324
                    state_next <= st_wait_new_switch;
325
                end if;
326
 
327
            when st_wait_new_switch =>
328
                if new_switch = '1' then                    -- wait for new stable switch data
329
                    sw_next <= sw_data;                     -- load new switch data (end the mismatch condition)
330
                    state_next <= st_send_spi_data;
331
                elsif new_button = '1' then
332
                    btn_next <= btn_data;                   -- load new button data (end the mismatch condition)
333
                    if btn_data /= (5 downto 0 => '0') then
334
                        state_next <= st_send_spi_data;
335
                    end if;
336
                end if;
337
 
338
            when st_send_spi_data =>
339
                spi_di_next <= sw_reg;                      -- load switch register to the spi port
340
                spi_wren_next <= '1';                       -- write data on next clock
341
                state_next <= st_wait_spi_ack;
342
 
343
            when st_wait_spi_ack =>                         -- the actual write happens on this state
344
                spi_di_next <= sw_reg;                      -- load switch register to the spi port
345
                if spi_wr_ack = '1' then                    -- wait acknowledge
346
                    spi_wren_next <= '0';                   -- remove write strobe on next clock
347
                    state_next <= st_wait_spi_finish;
348
                end if;
349
 
350
            when st_wait_spi_finish =>
351
                if spi_ssel_reg = '1' then
352
                    state_next <= st_wait_new_switch;
353
                end if;
354
 
355
            when others =>
356
                state_next <= st_reset;                     -- state st_reset is safe state
357
        end case;
358
    end process fsm_combi_proc;
359
 
360
    --=============================================================================================
361
    --  OUTPUT LOGIC PROCESSES
362
    --=============================================================================================
363
    -- connect the spi output wires
364
    spi_ssel_o_proc:    spi_ssel_o <= spi_ssel;
365
    spi_sck_o_proc:     spi_sck_o <= spi_sck;
366
    spi_mosi_o_proc:    spi_mosi_o <= spi_mosi;
367
    -- connect leds_reg signal to LED outputs
368
    leds_out_proc:      led_o <= leds_reg;
369
 
370
    --=============================================================================================
371
    --  DEBUG LOGIC PROCESSES
372
    --=============================================================================================
373
    -- connect the debug vector outputs
374
    dbg_o_proc:         dbg_o <= dbg;
375
 
376
end behavioral;
377
 

powered by: WebSVN 2.1.0

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