-- -- Copyright 2018 Ettus Research, A National Instruments Company -- -- SPDX-License-Identifier: LGPL-3.0 -- -- Module: axi_bitq -- Description: Simple IP to shift bits in/out (primarily for JTAG) -- axi_bitq is the processor interface to the bitq_fsm module library ieee; use ieee.std_logic_1164.all; library work; use work.bitq_fsm; entity axi_bitq is port ( bit_clk : inout std_logic; bit_in : in std_logic; bit_out : inout std_logic; bit_stb : inout std_logic; S_AXI_ACLK : in std_logic; S_AXI_ARESETN : in std_logic; S_AXI_AWADDR : in std_logic_vector(3 downto 0); S_AXI_AWVALID : in std_logic; S_AXI_AWREADY : out std_logic; S_AXI_WDATA : in std_logic_vector(31 downto 0); S_AXI_WSTRB : in std_logic_vector(3 downto 0); S_AXI_WVALID : in std_logic; S_AXI_WREADY : out std_logic; S_AXI_BRESP : out std_logic_vector(1 downto 0); S_AXI_BVALID : out std_logic; S_AXI_BREADY : in std_logic; S_AXI_ARADDR : in std_logic_vector(3 downto 0); S_AXI_ARVALID : in std_logic; S_AXI_ARREADY : out std_logic; S_AXI_RDATA : out std_logic_vector(31 downto 0); S_AXI_RRESP : out std_logic_vector(1 downto 0); S_AXI_RVALID : out std_logic; S_AXI_RREADY : in std_logic ); end axi_bitq; architecture arch of axi_bitq is signal read_token : std_logic; signal write_addr : std_logic_vector(3 downto 0); signal write_strb : std_logic_vector(3 downto 0); signal write_addr_token : std_logic; signal write_data : std_logic_vector(31 downto 0); signal write_data_token : std_logic; signal wr_data : std_logic_vector(31 downto 0); signal stb_data : std_logic_vector(31 downto 0); signal rd_data : std_logic_vector(31 downto 0); signal prescalar : std_logic_vector(7 downto 0); signal len : std_logic_vector(4 downto 0); signal ready : std_logic; signal start : std_logic; signal bitq_rstn : std_logic; signal bitq_soft_rst : std_logic; begin S_AXI_ARREADY <= not read_token; S_AXI_RVALID <= read_token; S_AXI_RRESP <= "00"; S_AXI_AWREADY <= not write_addr_token; S_AXI_WREADY <= not write_data_token; S_AXI_BVALID <= write_addr_token and write_data_token; S_AXI_BRESP <= "00"; --Register reads read_proc : process (S_AXI_ACLK) variable read_addr : std_logic_vector(S_AXI_ARADDR'left downto S_AXI_ARADDR'right+2); begin if rising_edge(S_AXI_ACLK) then read_addr := S_AXI_ARADDR(S_AXI_ARADDR'left downto S_AXI_ARADDR'right+2); if (S_AXI_ARESETN = '0') then read_token <= '0'; elsif (S_AXI_ARVALID = '1') and (read_token = '0') then read_token <= '1'; elsif (S_AXI_RREADY = '1') and (read_token = '1') then read_token <= '0'; end if; if (S_AXI_ARVALID = '1') and (read_token = '0') then S_AXI_RDATA <= (others => '0'); case read_addr is when "00" => S_AXI_RDATA(31 downto 0) <= wr_data; when "01" => S_AXI_RDATA(31 downto 0) <= stb_data; when "10" => S_AXI_RDATA(7 downto 0) <= prescalar; S_AXI_RDATA(12 downto 8) <= len; S_AXI_RDATA(31) <= ready; when "11" => S_AXI_RDATA(31 downto 0) <= rd_data; when others => null; end case; end if; end if; end process read_proc; write_proc : process (S_AXI_ACLK) begin if rising_edge(S_AXI_ACLK) then if (S_AXI_ARESETN = '0') then write_addr_token <= '0'; write_data_token <= '0'; write_strb <= (others => '0'); else if (S_AXI_AWVALID = '1') and (write_addr_token = '0') then write_addr_token <= '1'; elsif (S_AXI_BREADY = '1') and (write_addr_token = '1') and (write_data_token = '1') then write_addr_token <= '0'; end if; if (S_AXI_WVALID = '1') and (write_data_token = '0') then write_data_token <= '1'; elsif (S_AXI_BREADY = '1') and (write_addr_token = '1') and (write_data_token = '1') then write_data_token <= '0'; end if; end if; if (S_AXI_AWVALID = '1') and (write_addr_token = '0') then write_addr <= S_AXI_AWADDR; end if; if (S_AXI_WVALID = '1') and (write_data_token = '0') then write_data <= S_AXI_WDATA; write_strb <= S_AXI_WSTRB; end if; end if; end process write_proc; write_reg : process (S_AXI_ACLK) begin if rising_edge(S_AXI_ACLK) then bitq_soft_rst <= '0'; start <= '0'; if (S_AXI_ARESETN = '0') or (bitq_soft_rst = '1') then bitq_soft_rst <= '0'; start <= '0'; elsif (write_addr_token = '1') and (write_data_token = '1') then case write_addr(write_addr'left downto 2) is when "00" => if (write_strb(0) = '1') and (ready = '1') then wr_data(7 downto 0) <= write_data(7 downto 0); end if; if (write_strb(1) = '1') and (ready = '1') then wr_data(15 downto 8) <= write_data(15 downto 8); end if; if (write_strb(2) = '1') and (ready = '1') then wr_data(23 downto 16) <= write_data(23 downto 16); end if; if (write_strb(3) = '1') and (ready = '1') then wr_data(31 downto 24) <= write_data(31 downto 24); end if; when "01" => if (write_strb(0) = '1') and (ready = '1') then stb_data(7 downto 0) <= write_data(7 downto 0); end if; if (write_strb(1) = '1') and (ready = '1') then stb_data(15 downto 8) <= write_data(15 downto 8); end if; if (write_strb(2) = '1') and (ready = '1') then stb_data(23 downto 16) <= write_data(23 downto 16); end if; if (write_strb(3) = '1') and (ready = '1') then stb_data(31 downto 24) <= write_data(31 downto 24); end if; when "10" => if (write_strb(0) = '1') and (ready = '1') then prescalar <= write_data(7 downto 0); end if; if (write_strb(1) = '1') and (ready = '1') then len <= write_data(12 downto 8); if (write_strb(3) = '0') or (write_data(31) = '0') then start <= '1'; end if; end if; if (write_strb(3) = '1') then bitq_soft_rst <= write_data(31); end if; when "11" => --Read only register null; when others => null; end case; end if; end if; end process write_reg; bitq_rstn <= '0' when (S_AXI_ARESETN = '0') or (bitq_soft_rst = '1') else '1'; bitq_ctrl : entity bitq_fsm generic map ( IDLE_VALUE => 'Z' ) port map ( clk => S_AXI_ACLK, rstn => S_AXI_ARESETN, prescalar => prescalar, bit_clk => bit_clk, bit_in => bit_in, bit_out => bit_out, bit_stb => bit_stb, start => start, len => len, ready => ready, wr_data => wr_data, stb_data => stb_data, rd_data => rd_data ); end arch;