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

📄 apbps2.vhd

📁 free hardware ip core about sparcv8,a soc cpu in vhdl
💻 VHD
字号:
--------------------------------------------------------------------------------  This file is a part of the GRLIB VHDL IP LIBRARY--  Copyright (C) 2003, Gaisler Research----  This program is free software; you can redistribute it and/or modify--  it under the terms of the GNU General Public License as published by--  the Free Software Foundation; either version 2 of the License, or--  (at your option) any later version.----  This program is distributed in the hope that it will be useful,--  but WITHOUT ANY WARRANTY; without even the implied warranty of--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the--  GNU General Public License for more details.----  You should have received a copy of the GNU General Public License--  along with this program; if not, write to the Free Software--  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA ------------------------------------------------------------------------------- Entity:      apbps2-- File:        apbps2.vhd-- Author:      Marcus Hellqvist, Jiri Gaisler-- Description: PS/2 keyboard interface-----------------------------------------------------------------------------library ieee;use ieee.std_logic_1164.all;library grlib;use grlib.stdlib.all;use grlib.amba.all;use grlib.devices.all;library gaisler;use gaisler.misc.all;entity apbps2 is  generic(    pindex      : integer := 0;    paddr       : integer := 0;    pmask       : integer := 16#fff#;    pirq        : integer := 0;    fKHz        : integer := 50000;    fixed       : integer := 1    );  port(    rst         : in std_ulogic;        -- Global asynchronous reset    clk         : in std_ulogic;        -- Global clock    apbi        : in apb_slv_in_type;    apbo        : out apb_slv_out_type;    ps2i        : in ps2_in_type;    ps2o        : out ps2_out_type    );end;architecture rtl of apbps2 isconstant fifosize       : integer := 16;type rxstates is (idle,start,data,parity,stop);type txstates is (idle,waitrequest,start,data,parity,stop,ack);type fifotype is array(0 to fifosize-1) of std_logic_vector(7 downto 0);type ps2_regs is record  -- status reg  data_ready     : std_ulogic;                                   -- data ready  parity_error   : std_ulogic;                                   -- parity carry out/ error bit  frame_error    : std_ulogic;                                   -- frame error when receiving  kb_inh         : std_ulogic;                                   -- keyboard inhibit  rbf            : std_ulogic;                                   -- receiver buffer full  tbf            : std_ulogic;                                   -- transmitter buffer full  rcnt           : std_logic_vector(log2x(fifosize) downto 0);   -- fifo counter  tcnt           : std_logic_vector(log2x(fifosize) downto 0);   -- fifo counter    -- control reg  rx_en          : std_ulogic;                                   -- receive enable  tx_en          : std_ulogic;                                   -- transmit enable  rx_irq_en      : std_ulogic;                                   -- keyboard interrupt enable  tx_irq_en      : std_ulogic;                                   -- transmit interrupt enable    -- others  tx_act         : std_ulogic;                                   -- tx active  rxdf           : std_logic_vector(4 downto 0);                 -- rx data filter  rxcf           : std_logic_vector(4 downto 0);                 -- rx clock filter  rx_irq         : std_ulogic;                                   -- keyboard interrupt  tx_irq         : std_ulogic;                                   -- transmit interrupt  rxfifo         : fifotype;                                     -- fifo with 16 bytes  rraddr         : std_logic_vector(log2x(fifosize)-1 downto 0); -- fifo read address  rwaddr         : std_logic_vector(log2x(fifosize)-1 downto 0); -- fifo write address  rxstate        : rxstates;  txfifo         : fifotype;                                     -- fifo with 16 bytes  traddr         : std_logic_vector(log2x(fifosize)-1 downto 0); -- fifo read address  twaddr         : std_logic_vector(log2x(fifosize)-1 downto 0); -- fifo write address  txstate        : txstates;  ps2_clk_syn    : std_ulogic;                                   -- ps2 clock synchronized  ps2_data_syn   : std_ulogic;                                   -- ps2 data synchronized  ps2_clk_fall   : std_ulogic;                                   -- ps2 clock falling edge detector  rshift         : std_logic_vector(7 downto 0);                 -- shift register  rpar           : std_ulogic;                                   -- parity check bit  tshift         : std_logic_vector(9 downto 0);                 -- shift register  tpar           : std_ulogic;                                   -- transmit parity bit  ps2clk         : std_ulogic;                                   -- ps2 clock  ps2data        : std_ulogic;                                   -- ps2 data  ps2clkoe       : std_ulogic;                                   -- ps2 clock output enable  ps2dataoe      : std_ulogic;                                   -- ps2 data output enable  timer          : std_logic_vector(13 downto 0);                -- timer  reload         : std_logic_vector(13 downto 0);                -- reload registerend record; constant rcntzero      : std_logic_vector(log2x(fifosize) downto 0) := (others => '0'); constant REVISION      : integer := 1; constant pconfig       : apb_config_type := (                        0 => ahb_device_reg ( VENDOR_GAISLER, GAISLER_APBPS2, 0, REVISION, pirq),                        1 => apb_iobar(paddr, pmask)); signal r, rin          : ps2_regs; signal ps2_clk, ps2_data : std_ulogic;begin  ps2_op : process(r, rst, ps2_clk, ps2_data,apbi)    variable v  : ps2_regs;    variable rdata : std_logic_vector(31 downto 0);    variable irq : std_logic_vector(NAHBIRQ-1 downto 0);  begin    v := r;    rdata := (others => '0'); v.data_ready := '0'; irq := (others => '0'); irq(pirq) := r.rx_irq or r.tx_irq;    v.rx_irq := '0'; v.tx_irq := '0'; v.rbf := r.rcnt(log2x(fifosize)); v.tbf := r.tcnt(log2x(fifosize));    if r.rcnt /= rcntzero then v.data_ready := '1'; end if;    -- Synchronize and filter ps2 input    v.rxdf(0) := ps2_data; v.rxdf(4 downto 1) := r.rxdf(3 downto 0);    v.rxcf(0) := ps2_clk; v.rxcf(4 downto 1) := r.rxcf(3 downto 0);    if (r.rxdf(4) & r.rxdf(4) & r.rxdf(4) & r.rxdf(4)) = r.rxdf(3 downto 0) then      v.ps2_data_syn := r.rxdf(4);    end if;    if (r.rxcf(4) & r.rxcf(4) & r.rxcf(4) & r.rxcf(4)) = r.rxcf(3 downto 0) then      v.ps2_clk_syn := r.rxcf(4);    end if;    if (v.ps2_clk_syn /= r.ps2_clk_syn) and (v.ps2_clk_syn = '0') then      v.ps2_clk_fall := '1';    else      v.ps2_clk_fall := '0';    end if;        -- read registers    case apbi.paddr(3 downto 2) is      when "00" =>	rdata(7 downto 0) := r.rxfifo(conv_integer(r.rraddr));        if (apbi.psel(pindex) and apbi.penable and (not apbi.pwrite)) = '1' then          if r.rcnt /= rcntzero then            v.rxfifo(conv_integer(r.rraddr)) := (others => '0');            v.rraddr := r.rraddr + 1; v.rcnt := r.rcnt - 1;          end if;        end if;      when "01" =>	rdata(27 + log2x(fifosize) downto 27) := r.rcnt;        rdata(22 + log2x(fifosize) downto 22) := r.tcnt;        rdata(5 downto 0) := r.tbf & r.rbf & r.kb_inh & r.frame_error & r.parity_error & r.data_ready;      when "10" =>	rdata(3 downto 0) := r.tx_irq_en & r.rx_irq_en & r.tx_en & r.rx_en;      when others =>	if fixed = 0 then rdata(13 downto 0) := r.reload; end if;    end case;    -- write registers    if (apbi.psel(pindex) and apbi.penable and apbi.pwrite) = '1' then      case apbi.paddr(3 downto 2) is        when "00" =>          if r.tcnt(log2x(fifosize)) = '0' then            v.txfifo(conv_integer(r.twaddr)) := apbi.pwdata(7 downto 0);            v.twaddr := r.twaddr + 1; v.tcnt := r.tcnt + 1;          end if;        when "01" =>          v.kb_inh := apbi.pwdata(3);          v.frame_error := apbi.pwdata(2);          v.parity_error := apbi.pwdata(1);        when "10" =>          v.tx_irq_en := apbi.pwdata(3);          v.rx_irq_en := apbi.pwdata(2);          v.tx_en := apbi.pwdata(1);          v.rx_en := apbi.pwdata(0);        when "11" =>          if fixed = 0 then            v.reload := apbi.pwdata(13 downto 0);          end if;        when others =>          null;      end case;    end if;    case r.txstate is    when idle =>      if r.tx_en = '1' and r.tcnt /= rcntzero then        v.ps2clk := '0'; v.ps2clkoe := '0'; v.tx_act := '1';        v.ps2data := '1'; v.ps2dataoe := '0'; v.txstate := waitrequest;      end if;    when waitrequest =>      v.timer := r.timer - 1;      if (v.timer(13) and not r.timer(13)) = '1' then        if fixed = 1 then v.timer := conv_std_logic_vector(fKHz/10,14);        else v.timer := r.reload; end if;        v.ps2clk := '1'; v.ps2data := '0'; v.txstate := start;      end if;    when start  =>      v.ps2clkoe := '1';      v.tshift := "10" & r.txfifo(conv_integer(r.traddr));      v.traddr := r.traddr + 1; v.tcnt := r.tcnt - 1;      v.tpar := '1';      v.txstate := data;    when data =>      if r.ps2_clk_fall = '1' then        v.ps2data := r.tshift(0);        v.tpar := r.tpar xor r.tshift(0);        v.tshift := '1' & r.tshift(9 downto 1);        if v.tshift = "1111111110" then v.txstate := parity; end if;      end if;    when parity =>      if r.ps2_clk_fall = '1' then        v.ps2data := r.tpar; v.txstate := stop;      end if;    when stop =>      if r.ps2_clk_fall = '1' then        v.ps2data := '1'; v.txstate := ack;      end if;    when ack =>      v.ps2dataoe := '1';      if r.ps2_clk_fall = '1' and r.ps2_data_syn = '0'then        v.ps2data := '1'; v.ps2dataoe := '0'; v.tx_irq := r.tx_irq_en;        v.txstate := idle; v.tx_act := '0';      end if;    end case;    -- receiver state machine    case r.rxstate is    when idle =>      if (r.rx_en and not r.tx_act) = '1' then        v.rshift := (others => '1'); v.rxstate := start;      end if;    when start =>      if r.ps2_clk_fall = '1' then        if r.ps2_data_syn = '0' then          v.rshift := r.ps2_data_syn & r.rshift(7 downto 1);          v.rxstate := data; v.rpar := '0';          v.parity_error := '0'; v.frame_error := '0';        else v.rxstate := idle; end if;      end if;    when data =>      if r.ps2_clk_fall = '1' then        v.rshift := r.ps2_data_syn & r.rshift(7 downto 1);        v.rpar := r.rpar xor r.ps2_data_syn;        if r.rshift(0) = '0' then v.rxstate := parity; end if;      end if;    when parity =>      if r.ps2_clk_fall = '1' then        v.parity_error := r.rpar xor (not r.ps2_data_syn);        v.rxstate := stop;      end if;    when stop =>      if r.ps2_clk_fall = '1' then        if r.ps2_data_syn = '1' then          v.rx_irq := r.rx_irq_en; v.rxstate := idle;          if (r.rbf or r.parity_error) = '0' then            v.rxfifo(conv_integer(r.rwaddr)) := r.rshift(7 downto 0);            v.rwaddr := r.rwaddr + 1; v.rcnt := r.rcnt + 1;          end if;        else v.frame_error := '1'; v.rxstate := idle; end if;      end if;    end case;    -- keyboard inhibit / high impedance    if v.tx_act = '0' then      if r.rbf = '1' then        v.kb_inh := '1'; v.ps2clk := '0'; v.ps2data := '1';        v.ps2dataoe := '0'; v.ps2clkoe := '0';      else        v.ps2clk := '1'; v.ps2data := '1'; v.ps2dataoe := '1';        v.ps2clkoe := '1';      end if;    end if;    if r.tx_act = '1' then      v.rxstate := idle;    end if;        -- reset operations    if rst = '0' then      v.data_ready := '0'; v.kb_inh := '0'; v.parity_error := '0';      v.frame_error := '0'; v.rx_en := '0'; v.tx_act := '0';      v.tx_en := '0'; v.rx_irq := '0'; v.tx_irq := '0';      v.ps2_clk_fall  := '0'; v.ps2_clk_syn  := '0'; v.ps2_data_syn := '0';      v.rshift := (others => '0'); v.rxstate := idle; v.txstate := idle;      v.rraddr := (others => '0'); v.rwaddr := (others => '0');      v.rcnt := (others => '0'); v.traddr := (others => '0');      v.twaddr := (others => '0'); v.tcnt := (others => '0');      v.tshift := (others => '0'); v.tpar := '0';      v.timer := conv_std_logic_vector(fKHz/10,14);    end if;    -- update registers    rin <= v;    -- drive outputs    apbo.prdata      <= rdata;    apbo.pirq        <= irq;    apbo.pindex      <= pindex;    ps2o.ps2_clk_o   <= r.ps2clk;    ps2o.ps2_clk_oe  <= r.ps2clkoe;    ps2o.ps2_data_o  <= r.ps2data;    ps2o.ps2_data_oe <= r.ps2dataoe;  end process;  apbo.pconfig <= pconfig;  regs : process(clk)  begin    if rising_edge(clk) then      r <= rin;      ps2_data <= to_x01(ps2i.ps2_data_i);      ps2_clk <= to_x01(ps2i.ps2_clk_i);    end if;  end process;-- pragma translate_off    bootmsg : report_version    generic map ("apbps2_" & tost(pindex) & ": APB PS2 interface rev 0, irq "    & tost(pirq));-- pragma translate_onend;

⌨️ 快捷键说明

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