-- -- Copyright 2018 Ettus Research, A National Instruments Company -- -- SPDX-License-Identifier: LGPL-3.0 -- -- Module: bitq_fsm -- Description: Simple IP to shift bits in/out (primarily for JTAG) -- bitq_fsm implements the state machine underlying the IP library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity bitq_fsm is generic ( IDLE_VALUE : std_logic := 'Z' ); port ( clk : in std_logic; rstn : in std_logic; prescalar : in std_logic_vector(7 downto 0); bit_clk : inout std_logic; bit_in : in std_logic; bit_out : inout std_logic; bit_stb : inout std_logic; start : in std_logic; ready : out std_logic; len : in std_logic_vector(4 downto 0); wr_data : in std_logic_vector(31 downto 0); stb_data : in std_logic_vector(31 downto 0); rd_data : out std_logic_vector(31 downto 0) ); end bitq_fsm; architecture arch of bitq_fsm is type bitq_state_t is (IDLE, LOW, HIGH); signal bitq_state : bitq_state_t; signal bit_clk_count : unsigned(7 downto 0); signal bit_count : unsigned(5 downto 0); signal bit_out_r : std_logic; signal bit_stb_r : std_logic; signal rd_data_r : std_logic_vector(31 downto 0); begin rd_data <= rd_data_r; gen_io : process (bitq_state, bit_count, bit_out_r, bit_stb_r) begin case (bitq_state) is when IDLE => bit_clk <= IDLE_VALUE; bit_out <= IDLE_VALUE; bit_stb <= IDLE_VALUE; ready <= '1'; when LOW => bit_clk <= '0'; bit_out <= bit_out_r; bit_stb <= bit_stb_r; ready <= '0'; when HIGH => bit_clk <= '1'; bit_out <= bit_out_r; bit_stb <= bit_stb_r; ready <= '0'; when others => bit_clk <= IDLE_VALUE; bit_out <= IDLE_VALUE; bit_stb <= IDLE_VALUE; ready <= '1'; end case; end process; bit_clk_gen : process (clk) begin if rising_edge(clk) then if (rstn = '0') or (bitq_state = IDLE) or (bit_clk_count = 0) then bit_clk_count <= unsigned(prescalar); elsif (bit_clk_count /= 0) then bit_clk_count <= bit_clk_count - 1; end if; end if; end process bit_clk_gen; fsm : process (clk) begin if rising_edge(clk) then if (rstn = '0') then bitq_state <= IDLE; bit_count <= to_unsigned(0, bit_count'length); rd_data_r <= (others => '0'); else case bitq_state is when IDLE => bit_count <= to_unsigned(0, bit_count'length); if (start = '1') then bitq_state <= LOW; rd_data_r <= (others => '0'); bit_out_r <= wr_data(0); bit_stb_r <= stb_data(0); end if; when LOW => if (bit_clk_count = 0) then rd_data_r(to_integer(bit_count)) <= bit_in; bit_count <= bit_count + 1; bitq_state <= HIGH; --Rising edge end if; when HIGH => if (bit_clk_count = 0) then if (bit_count > unsigned('0' & len)) then bitq_state <= IDLE; else bit_out_r <= wr_data(to_integer(bit_count)); bit_stb_r <= stb_data(to_integer(bit_count)); bitq_state <= LOW; --Falling edge end if; end if; end case; end if; end if; end process fsm; end arch;