OpenCores
URL https://opencores.org/ocsvn/mips_enhanced/mips_enhanced/trunk

Subversion Repositories mips_enhanced

[/] [mips_enhanced/] [trunk/] [grlib-gpl-1.0.19-b3188/] [lib/] [gaisler/] [misc/] [grgpio.vhd] - Rev 2

Compare with Previous | Blame | View Log

------------------------------------------------------------------------------
--  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: 	gpio
-- File:	gpio.vhd
-- Author:	Jiri Gaisler - Gaisler Research
-- Description:	Scalable general-purpose I/O port
------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
library grlib;
use grlib.amba.all;
use grlib.stdlib.all;
use grlib.devices.all;
library gaisler;
use gaisler.misc.all;
--pragma translate_off
use std.textio.all;
--pragma translate_on
 
entity grgpio is
  generic (
    pindex   : integer := 0;
    paddr    : integer := 0;
    pmask    : integer := 16#fff#;
    imask    : integer := 16#0000#;
    nbits    : integer := 16;			-- GPIO bits
    oepol    : integer := 0;                    -- Output enable polarity
    syncrst  : integer := 0;                    -- Only synchronous reset
    bypass   : integer := 16#0000#;
    scantest : integer := 0;
    bpdir    : integer := 16#0000#
  );
  port (
    rst    : in  std_ulogic;
    clk    : in  std_ulogic;
    apbi   : in  apb_slv_in_type;
    apbo   : out apb_slv_out_type;
    gpioi  : in  gpio_in_type;
    gpioo  : out gpio_out_type
  );
end;
 
architecture rtl of grgpio is
 
constant REVISION : integer := 0;
constant PIMASK : std_logic_vector(31 downto 0) := '0' & conv_std_logic_vector(imask, 31);
 
constant BPMASK : std_logic_vector(31 downto 0) := conv_std_logic_vector(bypass, 32);
constant BPDIRM  : std_logic_vector(31 downto 0) := conv_std_logic_vector(bpdir, 32);
 
constant pconfig : apb_config_type := (
  0 => ahb_device_reg ( VENDOR_GAISLER, GAISLER_GPIO, 0, REVISION, 0),
  1 => apb_iobar(paddr, pmask));
 
type registers is record
  din1  	:  std_logic_vector(nbits-1 downto 0);
  din2  	:  std_logic_vector(nbits-1 downto 0);
  dout   	:  std_logic_vector(nbits-1 downto 0);
  imask  	:  std_logic_vector(nbits-1 downto 0);
  level  	:  std_logic_vector(nbits-1 downto 0);
  edge   	:  std_logic_vector(nbits-1 downto 0);
  ilat   	:  std_logic_vector(nbits-1 downto 0);
  dir    	:  std_logic_vector(nbits-1 downto 0);
  bypass        :  std_logic_vector(nbits-1 downto 0);
end record;
 
signal r, rin : registers;
signal arst     : std_ulogic;
 
begin
 
  arst <= apbi.testrst when (scantest = 1) and (apbi.testen = '1') else rst;
 
  comb : process(rst, r, apbi, gpioi)
  variable readdata, tmp2, dout, dir, pval, din : std_logic_vector(31 downto 0);
  variable v : registers;
  variable xirq : std_logic_vector(NAHBIRQ-1 downto 0);
  begin
 
    din := (others => '0');
    din(nbits-1 downto 0) := gpioi.din(nbits-1 downto 0);
 
    v := r; v.din2 := r.din1; v.din1 := din(nbits-1 downto 0);
    v.ilat := r.din2; dout := (others => '0'); dir := (others => '0');
    dir(nbits-1 downto 0) := r.dir(nbits-1 downto 0);
    if (syncrst = 1) and (rst = '0') then
      if oepol = 0 then dir(nbits-1 downto 0) := (others => '1');
      else dir(nbits-1 downto 0) := (others => '0'); end if;
    end if;
    dout(nbits-1 downto 0) := r.dout(nbits-1 downto 0);
 
-- read registers
 
    readdata := (others => '0');
    case apbi.paddr(4 downto 2) is
    when "000" => readdata(nbits-1 downto 0) := r.din2;
    when "001" => readdata(nbits-1 downto 0) := r.dout;
    when "010" =>
      if oepol = 0 then readdata(nbits-1 downto 0) := not r.dir;
      else readdata(nbits-1 downto 0) := r.dir; end if;
    when "011" =>
      if (imask /= 0) then
	readdata(nbits-1 downto 0) :=
	  r.imask(nbits-1 downto 0) and PIMASK(nbits-1 downto 0);
      end if;
    when "100" =>
      if (imask /= 0) then
	readdata(nbits-1 downto 0) :=
	  r.level(nbits-1 downto 0) and PIMASK(nbits-1 downto 0);
      end if;
    when "101" =>
      if (imask /= 0) then
	readdata(nbits-1 downto 0) :=
	  r.edge(nbits-1 downto 0) and PIMASK(nbits-1 downto 0);
      end if;
 
    when "110" =>
      if (bypass /= 0) then
        readdata(nbits-1 downto 0) :=
          r.bypass(nbits-1 downto 0) and BPMASK(nbits-1 downto 0);
      end if;
 
    when others =>
    end case;
 
