Line 19... |
Line 19... |
------------------------------ REVISION HISTORY -----------------------------------------------------------------------
|
------------------------------ REVISION HISTORY -----------------------------------------------------------------------
|
--
|
--
|
-- 2011/07/02 v0.01.0010 [JD] implemented a wire-through from switches to LEDs, just to test the toolchain. It worked!
|
-- 2011/07/02 v0.01.0010 [JD] implemented a wire-through from switches to LEDs, just to test the toolchain. It worked!
|
-- 2011/07/03 v0.01.0020 [JD] added clock input, and a simple LED blinker for each LED.
|
-- 2011/07/03 v0.01.0020 [JD] added clock input, and a simple LED blinker for each LED.
|
-- 2011/07/03 v0.01.0030 [JD] added clear input, and instantiated a SPI_MASTER from my OpenCores project.
|
-- 2011/07/03 v0.01.0030 [JD] added clear input, and instantiated a SPI_MASTER from my OpenCores project.
|
-- 2011/07/04 v0.01.0040 [JD] changed all clocks to clock enables, and use the 100MHz board gclk_i to clock all registers.
|
-- 2011/07/04 v0.01.0040 [JD] changed all clocks to clock enables, and use the 100MHz board pclk_i to clock all registers.
|
-- this change made the design go up to 288MHz, after synthesis.
|
-- this change made the design go up to 288MHz, after synthesis.
|
-- 2011/07/07 v0.03.0050 [JD] implemented a 16pin umbilical port for the MSO2014 in the Atlys VmodBB board, and moved all
|
-- 2011/07/07 v0.03.0050 [JD] implemented a 16pin umbilical port for the MSO2014 in the Atlys VmodBB board, and moved all
|
-- external monitoring pins to the VHDCI ports.
|
-- external monitoring pins to the VHDCI ports.
|
-- 2011/07/10 v1.10.0075 [JD] verified spi_master_slave at 50MHz, 25MHz, 16.666MHz, 12.5MHz, 10MHz, 8.333MHz, 7.1428MHz,
|
-- 2011/07/10 v1.10.0075 [JD] verified spi_master_slave at 50MHz, 25MHz, 16.666MHz, 12.5MHz, 10MHz, 8.333MHz, 7.1428MHz,
|
-- 6.25MHz, 1MHz and 500kHz
|
-- 6.25MHz, 1MHz and 500kHz
|
Line 40... |
Line 40... |
Generic (
|
Generic (
|
N : positive := 8; -- 8bit serial word length is default
|
N : positive := 8; -- 8bit serial word length is default
|
CPOL : std_logic := '0'; -- SPI mode selection (mode 0 default)
|
CPOL : std_logic := '0'; -- SPI mode selection (mode 0 default)
|
CPHA : std_logic := '0'; -- CPOL = clock polarity, CPHA = clock phase.
|
CPHA : std_logic := '0'; -- CPOL = clock polarity, CPHA = clock phase.
|
PREFETCH : positive := 3; -- prefetch lookahead cycles
|
PREFETCH : positive := 3; -- prefetch lookahead cycles
|
CLK_PERIOD : time := 10 ns; -- clock period for gclk_i (default 100MHz)
|
CLK_PERIOD : time := 10 ns; -- clock period for pclk_i (default 100MHz)
|
DEBOUNCE_TIME : time := 200 us); -- switch debounce time (use 200 us for silicon, 2 us for simulation)
|
DEBOUNCE_TIME : time := 2 us); -- switch debounce time (use 200 us for silicon, 2 us for simulation)
|
Port (
|
Port (
|
gclk_i : in std_logic := 'X'; -- board clock input 100MHz
|
sclk_i : in std_logic := 'X'; -- board clock input 100MHz
|
|
pclk_i : in std_logic := 'X'; -- board clock input 100MHz
|
--- SPI interface ---
|
--- SPI interface ---
|
spi_ssel_o : out std_logic; -- spi port SSEL
|
spi_ssel_o : out std_logic; -- spi port SSEL
|
spi_sck_o : out std_logic; -- spi port SCK
|
spi_sck_o : out std_logic; -- spi port SCK
|
spi_mosi_o : out std_logic; -- spi port MOSI
|
spi_mosi_o : out std_logic; -- spi port MOSI
|
spi_miso_o : out std_logic; -- spi port MISO
|
spi_miso_o : out std_logic; -- spi port MISO
|
Line 69... |
Line 70... |
architecture rtl of spi_master_atlys_top is
|
architecture rtl of spi_master_atlys_top is
|
|
|
--=============================================================================================
|
--=============================================================================================
|
-- Constants
|
-- Constants
|
--=============================================================================================
|
--=============================================================================================
|
-- clock divider count values from gclk_i (100MHz board clock)
|
-- clock divider count values from pclk_i (100MHz board clock)
|
-- these constants shall not be zero
|
-- these constants shall not be zero
|
constant FSM_CE_DIV : integer := 1; -- fsm operates at 100MHz
|
constant FSM_CE_DIV : integer := 1; -- fsm operates at 100MHz
|
constant SPI_2X_CLK_DIV : integer := 1; -- 50MHz SPI clock
|
constant SPI_2X_CLK_DIV : integer := 1; -- 50MHz SPI clock
|
constant SAMP_CE_DIV : integer := 1; -- board signals sampled at 100MHz
|
constant SAMP_CE_DIV : integer := 1; -- board signals sampled at 100MHz
|
|
|
Line 182... |
Line 183... |
--=============================================================================================
|
--=============================================================================================
|
-- spi master port: data and control signals driven by the master fsm
|
-- spi master port: data and control signals driven by the master fsm
|
Inst_spi_master_port: entity work.spi_master(rtl)
|
Inst_spi_master_port: entity work.spi_master(rtl)
|
generic map (N => N, CPOL => CPOL, CPHA => CPHA, PREFETCH => PREFETCH, SPI_2X_CLK_DIV => SPI_2X_CLK_DIV)
|
generic map (N => N, CPOL => CPOL, CPHA => CPHA, PREFETCH => PREFETCH, SPI_2X_CLK_DIV => SPI_2X_CLK_DIV)
|
port map(
|
port map(
|
sclk_i => gclk_i, -- system clock is used for serial and parallel ports
|
sclk_i => sclk_i, -- system clock is used for serial and parallel ports
|
pclk_i => gclk_i,
|
pclk_i => pclk_i,
|
rst_i => spi_rst_reg,
|
rst_i => spi_rst_reg,
|
spi_ssel_o => spi_ssel,
|
spi_ssel_o => spi_ssel,
|
spi_sck_o => spi_sck,
|
spi_sck_o => spi_sck,
|
spi_mosi_o => spi_mosi,
|
spi_mosi_o => spi_mosi,
|
spi_miso_i => spi_miso, -- driven by the spi slave
|
spi_miso_i => spi_miso, -- driven by the spi slave
|
Line 203... |
Line 204... |
|
|
-- spi slave port: data and control signals driven by the slave fsm
|
-- spi slave port: data and control signals driven by the slave fsm
|
Inst_spi_slave_port: entity work.spi_slave(rtl)
|
Inst_spi_slave_port: entity work.spi_slave(rtl)
|
generic map (N => N, CPOL => CPOL, CPHA => CPHA, PREFETCH => PREFETCH)
|
generic map (N => N, CPOL => CPOL, CPHA => CPHA, PREFETCH => PREFETCH)
|
port map(
|
port map(
|
clk_i => gclk_i,
|
clk_i => pclk_i,
|
spi_ssel_i => spi_ssel, -- driven by the spi master
|
spi_ssel_i => spi_ssel, -- driven by the spi master
|
spi_sck_i => spi_sck, -- driven by the spi master
|
spi_sck_i => spi_sck, -- driven by the spi master
|
spi_mosi_i => spi_mosi, -- driven by the spi master
|
spi_mosi_i => spi_mosi, -- driven by the spi master
|
spi_miso_o => spi_miso,
|
spi_miso_o => spi_miso,
|
di_req_o => spi_di_req_s,
|
di_req_o => spi_di_req_s,
|
Line 222... |
Line 223... |
|
|
-- debounce for the input switches, with new data strobe output
|
-- debounce for the input switches, with new data strobe output
|
Inst_sw_debouncer: entity work.grp_debouncer(rtl)
|
Inst_sw_debouncer: entity work.grp_debouncer(rtl)
|
generic map (N => 8, CNT_VAL => DEBOUNCE_TIME / CLK_PERIOD) -- debounce 8 inputs with selected settling time
|
generic map (N => 8, CNT_VAL => DEBOUNCE_TIME / CLK_PERIOD) -- debounce 8 inputs with selected settling time
|
port map(
|
port map(
|
clk_i => gclk_i, -- system clock
|
clk_i => pclk_i, -- system clock
|
data_i => sw_i, -- noisy input data
|
data_i => sw_i, -- noisy input data
|
data_o => sw_data -- registered stable output data
|
data_o => sw_data -- registered stable output data
|
);
|
);
|
|
|
-- debounce for the input pushbuttons, with new data strobe output
|
-- debounce for the input pushbuttons, with new data strobe output
|
Inst_btn_debouncer: entity work.grp_debouncer(rtl)
|
Inst_btn_debouncer: entity work.grp_debouncer(rtl)
|
generic map (N => 6, CNT_VAL => DEBOUNCE_TIME / CLK_PERIOD) -- debounce 6 inputs with selected settling time
|
generic map (N => 6, CNT_VAL => DEBOUNCE_TIME / CLK_PERIOD) -- debounce 6 inputs with selected settling time
|
port map(
|
port map(
|
clk_i => gclk_i, -- system clock
|
clk_i => pclk_i, -- system clock
|
data_i => btn_i, -- noisy input data
|
data_i => btn_i, -- noisy input data
|
data_o => btn_data -- registered stable output data
|
data_o => btn_data -- registered stable output data
|
);
|
);
|
|
|
--=============================================================================================
|
--=============================================================================================
|
Line 262... |
Line 263... |
-- clock.
|
-- clock.
|
-- input sample clock enable,
|
-- input sample clock enable,
|
-- fsm clock enable,
|
-- fsm clock enable,
|
-----------------------------------------------------------------------------------------------
|
-----------------------------------------------------------------------------------------------
|
-- generate the sampling clock enable from the 100MHz board input clock
|
-- generate the sampling clock enable from the 100MHz board input clock
|
samp_ce_gen_proc: process (gclk_i) is
|
samp_ce_gen_proc: process (pclk_i) is
|
variable clk_cnt : integer range SAMP_CE_DIV-1 downto 0 := 0;
|
variable clk_cnt : integer range SAMP_CE_DIV-1 downto 0 := 0;
|
begin
|
begin
|
if gclk_i'event and gclk_i = '1' then
|
if pclk_i'event and pclk_i = '1' then
|
if clk_cnt = SAMP_CE_DIV-1 then
|
if clk_cnt = SAMP_CE_DIV-1 then
|
samp_ce <= '1'; -- generate a single pulse every SAMP_CE_DIV clocks
|
samp_ce <= '1'; -- generate a single pulse every SAMP_CE_DIV clocks
|
clk_cnt := 0;
|
clk_cnt := 0;
|
else
|
else
|
samp_ce <= '0';
|
samp_ce <= '0';
|
clk_cnt := clk_cnt + 1;
|
clk_cnt := clk_cnt + 1;
|
end if;
|
end if;
|
end if;
|
end if;
|
end process samp_ce_gen_proc;
|
end process samp_ce_gen_proc;
|
-- generate the fsm clock enable from the 100MHz board input clock
|
-- generate the fsm clock enable from the 100MHz board input clock
|
fsm_ce_gen_proc: process (gclk_i) is
|
fsm_ce_gen_proc: process (pclk_i) is
|
variable clk_cnt : integer range FSM_CE_DIV-1 downto 0 := 0;
|
variable clk_cnt : integer range FSM_CE_DIV-1 downto 0 := 0;
|
begin
|
begin
|
if gclk_i'event and gclk_i = '1' then
|
if pclk_i'event and pclk_i = '1' then
|
if clk_cnt = FSM_CE_DIV-1 then
|
if clk_cnt = FSM_CE_DIV-1 then
|
fsm_ce <= '1'; -- generate a single pulse every FSM_CE_DIV clocks
|
fsm_ce <= '1'; -- generate a single pulse every FSM_CE_DIV clocks
|
clk_cnt := 0;
|
clk_cnt := 0;
|
else
|
else
|
fsm_ce <= '0';
|
fsm_ce <= '0';
|
Line 294... |
Line 295... |
|
|
--=============================================================================================
|
--=============================================================================================
|
-- INPUTS LOGIC
|
-- INPUTS LOGIC
|
--=============================================================================================
|
--=============================================================================================
|
-- registered inputs
|
-- registered inputs
|
samp_inputs_proc: process (gclk_i) is
|
samp_inputs_proc: process (pclk_i) is
|
begin
|
begin
|
if gclk_i'event and gclk_i = '1' then
|
if pclk_i'event and pclk_i = '1' then
|
if samp_ce = '1' then
|
if samp_ce = '1' then
|
clear <= btn_data(btUP); -- clear is button UP
|
clear <= btn_data(btUP); -- clear is button UP
|
leds_reg <= leds_next; -- update LEDs with spi_slave received data
|
leds_reg <= leds_next; -- update LEDs with spi_slave received data
|
end if;
|
end if;
|
end if;
|
end if;
|
Line 308... |
Line 309... |
|
|
--=============================================================================================
|
--=============================================================================================
|
-- REGISTER TRANSFER PROCESSES
|
-- REGISTER TRANSFER PROCESSES
|
--=============================================================================================
|
--=============================================================================================
|
-- fsm state and data registers: synchronous to the system clock
|
-- fsm state and data registers: synchronous to the system clock
|
fsm_reg_proc : process (gclk_i) is
|
fsm_reg_proc : process (pclk_i) is
|
begin
|
begin
|
-- FFD registers clocked on rising edge and cleared on sync 'clear'
|
-- FFD registers clocked on rising edge and cleared on sync 'clear'
|
if gclk_i'event and gclk_i = '1' then
|
if pclk_i'event and pclk_i = '1' then
|
if clear = '1' then -- sync reset
|
if clear = '1' then -- sync reset
|
m_wr_st_reg <= st_reset; -- only provide local reset for the state registers
|
m_wr_st_reg <= st_reset; -- only provide local reset for the state registers
|
else
|
else
|
if fsm_ce = '1' then
|
if fsm_ce = '1' then
|
m_wr_st_reg <= m_wr_st_next; -- master write state register update
|
m_wr_st_reg <= m_wr_st_next; -- master write state register update
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
-- FFD registers clocked on rising edge and cleared on ssel = '1'
|
-- FFD registers clocked on rising edge and cleared on ssel = '1'
|
if gclk_i'event and gclk_i = '1' then
|
if pclk_i'event and pclk_i = '1' then
|
if spi_ssel = '1' then -- sync reset
|
if spi_ssel = '1' then -- sync reset
|
s_wr_st_reg <= st_reset; -- only provide local reset for the state registers
|
s_wr_st_reg <= st_reset; -- only provide local reset for the state registers
|
s_rd_st_reg <= st_reset;
|
s_rd_st_reg <= st_reset;
|
else
|
else
|
if fsm_ce = '1' then
|
if fsm_ce = '1' then
|
Line 333... |
Line 334... |
s_rd_st_reg <= s_rd_st_next; -- slave read state register update
|
s_rd_st_reg <= s_rd_st_next; -- slave read state register update
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
-- FFD registers clocked on rising edge, with no reset
|
-- FFD registers clocked on rising edge, with no reset
|
if gclk_i'event and gclk_i = '1' then
|
if pclk_i'event and pclk_i = '1' then
|
if fsm_ce = '1' then
|
if fsm_ce = '1' then
|
--------- master write fsm signals -----------
|
--------- master write fsm signals -----------
|
spi_wren_reg_m <= spi_wren_next_m;
|
spi_wren_reg_m <= spi_wren_next_m;
|
spi_di_reg_m <= spi_di_next_m;
|
spi_di_reg_m <= spi_di_next_m;
|
spi_rst_reg <= spi_rst_next;
|
spi_rst_reg <= spi_rst_next;
|