Forum Discussion
Altera_Forum
Honored Contributor
12 years agoAttached is a new code which works :)
Thanks for your help & feedback. I have also cleaned up the code since I implement now single process delayed state machine; so I do not need to register outputs separately as before but I update them in the FSM. Inputs from the chip are registered though in a separate process. I use this on Wayengineer Cyclone IVE FPGA board and I have tested it with another code that uses buttons to update 7-segment display and also sends current data there to the PC over USB. If someone wants, I can provide that code as well. Next step would be reading from USB and notifying...
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
ENTITY FT245 IS
PORT(
clk : IN std_logic;
rstn : IN std_logic;
txrdy : OUT std_logic;
txval : IN std_logic;
txdat : IN std_logic_vector(7 downto 0);
txbus : OUT std_logic;
-- debug
-- d_delay_reg : out std_logic_vector(3 DOWNTO 0); -- debug only
-- d_state : out std_logic_vector(2 downto 0); -- debug only
-- FT2232 Bus Signals
usb_data : inout std_logic_vector(7 downto 0);
usb_rd_n : out std_logic;
usb_wr : out std_logic;
usb_rxf_n : in std_logic;
usb_txe_n : in std_logic
);
END FT245;
ARCHITECTURE behv OF FT245 IS
constant CMDDELAY : integer := 10; -- 10*20ns for 50Mhz clock = 200ns
signal usb_input : STD_LOGIC_VECTOR (7 DOWNTO 0);
signal usb_output : STD_LOGIC_VECTOR (7 DOWNTO 0);
signal rd_n : STD_LOGIC; -- RD_N (to be written)
signal wr : STD_LOGIC; -- WR (to be written)
signal rxf_reg : STD_LOGIC; -- Status of RX_F flag
signal txe_n_reg : STD_LOGIC; -- Status of TXE_N flag
signal oe : STD_LOGIC; -- For Bi-Di bus (to be written)
begin
--{------------------------------------------------------------------------------}
--{ Params : <CLK> Clock
--{ Descript: State machine: Output buffer
--{ The output registers are updated
--{------------------------------------------------------------------------------}
process (clk)
begin
if (rising_edge(clk)) then
rxf_reg <= usb_rxf_n; -- Register RXF input
txe_n_reg <= usb_txe_n; -- Register TXE_N input
end if;
end process;
txrdy <= not txe_n_reg; -- assert txrdy when FIFO has space.
PROCESS(clk, rstn, txval, txdat, rd_n, wr, oe, usb_output, txe_n_reg, rxf_reg)
type state_type is (init, idle, write_prepare, write_strobe, write_end);
-- Register to hold the current state
VARIABLE state_now : state_type;
VARIABLE state_next : state_type;
-- Counters to implement state change delays
VARIABLE currCnt : UNSIGNED(3 DOWNTO 0);
VARIABLE cnt : UNSIGNED(3 DOWNTO 0);
CONSTANT DELAY : UNSIGNED(3 DOWNTO 0) := "1010";
BEGIN
IF(rstn = '0') THEN
cnt := (others => '0');
state_now := init;
state_next := init;
rd_n <= '1';
wr <= '0';
oe <= '1'; -- default in output bus
usb_output <= (others=>'0');
txbus <= '1';
ELSIF(rising_edge(clk)) THEN
CASE state_now IS
when init =>
rd_n <= '1';
wr <= '0';
oe <= '1'; -- default in output bus
usb_output <= (others=>'0');
txbus <= '1';
cnt := (others => '0');
state_next := idle;
when idle =>
IF(txval = '0') THEN
txbus <= '0';
ELSIF(txval = '1') THEN
state_next := write_prepare;
usb_output <= txdat;
txbus <= '1';
END IF;
when write_prepare =>
if(txe_n_reg = '0') then -- wait until TX fifo has space
oe <= '1';
state_next := write_strobe;
end if;
when write_strobe =>
wr <= '1';
cnt := DELAY;
state_next := write_end;
when write_end =>
wr <= '0';
cnt := (others => '0');
state_next := idle;
when others =>
cnt := (others => '0');
state_next := init;
END CASE;
-- handle delay between change states
currCnt := currCnt + 1;
IF(currCnt >= cnt) THEN
state_now := state_next;
cnt := (others => '0');
currCnt := (others => '0');
END IF;
-- debug only
-- IF(state_now = init) THEN
-- d_state <= "000";
-- ELSIF(state_now = idle) THEN
-- d_state <= "001";
-- ELSIF(state_now = write_prepare) THEN
-- d_state <= "010";
-- ELSIF(state_now = write_strobe) THEN
-- d_state <= "011";
-- ELSIF(state_now = write_end) THEN
-- d_state <= "100";
-- ELSE
-- d_state <= "111";
-- END IF;
-- d_delay_reg <= std_logic_vector(cnt); -- debug only
END IF;
END PROCESS;
--{------------------------------------------------------------------------------}
--{ Descript: Output
--{ The actual outputs are set
--{------------------------------------------------------------------------------}
usb_rd_n <= rd_n;
usb_wr <= wr;
usb_data <= usb_output when oe = '1' else (others => 'Z');
usb_input <= usb_data when oe = '0';
END behv;