-- write registers
 
    if (apbi.psel(pindex) and apbi.penable and apbi.pwrite) = '1' then
      case apbi.paddr(4 downto 2) is
      when "000" => null;
      when "001" => v.dout := apbi.pwdata(nbits-1 downto 0);
      when "010" =>
        if oepol = 0 then v.dir  := not apbi.pwdata(nbits-1 downto 0);
        else v.dir := apbi.pwdata(nbits-1 downto 0); end if;
      when "011" =>
        if (imask /= 0) then
	  v.imask := apbi.pwdata(nbits-1 downto 0) and PIMASK(nbits-1 downto 0);
        end if;
      when "100" =>
        if (imask /= 0) then
	  v.level := apbi.pwdata(nbits-1 downto 0) and PIMASK(nbits-1 downto 0);
        end if;
      when "101" =>
        if (imask /= 0) then
	  v.edge := apbi.pwdata(nbits-1 downto 0) and PIMASK(nbits-1 downto 0);
        end if;
 
      when "110" =>
        if (bypass /= 0) then
	  v.bypass := apbi.pwdata(nbits-1 downto 0) and BPMASK(nbits-1 downto 0);
        end if;
 
      when others =>
      end case;
    end if;
 
-- interrupt filtering and routing
 
    xirq := (others => '0'); tmp2 := (others => '0');
    if (imask /= 0) then
      tmp2(nbits-1 downto 0) := r.din2;
      for i in 0 to nbits-1 loop
        if (PIMASK(i) and r.imask(i)) = '1' then
	  if r.edge(i) = '1' then
	    if r.level(i) = '1' then tmp2(i) := r.din2(i) and not r.ilat(i);
            else tmp2(i) := not r.din2(i) and r.ilat(i); end if;
          else tmp2(i) := r.din2(i) xor not r.level(i); end if;
	else
	  tmp2(i) := '0';
        end if;
      end loop;
 
      for i in 0 to nbits-1 loop
         if i > NAHBIRQ-1 then
            exit;
         end if;
         xirq(i) := tmp2(i);
      end loop;
    end if;
 
-- drive filtered inputs on the output record
 
   pval := (others => '0');
   pval(nbits-1 downto 0) := r.din2;
 
-- Drive output with gpioi.sig_in for bypassed registers
   if bypass /= 0 then
       for i in 0 to nbits-1 loop
           if r.bypass(i) = '1' then
               dout(i) := gpioi.sig_in(i);
           end if;
       end loop;
   end if;
 
-- Drive output with gpioi.sig_in for bypassed registers
   if bpdir /= 0 then
       for i in 0 to nbits-1 loop
           if (BPDIRM(i) and gpioi.sig_en(i)) = '1'   then
               dout(i) := gpioi.sig_in(i);
               if oepol = 0 then dir(i) := '0'; else dir(i) := '1'; end if;
           end if;
       end loop;
   end if;
-- reset operation
 
    if rst = '0' then
      v.imask := (others => '0'); v.bypass := (others => '0');
      if oepol = 1 then v.dir := (others => '0');
      else v.dir := (others => '1'); end if;
      v.dout := (others => '0');
    end if;
 
    rin <= v;
 
    apbo.prdata <= readdata; 	-- drive apb read bus
    apbo.pirq <= xirq;
 
    gpioo.dout <= dout;
    gpioo.oen <= dir;
    gpioo.val <= pval;
 
-- non filtered input
    gpioo.sig_out <= din;
 
  end process;
 
  apbo.pindex <= pindex;
  apbo.pconfig <= pconfig;
 
-- registers
 
  regs : process(clk, arst)
  begin
    if rising_edge(clk) then r <= rin; end if;
    if (syncrst = 0 ) and (arst = '0') then
      if oepol = 1 then r.dir <= (others => '0');
      else r.dir <= (others => '1'); end if;
    end if;
  end process;
 
-- boot message
 
-- pragma translate_off
    bootmsg : report_version
    generic map ("grgpio" & tost(pindex) &
	": " &  tost(nbits) & "-bit GPIO Unit rev " & tost(REVISION));
-- pragma translate_on
 
end;
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.