⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ps2inerface.vhd

📁 actel BASYs开发板自带的demo程序
💻 VHD
📖 第 1 页 / 共 3 页
字号:
   
            -- with the ps2_clk line low bring ps2_data low
            -- wait for 20us and then go to tx_release_clk
            when tx_bring_data_down =>
               -- keep clock line low
               ps2_clk_h <= '0';
               -- set data line low
               -- when clock is released in the next state
               -- the device will read bit 0 on data line
               -- and this bit represents the start bit.
               ps2_data_h <= '0';   -- start bit = '0'
               if(delay_20us_done = '1') then
                  state <= tx_release_clk;
               else
                  state <= tx_bring_data_down;
               end if;
   
            -- release the ps2_clk line
            -- keep holding data line low
            when tx_release_clk =>
               ps2_clk_h <= '1';
               -- must maintain data low,
               -- otherwise will be released by default value
               ps2_data_h <= '0';
               state <= tx_first_wait_down_edge;
   
            -- state is necessary because the clock signal
            -- is not released instantaneously and, because of debounce,
            -- delay is even greater.
            -- Wait 63 clock periods for the clock line to release
            -- then if clock is low then go to tx_clk_l
            -- else wait until ps2_clk goes low.
            when tx_first_wait_down_edge =>
               ps2_data_h <= '0';
               if(delay_63clk_done = '1') then
                  if(ps2_clk_s = '0') then
                     state <= tx_clk_l;
                  else
                     state <= tx_first_wait_down_edge;
                  end if;
               else
                  state <= tx_first_wait_down_edge;
               end if;
   
            -- place the least significant bit from frame
            -- on the data line
            -- During this state the frame is shifted one
            -- bit to the right
            when tx_clk_l =>
               ps2_data_h <= frame(0);
               state <= tx_wait_up_edge;

            -- wait for the clock to go high
            -- this is the edge on which the device reads the data
            -- on ps2_data.
            -- keep holding ps2_data on frame(0) because else
            -- will be released by default value.
            -- Check if sent the last bit and if so, release data line
            -- and go to state that wait for acknowledge
            when tx_wait_up_edge =>
               ps2_data_h <= frame(0);
               -- NUMBITS - 1 because first (start bit = 0) bit was read
               -- when the clock line was released in the request to
               -- send command (see tx_bring_data_down state).
               if(bit_count = NUMBITS-1) then
                  ps2_data_h <= '1';
                  state <= tx_wait_up_edge_before_ack;
               -- if more bits to send, wait for the up edge
               -- of ps2_clk
               elsif(ps2_clk_s = '1') then
                  state <= tx_clk_h;
               else
                  state <= tx_wait_up_edge;
               end if;
   
            -- ps2_clk is released, wait for down edge
            -- and go to tx_clk_l when arrived
            when tx_clk_h =>
               ps2_data_h <= frame(0);
               if(ps2_clk_s = '0') then
                  state <= tx_clk_l;
               else
                  state <= tx_clk_h;
               end if;
   
            -- release ps2_data and wait for rising edge of ps2_clk
            -- once this occurs, transition to tx_wait_ack
            when tx_wait_up_edge_before_ack =>
               ps2_data_h <= '1';
               if(ps2_clk_s = '1') then
                  state <= tx_wait_ack;
               else
                  state <= tx_wait_up_edge_before_ack;
               end if;
            
            -- wait for the falling edge of the clock line
            -- if data line is low when this occurs, the
            -- ack is received
            -- else if data line is high, the device did not
            -- acknowledge the transimission
            when tx_wait_ack =>
               if(ps2_clk_s = '0') then
                  if(ps2_data_s = '0') then
                     -- acknowledge received
                     state <= tx_received_ack;
                  else
                     -- acknowledge not received
                     state <= tx_error_no_ack;
                  end if;
               else
                  state <= tx_wait_ack;
               end if;
   
            -- wait for ps2_clk to be released together with ps2_data
            -- (bus to be idle) and go back to idle state
            when tx_received_ack =>
               if(ps2_clk_s = '1' and ps2_data_s = '1') then
                  state  <= idle;
               else
                  state <= tx_received_ack;
               end if;
   
            -- wait for ps2_clk to be released together with ps2_data
            -- (bus to be idle) and go back to idle state
            -- signal error for not receiving ack
            when tx_error_no_ack =>
               if(ps2_clk_s = '1' and ps2_data_s = '1') then
                  err <= '1';
                  state  <= idle;
               else
                  state <= tx_error_no_ack;
               end if;
   
            -- if invalid transition occurred, signal error and
            -- go back to idle state
            when others =>
               err <= '1';
               state  <= idle;
   
         end case;
      end if;
   end process manage_fsm;

   ---------------------------------------------------------------------
   -- DELAY COUNTERS
   ---------------------------------------------------------------------

   -- Enable the 100us counter only when state is tx_force_clk_l
   delay_100us_counter_enable <= '1' when state = tx_force_clk_l else '0';

   -- Counter for a 100us delay
   -- after done counting, done signal remains active until
   -- enable counter is reset.
   delay_100us_counter: process(clk)
   begin
      if(rising_edge(clk)) then
         if(delay_100us_counter_enable = '1') then
            if(delay_100us_count = (DELAY_100US)) then
               delay_100us_count <= delay_100us_count;
               delay_100us_done <= '1';
            else
               delay_100us_count <= delay_100us_count + 1;
               delay_100us_done <= '0';
            end if;
         else
            delay_100us_count <= (others => '0');
            delay_100us_done <= '0';
         end if;
      end if;
   end process delay_100us_counter;

   -- Enable the 20us counter only when state is tx_bring_data_down
   delay_20us_counter_enable <= '1' when state = tx_bring_data_down else '0'; 

   -- Counter for a 20us delay
   -- after done counting, done signal remains active until
   -- enable counter is reset.
   delay_20us_counter: process(clk)
   begin
      if(rising_edge(clk)) then
         if(delay_20us_counter_enable = '1') then
            if(delay_20us_count = (DELAY_20US)) then
               delay_20us_count <= delay_20us_count;
               delay_20us_done <= '1';
            else
               delay_20us_count <= delay_20us_count + 1;
               delay_20us_done <= '0';
            end if;
         else
            delay_20us_count <= (others => '0');
            delay_20us_done <= '0';
         end if;
      end if;
   end process delay_20us_counter;

   -- Enable the 63clk counter only when state is tx_first_wait_down_edge
   delay_63clk_counter_enable <= '1' when state = tx_first_wait_down_edge else '0';

   -- Counter for a 63 clock periods delay
   -- after done counting, done signal remains active until
   -- enable counter is reset.
   delay_63clk_counter: process(clk)
   begin
      if(rising_edge(clk)) then
         if(delay_63clk_counter_enable = '1') then
            if(delay_63clk_count = (DELAY_63CLK)) then
               delay_63clk_count <= delay_63clk_count;
               delay_63clk_done <= '1';
            else
               delay_63clk_count <= delay_63clk_count + 1;
               delay_63clk_done <= '0';
            end if;
         else
            delay_63clk_count <= (others => '0');
            delay_63clk_done <= '0';
         end if;
      end if;
   end process delay_63clk_counter;

   ---------------------------------------------------------------------
   -- BIT COUNTER AND FRAME SHIFTING LOGIC
   ---------------------------------------------------------------------

   -- counts the number of bits shifted into the frame
   -- or out of the frame.
   bit_counter: process(clk)
   begin
      if(rising_edge(clk)) then
         if(reset_bit_count = '1') then
            bit_count <= (others => '0');
         elsif(shift_frame = '1') then
            bit_count <= bit_count + 1;
         end if;
      end if;
   end process bit_counter;

   -- shifts frame with one bit to right when shift_frame is acitve
   -- and loads data into frame from tx_data then load_tx_data is high
   load_tx_data_into_frame: process(clk)
   begin
      if(rising_edge(clk)) then
         if(load_tx_data = '1') then
            frame(8 downto 1) <= tx_data;       -- byte to send
            frame(0) <= '0';                    -- start bit
            frame(10) <= '1';                   -- stop bit
            frame(9) <= tx_parity;              -- parity bit
         elsif(shift_frame = '1') then
            -- shift right 1 bit
            frame(9 downto 0) <= frame(10 downto 1);
            -- shift in from the ps2_data line
            frame(10) <= ps2_data_s;
         end if;
      end if;
   end process load_tx_data_into_frame;

   -- Loads data from frame into rx_data output when data is ready
   do_load_rx_data: process(clk)
   begin
      if(rising_edge(clk)) then
         if(load_rx_data = '1') then
            rx_data <= frame(8 downto 1);
         end if;
      end if;
   end process do_load_rx_data;

end Behavioral;


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -