A src/spi_recv.vhd => src/spi_recv.vhd +43 -0
@@ 0,0 1,43 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity spi_recv is
+
+ generic (
+ WIDTH : integer := 8);
+
+ port (
+ clk_i : in std_logic;
+ rst_in : in std_logic;
+ data_i : in std_logic;
+ recv_o : out std_logic;
+ recv_data_o : out std_logic_vector(WIDTH - 1 downto 0));
+end entity spi_recv;
+
+architecture a1 of spi_recv is
+ signal bit_index_reg : integer range 0 to WIDTH;
+ signal initialized : std_logic;
+begin -- architecture a1
+ recv_o <= '1' when bit_index_reg = 0 and initialized = '1' else
+ '0';
+
+ set_bit_index: process (clk_i) is
+ begin -- process set_bit_index
+ if rst_in = '0' then -- synchronous reset (active low)
+ bit_index_reg <= 0;
+ initialized <= '0';
+ elsif rising_edge(clk_i) then -- rising clock edge
+ initialized <= '1';
+ bit_index_reg <= (bit_index_reg + 1) mod WIDTH;
+ end if;
+ end process set_bit_index;
+
+ sr: entity work.sipo_shift_register
+ generic map (
+ WIDTH => WIDTH)
+ port map (
+ clk_i => clk_i,
+ data_i => data_i,
+ q_o => recv_data_o);
+
+end architecture a1;
A src/spi_transmit.vhd => src/spi_transmit.vhd +105 -0
@@ 0,0 1,105 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity spi_transmit is
+
+ generic (
+ WIDTH : integer := 8);
+
+ port (
+ clk_i : in std_logic; -- Clock
+ rst_in : in std_logic; -- Asynchronous reset, active low
+ transmit_data_i : in std_logic_vector(WIDTH - 1 downto 0); -- The data to
+ -- transmit.
+ -- Change only
+ -- if ready_o
+ -- is '1'.
+ transmit_i : in std_logic; -- Pulse to signal new data are present
+ -- in transmit_data. Data has to change
+ -- only if ready_o is '1'
+ ready_o : out std_logic; -- Signals that the transmitter is
+ -- ready for new data on `transmit_data_i``.
+ transmitting_o : out std_logic; -- Signals that the transmitter is
+ -- currently transmitting data
+ transmit_bit_o : out std_logic); -- The bit to transmit (on master MOSI)
+
+end entity spi_transmit;
+
+architecture a1 of spi_transmit is
+ signal ready_reg : std_logic; -- is the transmitter ready for new data?
+ signal ready_next : std_logic;
+
+ signal data_prepared_reg : std_logic; -- is there data prepared for next transmission?
+ signal data_prepared_next : std_logic;
+ signal store_data_in_sr_reg : std_logic; -- should data be stored in the
+ -- shift register next clock cycle?
+ signal store_data_in_sr_next : std_logic;
+
+ signal data_bit_index_reg : integer range 0 to WIDTH;
+ signal data_bit_index_next : integer range 0 to WIDTH;
+
+ signal transmitting_reg : std_logic; -- is there an ongoing transmission?
+ signal transmitting_next : std_logic;
+
+ signal continue_in_ongoing_transmission : std_logic; -- at the end of
+ -- transmission, are
+ -- next data ready and
+ -- should the transmission continue?
+begin -- architecture a1
+ ready_o <= ready_reg;
+ transmitting_o <= transmitting_reg;
+
+ ready_next <= '0' when ready_reg = '1' and transmit_i = '1' and transmitting_reg = '1' else
+ '0' when ready_reg = '0' and data_prepared_next = '1' else
+ '1';
+
+ data_bit_index_next <= (data_bit_index_reg + 1) mod WIDTH when transmitting_reg = '1' else
+ 0;
+
+ continue_in_ongoing_transmission <= '1' when transmitting_reg = '1' and data_bit_index_next = 0 and store_data_in_sr_next = '1' else
+ '0';
+
+ transmitting_next <= '1' when continue_in_ongoing_transmission = '1' else
+ '0' when transmitting_reg = '1' and data_bit_index_next = 0 else
+ '1' when transmitting_reg = '1' else
+ '1' when store_data_in_sr_next = '1' else
+ '0';
+
+ store_data_in_sr_next <= '0' when store_data_in_sr_reg = '1' else
+ '1' when transmitting_reg = '0' and transmit_i = '1' else
+ '1' when transmitting_reg = '0' and data_prepared_reg = '1' else
+ '1' when transmitting_reg = '1' and data_bit_index_next = 0 and data_prepared_reg = '1' else
+ '0';
+
+ data_prepared_next <= '1' when transmit_i = '1' and ready_reg = '1' and transmitting_reg = '1' else
+ '1' when data_prepared_reg = '1' and store_data_in_sr_next = '0' else
+ '0';
+
+ store_next: process (clk_i) is
+ begin -- process store_next
+ if rst_in = '0' then -- synchronous reset (active low)
+ ready_reg <= '0';
+ data_prepared_reg <= '0';
+ store_data_in_sr_reg <= '0';
+ data_bit_index_reg <= 0;
+ transmitting_reg <= '0';
+ elsif rising_edge(clk_i) then -- rising clock edge
+ ready_reg <= ready_next;
+ data_prepared_reg <= data_prepared_next;
+ store_data_in_sr_reg <= store_data_in_sr_next;
+ data_bit_index_reg <= data_bit_index_next;
+ transmitting_reg <= transmitting_next;
+ end if;
+ end process store_next;
+
+ sr: entity work.piso_shift_register
+ generic map (
+ WIDTH => WIDTH)
+ port map (
+ clk_i => clk_i,
+ data_i => transmit_data_i,
+ store_i => store_data_in_sr_next,
+ q_o => transmit_bit_o
+ );
+
+end architecture a1;