Line 66... |
Line 66... |
-- When the interface is idle, data at the 'do_o' port holds the last word received.
|
-- When the interface is idle, data at the 'do_o' port holds the last word received.
|
--
|
--
|
-- PARALLEL READ SEQUENCE
|
-- PARALLEL READ SEQUENCE
|
-- ======================
|
-- ======================
|
-- ______ ______ ______ ______
|
-- ______ ______ ______ ______
|
-- spi_clk bit1 \______/ bitN \______/bitN-1\______/bitN-2\__... -- spi 2x base clock
|
-- spi_clk bit1 \______/ bitN \______/bitN-1\______/bitN-2\__... -- internal spi 2x base clock
|
-- _ __ __ __ __ __ __ __ __
|
-- _ __ __ __ __ __ __ __ __
|
-- pclk_i \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \_... -- parallel interface clock (may be async to sclk_i)
|
-- pclk_i \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \_... -- parallel interface clock (may be async to sclk_i)
|
-- _____________ _____________________________________... -- 1) rx data is transferred to 'do_buffer_reg'
|
-- _____________ _____________________________________... -- 1) rx data is transferred to 'do_buffer_reg'
|
-- do_o ___old_data__X__________new_data___________________... -- after last rx bit, at rising 'spi_clk'.
|
-- do_o ___old_data__X__________new_data___________________... -- after last rx bit, at rising 'spi_clk'.
|
-- ____________
|
-- ____________
|
Line 162... |
Line 162... |
SPI_2X_CLK_DIV : positive := 5); -- for a 100MHz sclk_i, yields a 10MHz SCK
|
SPI_2X_CLK_DIV : positive := 5); -- for a 100MHz sclk_i, yields a 10MHz SCK
|
Port (
|
Port (
|
sclk_i : in std_logic := 'X'; -- high-speed serial interface system clock
|
sclk_i : in std_logic := 'X'; -- high-speed serial interface system clock
|
pclk_i : in std_logic := 'X'; -- high-speed parallel interface system clock
|
pclk_i : in std_logic := 'X'; -- high-speed parallel interface system clock
|
rst_i : in std_logic := 'X'; -- reset core
|
rst_i : in std_logic := 'X'; -- reset core
|
|
---- serial interface ----
|
spi_ssel_o : out std_logic; -- spi bus slave select line
|
spi_ssel_o : out std_logic; -- spi bus slave select line
|
spi_sck_o : out std_logic; -- spi bus sck
|
spi_sck_o : out std_logic; -- spi bus sck
|
spi_mosi_o : out std_logic; -- spi bus mosi output
|
spi_mosi_o : out std_logic; -- spi bus mosi output
|
spi_miso_i : in std_logic := 'X'; -- spi bus spi_miso_i input
|
spi_miso_i : in std_logic := 'X'; -- spi bus spi_miso_i input
|
|
---- parallel interface ----
|
di_req_o : out std_logic; -- preload lookahead data request line
|
di_req_o : out std_logic; -- preload lookahead data request line
|
di_i : in std_logic_vector (N-1 downto 0) := (others => 'X'); -- parallel data in (clocked on rising spi_clk after last bit)
|
di_i : in std_logic_vector (N-1 downto 0) := (others => 'X'); -- parallel data in (clocked on rising spi_clk after last bit)
|
wren_i : in std_logic := 'X'; -- user data write enable, starts transmission when interface is idle
|
wren_i : in std_logic := 'X'; -- user data write enable, starts transmission when interface is idle
|
do_valid_o : out std_logic; -- do_o data valid signal, valid during one spi_clk rising edge.
|
do_valid_o : out std_logic; -- do_o data valid signal, valid during one spi_clk rising edge.
|
do_o : out std_logic_vector (N-1 downto 0); -- parallel output (clocked on rising spi_clk after last bit)
|
do_o : out std_logic_vector (N-1 downto 0); -- parallel output (clocked on rising spi_clk after last bit)
|
--- debug ports: can be removed for the application circuit ---
|
--- debug ports: can be removed or left unconnected for the application circuit ---
|
do_transfer_o : out std_logic; -- debug: internal transfer driver
|
do_transfer_o : out std_logic; -- debug: internal transfer driver
|
wren_o : out std_logic; -- debug: internal state of the wren_i pulse stretcher
|
wren_o : out std_logic; -- debug: internal state of the wren_i pulse stretcher
|
wren_ack_o : out std_logic; -- debug: wren ack from state machine
|
wren_ack_o : out std_logic; -- debug: wren ack from state machine
|
rx_bit_reg_o : out std_logic; -- debug: internal rx bit
|
rx_bit_reg_o : out std_logic; -- debug: internal rx bit
|
state_dbg_o : out std_logic_vector (5 downto 0); -- debug: internal state register
|
state_dbg_o : out std_logic_vector (5 downto 0); -- debug: internal state register
|
Line 206... |
Line 208... |
signal samp_ce : std_logic := '1'; -- data sampling clock enable
|
signal samp_ce : std_logic := '1'; -- data sampling clock enable
|
--
|
--
|
-- GLOBAL RESET:
|
-- GLOBAL RESET:
|
-- all signals are initialized to zero at GSR (global set/reset) by giving explicit
|
-- all signals are initialized to zero at GSR (global set/reset) by giving explicit
|
-- initialization values at declaration. This is needed for all Xilinx FPGAs, and
|
-- initialization values at declaration. This is needed for all Xilinx FPGAs, and
|
-- especially for the Spartan-6 and newer CLB architectures, where a local reset can
|
-- especially for the Spartan-6 and newer CLB architectures, where a async reset can
|
-- reduce the usability of the slice registers, due to the need to share the control
|
-- reduce the usability of the slice registers, due to the need to share the control
|
-- set (RESET/PRESET, CLOCK ENABLE and CLOCK) by all 8 registers in a slice.
|
-- set (RESET/PRESET, CLOCK ENABLE and CLOCK) by all 8 registers in a slice.
|
-- By using GSR for the initialization, and reducing RESET local init to the bare
|
-- By using GSR for the initialization, and reducing async RESET local init to the bare
|
-- essential, the model achieves better LUT/FF packing and CLB usability.
|
-- essential, the model achieves better LUT/FF packing and CLB usability.
|
--
|
--
|
-- internal state signals for register and combinatorial stages
|
-- internal state signals for register and combinatorial stages
|
signal state_next : natural range N+1 downto 0 := 0;
|
signal state_next : natural range N+1 downto 0 := 0;
|
signal state_reg : natural range N+1 downto 0 := 0;
|
signal state_reg : natural range N+1 downto 0 := 0;
|
Line 285... |
Line 287... |
-- on using clock enables to process the serial high-speed clock at lower rates for the core fsm,
|
-- on using clock enables to process the serial high-speed clock at lower rates for the core fsm,
|
-- the spi clock generator and the input sampling clock.
|
-- the spi clock generator and the input sampling clock.
|
-- The clock generation block derive 2 continuous antiphase signals from the 2x spi base clock
|
-- The clock generation block derive 2 continuous antiphase signals from the 2x spi base clock
|
-- for the core clocking.
|
-- for the core clocking.
|
-- The 2 clock phases are generated by sepparate and synchronous FFs, and should have only
|
-- The 2 clock phases are generated by sepparate and synchronous FFs, and should have only
|
-- interconnect delays.
|
-- differential interconnect delay skew.
|
-- Clock enable signals are generated with the same phase as the 2 core clocks, and these clock
|
-- Clock enable signals are generated with the same phase as the 2 core clocks, and these clock
|
-- enables are used to control clocking of all internal synchronous circuitry.
|
-- enables are used to control clocking of all internal synchronous circuitry.
|
-- The clock enable phase is selected for serial input sampling, fsm clocking, and spi SCK output,
|
-- The clock enable phase is selected for serial input sampling, fsm clocking, and spi SCK output,
|
-- based on the configuration of CPOL and CPHA.
|
-- based on the configuration of CPOL and CPHA.
|
-- Each phase is selected so that all the registers can be clocked with a rising edge on all SPI
|
-- Each phase is selected so that all the registers can be clocked with a rising edge on all SPI
|
Line 381... |
Line 383... |
end if;
|
end if;
|
end if;
|
end if;
|
end process rx_bit_proc;
|
end process rx_bit_proc;
|
|
|
--=============================================================================================
|
--=============================================================================================
|
-- RTL REGISTER PROCESSES
|
|
--=============================================================================================
|
|
-- fsm state and data registers: synchronous to the spi base reference clock
|
|
core_reg_proc : process (sclk_i) is
|
|
begin
|
|
-- FF registers clocked on rising edge and cleared on sync rst_i
|
|
if sclk_i'event and sclk_i = '1' then
|
|
if rst_i = '1' then -- sync reset
|
|
state_reg <= 0; -- only provide local reset for the state machine
|
|
elsif fsm_ce = '1' then -- fsm_ce is clock enable for the fsm
|
|
state_reg <= state_next; -- state register
|
|
end if;
|
|
end if;
|
|
-- FF registers clocked on rising edge
|
|
if sclk_i'event and sclk_i = '1' then
|
|
if fsm_ce = '1' then
|
|
sh_reg <= sh_next; -- shift register
|
|
ena_ssel_reg <= ena_ssel_next; -- spi select enable
|
|
ena_sck_reg <= ena_sck_next; -- spi clock enable
|
|
do_buffer_reg <= do_buffer_next; -- registered output data buffer
|
|
do_transfer_reg <= do_transfer_next; -- output data transferred to buffer
|
|
di_req_reg <= di_req_next; -- input data request
|
|
wren_ack_reg <= wren_ack_next; -- wren ack for data load synchronization
|
|
end if;
|
|
end if;
|
|
end process core_reg_proc;
|
|
|
|
--=============================================================================================
|
|
-- CROSS-CLOCK PIPELINE TRANSFER LOGIC
|
-- CROSS-CLOCK PIPELINE TRANSFER LOGIC
|
--=============================================================================================
|
--=============================================================================================
|
-- do_valid_o and di_req_o strobe output logic
|
-- do_valid_o and di_req_o strobe output logic
|
-- this is a delayed pulse generator with a ripple-transfer FFD pipeline, that generates a
|
-- this is a delayed pulse generator with a ripple-transfer FFD pipeline, that generates a
|
-- fixed-length delayed pulse for the output flags, at the parallel clock domain
|
-- fixed-length delayed pulse for the output flags, at the parallel clock domain
|
Line 457... |
Line 431... |
end if;
|
end if;
|
end if;
|
end if;
|
end process in_transfer_proc;
|
end process in_transfer_proc;
|
|
|
--=============================================================================================
|
--=============================================================================================
|
|
-- RTL REGISTER PROCESSES
|
|
--=============================================================================================
|
|
-- fsm state and data registers: synchronous to the spi base reference clock
|
|
core_reg_proc : process (sclk_i) is
|
|
begin
|
|
-- FF registers clocked on rising edge and cleared on sync rst_i
|
|
if sclk_i'event and sclk_i = '1' then
|
|
if rst_i = '1' then -- sync reset
|
|
state_reg <= 0; -- only provide local reset for the state machine
|
|
elsif fsm_ce = '1' then -- fsm_ce is clock enable for the fsm
|
|
state_reg <= state_next; -- state register
|
|
end if;
|
|
end if;
|
|
-- FF registers clocked on rising edge
|
|
if sclk_i'event and sclk_i = '1' then
|
|
if fsm_ce = '1' then
|
|
sh_reg <= sh_next; -- shift register
|
|
ena_ssel_reg <= ena_ssel_next; -- spi select enable
|
|
ena_sck_reg <= ena_sck_next; -- spi clock enable
|
|
do_buffer_reg <= do_buffer_next; -- registered output data buffer
|
|
do_transfer_reg <= do_transfer_next; -- output data transferred to buffer
|
|
di_req_reg <= di_req_next; -- input data request
|
|
wren_ack_reg <= wren_ack_next; -- wren ack for data load synchronization
|
|
end if;
|
|
end if;
|
|
end process core_reg_proc;
|
|
|
|
--=============================================================================================
|
-- RTL combinatorial LOGIC PROCESSES
|
-- RTL combinatorial LOGIC PROCESSES
|
--=============================================================================================
|
--=============================================================================================
|
-- state and datapath combinatorial logic
|
-- state and datapath combinatorial logic
|
core_combi_proc : process ( sh_reg, state_reg, rx_bit_reg, ena_ssel_reg, ena_sck_reg, do_buffer_reg,
|
core_combi_proc : process ( sh_reg, state_reg, rx_bit_reg, ena_ssel_reg, ena_sck_reg, do_buffer_reg,
|
do_transfer_reg, di_reg, wren ) is
|
do_transfer_reg, di_reg, wren ) is
|