---------------------------------------------------------------------------- -- spi_Nx8.vhd -- SPI Nx8bit Shift Register (PS interface) -- Version 1.0 -- -- Copyright (C) 2020 H.Poetzl -- -- This program is free software: you can redistribute it and/or -- modify it under the terms of the GNU General Public License -- as published by the Free Software Foundation, either version -- 2 of the License, or (at your option) any later version. -- ---------------------------------------------------------------------------- library IEEE; use IEEE.std_logic_1164.ALL; use IEEE.numeric_std.ALL; library unisim; use unisim.VCOMPONENTS.ALL; library unimacro; use unimacro.VCOMPONENTS.ALL; use work.vivado_pkg.ALL; -- Vivado Attributes entity spi_Nx8 is generic ( NUM_BYTES : integer := 1; DATA_WIDTH : integer := NUM_BYTES * 8 ); port ( ssn : in std_logic; sclk : in std_logic; mosi : in std_logic; miso : out std_logic; -- din : in std_logic_vector (DATA_WIDTH - 1 downto 0); dout : out std_logic_vector (DATA_WIDTH - 1 downto 0); -- dbg : out std_logic_vector (1 downto 0); valid : out std_logic ); end entity spi_Nx8; architecture RTL of spi_Nx8 is constant SHIFT_SIZE : integer := NUM_BYTES * 8; signal count : integer; signal shift : std_logic_vector (SHIFT_SIZE - 1 downto 0); signal pass : boolean; signal miso_rt : std_logic; begin count_proc : process (sclk, ssn) begin if ssn then count <= 0; elsif rising_edge(sclk) then if count = SHIFT_SIZE - 1 then count <= 0; else count <= count + 1; end if; end if; end process; shift_proc : process (sclk) begin if rising_edge(sclk) then if count = 0 then shift <= din(SHIFT_SIZE - 2 downto 0) & mosi; else shift <= shift(SHIFT_SIZE - 2 downto 0) & mosi; end if; end if; end process; retime_proc : process (sclk, ssn) begin if ssn then pass <= true; elsif falling_edge(sclk) then if count = 0 then pass <= true; else pass <= false; end if; miso_rt <= shift(SHIFT_SIZE - 1); end if; end process; miso <= din(SHIFT_SIZE - 1) when pass else miso_rt; dout <= shift(SHIFT_SIZE - 2 downto 0) & mosi; valid <= '1' when count = SHIFT_SIZE - 1 else '0'; dbg(1) <= '1' when miso_rt = '1' else '0'; dbg(0) <= '1' when pass else '0'; end RTL;