131 lines
3.2 KiB
VHDL
131 lines
3.2 KiB
VHDL
--
|
|
-- 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;
|
|
|