Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
21600 Discussions

Newbie - FT245 driver and 1 second period timer issue

Altera_Forum
Honored Contributor II
1,308 Views

Hello,  

 

I am a newbie in FPGA programming and VHDL, however I did some projects on Altera boards (simple 7 segments, etc).  

I am using wayengineer.com Cyclone IV board and FT245 breakout board for it. It runs on 50Mhz clock.  

I did a code that can read a single byte from the FT245 and then it will send it back.  

Problem is that every 1 second, I want the data - last byte received to be sent back. However, code constantly sends data out. It does read it correctly, so if you type 'a' it will send 'a' all the time and not when PeriodS_Reg = '1'.  

Debug led that blinks every 1 second, does blink in that interval.  

If I comment out in idle state elsif(PeriodS='1') and in reading_end I go to writing_prepare state, code correctly echo's back the last read character.  

So I think this elsif(PeriodS='1') in idle state is the problem since it always goes in it.  

 

Do you have any suggestions?
0 Kudos
2 Replies
Altera_Forum
Honored Contributor II
393 Views

library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity Test_FT245 is port ( clk : in std_logic; -- 50Mhz reset : in std_logic; -- 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; debug_led : out std_logic; debug_led2 : out std_logic; debug_led3 : out std_logic ); end entity Test_FT245; architecture behavioral of Test_FT245 is constant CMDDELAY : integer := 10; -- 10*20ns for 50Mhz clock = 200ns signal Period1uS, Period1mS, Period1S: STD_LOGIC; signal Period1S_Reg : STD_LOGIC; signal usb_input : STD_LOGIC_VECTOR (7 DOWNTO 0); signal usb_output_next: STD_LOGIC_VECTOR (7 DOWNTO 0); signal usb_output_reg : STD_LOGIC_VECTOR (7 DOWNTO 0); signal recv_data_reg : STD_LOGIC_VECTOR(7 DOWNTO 0); signal recv_data_next : STD_LOGIC_VECTOR(7 DOWNTO 0); signal rd_n_reg : STD_LOGIC; -- Registered RD_N (to be written) signal rd_n_next : STD_LOGIC; -- Next RD_N (to be registered) signal wr_reg : STD_LOGIC; -- Registered WR (to be written) signal wr_next : STD_LOGIC; -- Next WR (to be registered) signal rxf_reg : STD_LOGIC; -- Status of RX_F flag signal txe_n_reg : STD_LOGIC; -- Status of TXE_N flag signal oe_reg : STD_LOGIC; -- For Bi-Di bus (to be written) signal oe_next : STD_LOGIC; -- For Bi-Di bus (next output enable state - to be registered) signal delay_reg : integer range 0 to CMDDELAY; -- Delay counter (for start next state) signal delay_next: integer range 0 to CMDDELAY; -- Delay counter (for start next state) signal debug_led_reg : STD_LOGIC; signal debug_led_next : STD_LOGIC; signal debug_led2_reg : STD_LOGIC; signal debug_led2_next: STD_LOGIC; signal debug_led3_reg : STD_LOGIC; signal debug_led3_next: STD_LOGIC; -- Build an enumerated type for the state machine type state_type is (init, idle, reading_prepare, reading_strobe, reading_end, write_prepare, write_strobe, write_end); -- Register to hold the current state signal state_now : state_type; signal state_next : state_type; begin PROCESS( reset, clk, Period1uS, Period1mS ) VARIABLE Count : STD_LOGIC_VECTOR(5 DOWNTO 0); VARIABLE Count1 : STD_LOGIC_VECTOR(9 DOWNTO 0); VARIABLE Count2 : STD_LOGIC_VECTOR(9 DOWNTO 0); BEGIN --Period: 1uS IF( reset = '0' ) THEN Count := "000000"; ELSIF( rising_edge(clk)) THEN IF( Count>"110000" ) THEN Count := "000000"; -- 110000:48 50/50M = 1us ELSE Count := Count + 1; END IF; Period1uS <= Count(5); END IF; --Period: 1mS IF( Period1uS'EVENT AND Period1uS='1' ) THEN IF( Count1>"1111100110" ) THEN Count1 := "0000000000"; -- 1111100110:998 1000*1us = 1ms ELSE Count1 := Count1 + 1; END IF; Period1mS <= Count1(9); END IF; --Period: 1S (1111100110: 998) IF( Period1mS'EVENT AND Period1mS='1' ) THEN IF( Count2>"1111100110" ) THEN Count2 := "0000000000"; ELSE Count2 := Count2 + 1; END IF; Period1S <= Count2(9); END IF; END PROCESS; process (clk, reset) begin if (rising_edge(clk)) then if (reset = '0') then delay_reg <= 0; else if (delay_reg = 0) then state_now <= state_next; delay_reg <= delay_next; else delay_reg <= delay_reg - 1; end if; end if; end if; end process; process (clk) begin if (rising_edge(clk)) then rd_n_reg <= rd_n_next; -- Register RD_N output wr_reg <= wr_next; -- Register WR output rxf_reg <= usb_rxf_n; -- Register RXF input txe_n_reg <= usb_txe_n; -- Register TXE_N input oe_reg <= oe_next; -- Register Bi-Di OE flag debug_led_reg <= debug_led_next; debug_led2_reg <= debug_led2_next; debug_led3_reg <= debug_led3_next; usb_output_reg <= usb_output_next; recv_data_reg <= recv_data_next; Period1S_Reg <= Period1S; end if; end process; process (clk, reset, state_now) begin if (reset = '0') then rd_n_next <= '1'; wr_next <= '0'; oe_next <= '1'; -- default in output bus usb_output_next <= (others=>'0'); recv_data_next <= (others=>'0'); delay_next <= 0; debug_led_next <= '0'; debug_led2_next <= '0'; debug_led3_next <= '0'; state_next <= init; else rd_n_next <= rd_n_reg; wr_next <= wr_reg; oe_next <= oe_reg; delay_next <= delay_reg; state_next <= state_now; debug_led_next <= debug_led_reg; debug_led2_next <= debug_led2_reg; debug_led3_next <= debug_led3_reg; usb_output_next <= usb_output_reg; recv_data_next <= recv_data_reg; if(Period1S_Reg = '1') then debug_led_next <= not debug_led_reg; end if; case state_now is when init => rd_n_next <= '1'; wr_next <= '0'; oe_next <= '1'; -- default in output bus usb_output_next <= (others=>'0'); delay_next <= 0; state_next <= idle; when idle => delay_next <= 0; if(rxf_reg = '0') then state_next <= reading_prepare; elsif(Period1S_Reg = '1') then -- Send data every 1 second state_next <= write_prepare; end if; when write_prepare => debug_led2_next <= '1'; if(txe_n_reg = '0') then -- wait until TX fifo has space oe_next <= '1'; --usb_output_next <= "01000001"; usb_output_next <= recv_data_reg; delay_next <= 0; state_next <= write_strobe; end if; when write_strobe => wr_next <= '1'; delay_next <= CMDDELAY; state_next <= write_end; when write_end => debug_led2_next <= '0'; wr_next <= '0'; delay_next <= CMDDELAY; state_next <= idle; when reading_prepare => debug_led3_next <= '1'; oe_next <= '0'; delay_next <= 0; state_next <= reading_strobe; when reading_strobe => rd_n_next <= '0'; delay_next <= CMDDELAY; state_next <= reading_end; when reading_end => debug_led3_next <= '0'; recv_data_next <= usb_input; rd_n_next <= '1'; delay_next <= 0; state_next <= idle; when others => rd_n_next <= rd_n_reg; wr_next <= wr_reg; oe_next <= oe_reg; state_next <= init; delay_next <= 0; end case; end if; end process; usb_rd_n <= rd_n_reg; usb_wr <= wr_reg; debug_led <= debug_led_reg; debug_led2 <= debug_led2_reg; debug_led3 <= usb_rxf_n; usb_data <= usb_output_reg when oe_reg = '1' else (others => 'Z'); usb_input <= usb_data when oe_reg = '0'; end behavioral;

