Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
12 years ago

Newbie - FT245 driver and 1 second period timer issue

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?

2 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    
    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;
    

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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;