Skip to content

Instantly share code, notes, and snippets.

@apurvanandan1997
Created August 5, 2019 01:27
Show Gist options
  • Save apurvanandan1997/27a217c0cdc40d92343d748850d38837 to your computer and use it in GitHub Desktop.
Save apurvanandan1997/27a217c0cdc40d92343d748850d38837 to your computer and use it in GitHub Desktop.
----------------------------------------------------------------------------------
-- Company: apertus° Association
-- Engineer: Apurva Nandan
--
-- Create Date: 00:22:57 08/05/2019
-- Design Name:
-- Module Name: ft601
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description: FT601 Controller in FT245 mode
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity ft601 is
port (
clk : in std_logic;
rst : in std_logic;
led : out std_logic;
-- To FT601 chip
ft601_data : inout std_logic_vector(31 downto 0);
ft601_be : out std_logic_vector(3 downto 0);
ft601_rxf_n : in std_logic;
ft601_txe_n : in std_logic;
ft601_wr_n : out std_logic;
ft601_siwu_n : out std_logic;
ft601_rd_n : out std_logic;
ft601_oe_n : out std_logic;
-- From Internal FIFOs
data_in : in std_logic_vector(31 downto 0);
req_data : out std_logic;
fifo_in_emp : in std_logic;
data_wr_en : in std_logic;
-- To Internal FIFOs
data_out : out std_logic_vector(31 downto 0);
dat_out_rdy : out std_logic
);
end entity ft601;
architecture rtl of ft601 is
constant IDLE : std_logic_vector(2 downto 0) := "000";
constant INTMDT1 : std_logic_vector(2 downto 0) := "001";
constant INTMDT2 : std_logic_vector(2 downto 0) := "010";
constant INTMDT3 : std_logic_vector(2 downto 0) := "011";
constant ACTIVE_RX : std_logic_vector(2 downto 0) := "100";
constant ACTIVE_TX : std_logic_vector(2 downto 0) := "101";
signal i_state : std_logic_vector(2 downto 0) := IDLE;
signal ft601_txe : std_logic := '0';
signal ft601_rd : std_logic := '0';
signal ft601_oe : std_logic := '0';
signal ft601_rxf : std_logic := '0';
signal i_byte_en : std_logic := '0';
signal i_rd_en : std_logic := '0';
signal i_wr_en : std_logic := '0';
signal i_dat_rdy : std_logic := '0';
signal i_dat_i_buf : std_logic_vector(31 downto 0);
signal i_dat_o_buf : std_logic_vector(31 downto 0);
signal i_tx_state : std_logic_vector(2 downto 0) := IDLE;
signal i_valid : std_logic_vector(2 downto 0) := "000";
signal i_pre_valid : std_logic_vector(2 downto 0) := "000";
signal i_data : std_logic_vector(95 downto 0);
signal i_pre_data : std_logic_vector(95 downto 0);
begin
process(clk)
begin
if rising_edge(clk) then
i_dat_o_buf <= ft601_data(7 downto 0) & ft601_data(15 downto 8) & ft601_data(23 downto 16) & ft601_data(31 downto 24);
ft601_rxf <= not ft601_rxf_n;
ft601_txe <= not ft601_txe_n;
ft601_oe_n <= not ft601_oe;
ft601_rd_n <= not ft601_rd;
end if;
end process;
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
i_byte_en <= '1';
ft601_oe <= '0';
ft601_rd <= '0';
dat_out_rdy <= '0';
i_rd_en <= '0';
i_state <= IDLE;
else
if i_state = IDLE then
if ft601_rxf = '1' then
i_state <= INTMDT1;
ft601_oe <= '1';
i_byte_en <= '0';
elsif ft601_txe = '1' and i_dat_rdy = '1' then
i_state <= ACTIVE_TX;
i_rd_en <= '1';
ft601_oe <= '0';
i_byte_en <= '1';
end if;
elsif i_state = ACTIVE_TX then
if i_dat_rdy = '0' then
i_state <= IDLE;
i_rd_en <= '0';
end if;
elsif i_state = INTMDT1 then
ft601_rd <= '1';
i_state <= INTMDT2;
elsif i_state = INTMDT2 then
i_state <= INTMDT3;
elsif i_state = INTMDT3 then
i_state <= ACTIVE_RX;
elsif i_state = ACTIVE_RX then
if ft601_rxf = '1' then
dat_out_rdy <= '1';
data_out <= i_dat_o_buf;
else
i_byte_en <= '1';
ft601_oe <= '0';
ft601_rd <= '0';
dat_out_rdy <= '0';
i_rd_en <= '0';
i_state <= IDLE;
end if;
end if;
end if;
end if;
end process;
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
i_tx_state <= IDLE;
i_dat_rdy <= '0';
i_wr_en <= '0';
i_valid <= "000";
i_pre_valid <= "000";
else
if i_tx_state = IDLE then
if i_rd_en = '1' and ft601_txe = '1'
and (i_pre_valid(0) = '1' or fifo_in_emp = '0') then
i_tx_state <= ACTIVE_TX;
i_dat_i_buf <= i_pre_data(31 downto 0);
i_valid(2) <= i_pre_valid(0);
i_wr_en <= i_pre_valid(0);
i_pre_valid <= "0" & i_pre_valid(2 downto 1);
i_data(95 downto 64) <= i_pre_data(31 downto 0);
i_pre_data(63 downto 0) <= i_pre_data(95 downto 32);
end if;
i_dat_rdy <= i_pre_valid(0) or not fifo_in_emp;
elsif i_tx_state = ACTIVE_TX then
if i_rd_en = '0' or ft601_txe = '0'
or (i_pre_valid(1) = '0' and fifo_in_emp ='1') then
i_tx_state <= INTMDT1;
i_dat_rdy <= '0';
end if;
if i_pre_valid(0) = '1' then
i_data(95 downto 0) <= i_pre_data(31 downto 0) & i_data(95 downto 32);
i_pre_data(63 downto 0) <= i_pre_data(95 downto 32);
i_dat_i_buf <= i_pre_data(31 downto 0);
else
i_data(95 downto 0) <= data_in & i_data(95 downto 32);
i_pre_data(63 downto 0) <= i_pre_data(95 downto 32);
i_dat_i_buf <= data_in;
end if;
i_valid(2) <= i_pre_valid(0) or data_wr_en;
i_valid(1) <= i_valid(2);
i_valid(0) <= i_valid(1) and not ft601_txe;
i_wr_en <= i_pre_valid(0) or data_wr_en;
i_pre_valid <= "0" & i_pre_valid(2 downto 1);
elsif i_tx_state = INTMDT1 then
i_tx_state <= INTMDT2;
i_wr_en <= '0';
i_valid(1) <= i_valid(1) and not ft601_txe;
elsif i_tx_state = INTMDT2 then
i_tx_state <= INTMDT3;
i_valid(2) <= i_valid(2) and not ft601_txe;
elsif i_tx_state = INTMDT3 then
i_valid <= i_valid(1 downto 0) & "0";
i_data(95 downto 32) <= i_data( 63 downto 0);
if i_valid(1 downto 0) = "00" then
i_tx_state <= IDLE;
end if;
if i_valid(2) = '1' then
i_pre_valid <= i_pre_valid(1 downto 0) & i_valid(2);
i_pre_data <= i_pre_data(63 downto 0) & i_data(95 downto 64);
end if;
end if;
end if;
end if;
end process;
ft601_data <= i_dat_i_buf(7 downto 0) & i_dat_i_buf(15 downto 8) & i_dat_i_buf(23 downto 16) & i_dat_i_buf(31 downto 24) when i_byte_en = '1' else (others => 'Z');
req_data <= (not fifo_in_emp) and i_rd_en and ft601_txe and (not i_pre_valid(1)) when (i_tx_state = IDLE or i_tx_state = ACTIVE_TX) else '0';
ft601_be <= "1111" when i_byte_en = '1' else (others => 'Z');
ft601_siwu_n <= '1';
ft601_wr_n <= not i_wr_en;
led <= not rst when i_state /= IDLE else '0';
end architecture rtl;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment