library IEEE; use IEEE.std_logic_1164.all; use ieee.std_logic_arith.all; USE ieee.std_logic_unsigned.all; -- Shift register with parallel input and serial output. -- Input bus is 16 bit. Writing -- starts the serial transfer. -- internal address 0 1 -- writing data config -- bits 0 - enable strobe -- bits 1 - enable additional serial clock -- bits 2 - 0 MSB first, 1 LSB first -- bits 3 - enable IRQ when ready -- reading data state_machine & config -- "000" when waiting -- "001" when shd, -- "010" when shc, -- "011" when str, -- "100" when str1, -- MSB is busy entity par2ser is GENERIC ( WIDTH : Integer := 16 -- Width of the 'Byte' ); PORT ( CE : IN STD_LOGIC; -- Chip enable A0 : IN STD_LOGIC; -- bit 0 of the address WE : IN STD_LOGIC; -- Write enable WR : IN STD_LOGIC; -- Write enable D : IN STD_LOGIC_VECTOR(WIDTH-1 downto 0); -- Data input bus CLK : IN STD_LOGIC; -- Clock RESET_n : IN STD_LOGIC; -- reset PQ : OUT STD_LOGIC_VECTOR(WIDTH-1 downto 0); -- Parallel outputs SCLK : OUT STD_LOGIC; -- Serial Clock SDAT : OUT STD_LOGIC; -- Serial Data SSTR : OUT STD_LOGIC; -- Serial Strobe IRQ : OUT STD_LOGIC);-- interrupt when ready end par2ser; architecture a of par2ser is SIGNAL CNT_FF : Integer range 0 to WIDTH; -- counter for the number of bits to be shifted out SIGNAL SL : STD_LOGIC; -- DFF_S is the shift register SIGNAL DFF_S : STD_LOGIC_VECTOR(WIDTH-1 downto 0); -- clock enable for the input register SIGNAL EN : STD_LOGIC; TYPE sm IS (waiting, sld, shd, shc, str, str1); -- state machine SIGNAL SERREG : sm; SIGNAL p_ld, wtng, shift, strb : STD_LOGIC; SIGNAL IRQe, IRQi : STD_LOGIC; SIGNAL sm_o : STD_LOGIC_VECTOR(2 downto 0); SIGNAL CNF : STD_LOGIC_VECTOR(3 downto 0); begin EN <= (CE and WE and not A0) or shift; process(CLK, EN) -- shift register begin if EN='0' then NULL; elsif CLK'event and CLK='1' then if shift='1' then if CNF(2)='0' then -- MSB first DFF_S <= DFF_S(WIDTH-2 downto 0) & DFF_S(WIDTH-1); else -- LSB first DFF_S <= DFF_S(0) & DFF_S(WIDTH-1 downto 1); end if; else DFF_S <= D; end if; end if; end process; process(CLK, RESET_n) begin if RESET_n = '0' then CNF <= (others => '0'); elsif CLK'event and CLK='1' then if (CE and WE and A0)='1' then CNF <= D(CNF'range); end if; end if; end process; process(CLK, RESET_n) -- start of the state machine begin if RESET_n = '0' then SL <= '0'; elsif CLK'event and CLK='1' then if ( (CE and WE and not A0) and wtng) = '1' then SL <= '1'; elsif SERREG=str1 then SL <= '0'; end if; end if; end process; process(CLK, RESET_n) -- counter for the number of shifts begin if RESET_n = '0' then CNT_FF <= WIDTH; elsif CLK'event and CLK='1' then if SERREG=waiting then CNT_FF <= WIDTH; -- sync load elsif SERREG=shc then CNT_FF <= CNT_FF - 1; -- decr end if; end if; end process; process(CLK, RESET_n) -- state machine begin if RESET_n = '0' then SERREG <= waiting; SSTR <= '0'; elsif CLK'event and CLK='1' then SSTR <= '0'; CASE SERREG IS WHEN waiting => if SL='1' then SERREG <= shc; end if; WHEN shc => SERREG <= shd; WHEN shd => if (CNT_FF = 0) then SERREG <= str; SSTR <= not CNF(0); else SERREG <= shc; end if; WHEN str => SERREG <= str1; SSTR <= not CNF(0); WHEN others => SERREG <= waiting; end case; end if; end process; with SERREG select shift <= '1' when shd, '0' when others; with SERREG select wtng <= '1' when waiting, '0' when others; with SERREG select sm_o <= "000" when waiting, "001" when shd, "010" when shc, "011" when str, "100" when str1, "111" when others; -- process(sm_o, DFF_S, A0) -- begin -- PQ <= (others => '0'); -- if A0='1' then PQ(sm_o'range) <= sm_o; -- else PQ <= DFF_S; -- end if; -- end process; with A0 select PQ <= SL & "00000000" & sm_o & CNF when '1', DFF_S when others; process(clk, RESET_n) begin if RESET_n = '0' then SCLK <= '0'; IRQi <= '0'; elsif CLK'event and CLK='1' then case SERREG is when shc => SCLK <= '1'; IRQi<= '0'; when str => SCLK <= CNF(1); IRQi<= CNF(3); when str1=> SCLK <= '0'; IRQi<= CNF(3); when others => SCLK <= '0'; IRQi<= '0'; end case; end if; end process; IRQ <= IRQi; SDAT <= DFF_S(WIDTH-1) when CNF(2)='0' else DFF_S(0); -- serial data output end;