0 Kudos
Altera_Forum
Honored Contributor II
393 Views

I found out what the problem was. Period1S was high for 1ms, so while in idle state it would send bunch of data out since Period1S = '1' would be satisfied.  

I have fixed the problem with the edge detector: 

 

library ieee; use ieee.std_logic_1164.all; entity edge_detector is port ( clk_50mhz : in std_logic; rst : in std_logic; din : in std_logic; change : out std_logic; rising : out std_logic; falling : out std_logic ); end edge_detector; architecture bhv of edge_detector is signal din_delayed1 :std_logic; begin process(clk_50mhz) begin if rising_edge(clk_50mhz) then if rst = '0' then din_delayed1 <= '0'; else din_delayed1 <= din; end if; end if; end process; change <= (din_delayed1 xor din); --rising or falling edge (0 -> 1 xor 1 -> 0) rising <= ( (not din_delayed1) and din); falling <= (din_delayed1 and (not din)); end bhv;  

 

Now in my main code: 

 

signal PeriodRising : STD_LOGIC; component edge_detector is port ( clk_50mhz : in std_logic; rst : in std_logic; din : in std_logic; change : out std_logic; rising : out std_logic; falling : out std_logic ); end component; .... edetect : edge_detector port map ( rst => reset, clk_50mhz => clk, din => Period1mS, rising => PeriodRising ); ... when idle => delay_next <= 0; write_cnt_next <= 0; if(rxf_reg = '0') then state_next <= reading_prepare; elsif(PeriodRising = '1') then -- Send data every 1 second state_next <= write_prepare; end if;
0 Kudos
Reply