Jump to content
Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

VHDL implementation of the 8255 PIO

From CPCWiki - THE Amstrad CPC encyclopedia!

This code can be used to implement an 8255 PIO in a CPLD or a FPGA.

--
-- A simulation model of I82C55 PIA
-- Copyright (c) MikeJ - Feb 2007
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS CODE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- You are responsible for any legal issues arising from your use of this code.
--
-- The latest version of this file can be found at: www.fpgaarcade.com
--
-- Email support@fpgaarcade.com
--
-- Revision list
--
-- version 001 initial release
--

library ieee ;
  use ieee.std_logic_1164.all ;
  use ieee.std_logic_unsigned.all;
  use ieee.numeric_std.all;

entity I82C55 is
  port (

    I_ADDR            : in    std_logic_vector(1 downto 0); -- A1-A0
    I_DATA            : in    std_logic_vector(7 downto 0); -- D7-D0
    O_DATA            : out   std_logic_vector(7 downto 0);
    O_DATA_OE_L       : out   std_logic;

    I_CS_L            : in    std_logic;
    I_RD_L            : in    std_logic;
    I_WR_L            : in    std_logic;

    I_PA              : in    std_logic_vector(7 downto 0);
    O_PA              : out   std_logic_vector(7 downto 0);
    O_PA_OE_L         : out   std_logic_vector(7 downto 0);

    I_PB              : in    std_logic_vector(7 downto 0);
    O_PB              : out   std_logic_vector(7 downto 0);
    O_PB_OE_L         : out   std_logic_vector(7 downto 0);

    I_PC              : in    std_logic_vector(7 downto 0);
    O_PC              : out   std_logic_vector(7 downto 0);
    O_PC_OE_L         : out   std_logic_vector(7 downto 0);

    RESET             : in    std_logic;
    ENA               : in    std_logic; -- (CPU) clk enable
    CLK               : in    std_logic
    );
end;

architecture RTL of I82C55 is

  -- registers
  signal bit_mask          : std_logic_vector(7 downto 0);
  signal r_porta           : std_logic_vector(7 downto 0);
  signal r_portb           : std_logic_vector(7 downto 0);
  signal r_portc           : std_logic_vector(7 downto 0);
  signal r_control         : std_logic_vector(7 downto 0);
  --
  signal porta_we          : std_logic;
  signal portb_we          : std_logic;
  signal porta_re          : std_logic;
  signal portb_re          : std_logic;
  --
  signal porta_we_t1       : std_logic;
  signal portb_we_t1       : std_logic;
  signal porta_re_t1       : std_logic;
  signal portb_re_t1       : std_logic;
  --
  signal porta_we_rising   : boolean;
  signal portb_we_rising   : boolean;
  signal porta_re_rising   : boolean;
  signal portb_re_rising   : boolean;
  --
  signal groupa_mode       : std_logic_vector(1 downto 0); -- port a/c upper
  signal groupb_mode       : std_logic;                    -- port b/c lower
  --
  signal porta_read        : std_logic_vector(7 downto 0);
  signal portb_read        : std_logic_vector(7 downto 0);
  signal portc_read        : std_logic_vector(7 downto 0);
  signal control_read      : std_logic_vector(7 downto 0);
  signal mode_clear        : std_logic;
  --
  signal a_inte1           : std_logic;
  signal a_inte2           : std_logic;
  signal b_inte            : std_logic;
  --
  signal a_intr            : std_logic;
  signal a_obf_l           : std_logic;
  signal a_ibf             : std_logic;
  signal a_ack_l           : std_logic;
  signal a_stb_l           : std_logic;
  signal a_ack_l_t1        : std_logic;
  signal a_stb_l_t1        : std_logic;
  --
  signal b_intr            : std_logic;
  signal b_obf_l           : std_logic;
  signal b_ibf             : std_logic;
  signal b_ack_l           : std_logic;
  signal b_stb_l           : std_logic;
  signal b_ack_l_t1        : std_logic;
  signal b_stb_l_t1        : std_logic;
  --
  signal a_ack_l_rising    : boolean;
  signal a_stb_l_rising    : boolean;
  signal b_ack_l_rising    : boolean;
  signal b_stb_l_rising    : boolean;
  --
  signal porta_ipreg       : std_logic_vector(7 downto 0);
  signal portb_ipreg       : std_logic_vector(7 downto 0);
begin
  --
  -- mode 0   - basic input/output
  -- mode 1   - strobed input/output
  -- mode 2/3 - bi-directional bus
  --
  -- control word (write)
  --
  -- D7    mode set flag        1 = active
  -- D6..5 GROUPA mode selection (mode 0,1,2)
  -- D4    GROUPA porta         1 = input, 0 = output
  -- D3    GROUPA portc upper   1 = input, 0 = output
  -- D2    GROUPB mode selection (mode 0 ,1)
  -- D1    GROUPB portb         1 = input, 0 = output
  -- D0    GROUPB portc lower   1 = input, 0 = output
  --
  -- D7    bit set/reset        0 = active
  -- D6..4 x
  -- D3..1 bit select
  -- d0    1 = set, 0 - reset
  --
  -- all output registers including status are reset when mode is changed
    --1. Port A:
    --All Modes: Output data is cleared, input data is not cleared.

    --2. Port B:
    --Mode 0: Output data is cleared, input data is not cleared.
    --Mode 1 and 2: Both output and input data are cleared.

    --3. Port C:
    --Mode 0:Output data is cleared, input data is not cleared.
    --Mode 1 and 2: IBF and INTR are cleared and OBF# is set.
    --Outputs in Port C which are not used for handshaking or interrupt signals are cleared.
    --Inputs such as STB#, ACK#, or "spare" inputs are not affected. The interrupts for Ports A and B are disabled.

  p_bit_mask : process(I_DATA)
  begin
    bit_mask <= x"01";
    case I_DATA(3 downto 1) is
      when "000" => bit_mask <= x"01";
      when "001" => bit_mask <= x"02";
      when "010" => bit_mask <= x"04";
      when "011" => bit_mask <= x"08";
      when "100" => bit_mask <= x"10";
      when "101" => bit_mask <= x"20";
      when "110" => bit_mask <= x"40";
      when "111" => bit_mask <= x"80";
      when others => null;
    end case;
  end process;

  p_write_reg_reset : process(RESET, CLK)
    variable r_portc_masked : std_logic_vector(7 downto 0);
    variable r_portc_setclr : std_logic_vector(7 downto 0);
  begin
    if (RESET = '1') then
      r_porta <= x"00";
      r_portb <= x"00";
      r_portc <= x"00";
      r_control <= x"9B"; -- 10011011
      mode_clear <= '1';
    elsif rising_edge(CLK) then

      r_portc_masked := (not bit_mask) and r_portc;
      for i in 0 to 7 loop
        r_portc_setclr(i) := bit_mask(i) and I_DATA(0);
      end loop;

      if (ENA = '1') then
        mode_clear <= '0';
        if (I_CS_L = '0') and (I_WR_L = '0') then
          case I_ADDR is
            when "00" => r_porta   <= I_DATA;
            when "01" => r_portb   <= I_DATA;
            when "10" => r_portc   <= I_DATA;

            when "11" => if (I_DATA(7) = '0') then -- set/clr
                           r_portc <= r_portc_masked or r_portc_setclr;
                         else
                           --mode_clear <= '1';
                           --r_porta    <= x"00";
                           --r_portb    <= x"00"; -- clear port b input reg
                           --r_portc    <= x"00"; -- clear control sigs
                           r_control  <= I_DATA; -- load new mode
                         end if;
            when others => null;
          end case;
        end if;
      end if;
    end if;
  end process;

  p_decode_control : process(r_control)
  begin
    groupa_mode <= r_control(6 downto 5);
    groupb_mode <= r_control(2);
  end process;

  p_oe : process(I_CS_L, I_RD_L)
  begin
    O_DATA_OE_L <= '1';
    if (I_CS_L = '0') and (I_RD_L = '0') then
      O_DATA_OE_L <= '0';
    end if;
  end process;

  p_read : process(I_ADDR, porta_read, portb_read, portc_read, control_read)
  begin
    O_DATA <= x"00"; -- default
    --if (I_CS_L = '0') and (I_RD_L = '0') then -- not required
      case I_ADDR is
        when "00" => O_DATA <= porta_read;
        when "01" => O_DATA <= portb_read;
        when "10" => O_DATA <= portc_read;
        when "11" => O_DATA <= control_read;
        when others => null;
      end case;
    --end if;
  end process;
  control_read(7) <= '1'; -- always 1
  control_read(6 downto 0) <= r_control(6 downto 0);

  p_rw_control : process(I_CS_L, I_RD_L, I_WR_L, I_ADDR)
  begin
    porta_we <= '0';
    portb_we <= '0';
    porta_re <= '0';
    portb_re <= '0';

    if (I_CS_L = '0') and (I_ADDR = "00") then
      porta_we <= not I_WR_L;
      porta_re <= not I_RD_L;
    end if;

    if (I_CS_L = '0') and (I_ADDR = "01") then
      portb_we <= not I_WR_L;
      portb_re <= not I_RD_L;
    end if;
  end process;

  p_rw_control_reg : process
  begin
    wait until rising_edge(CLK);
    if (ENA = '1') then
      porta_we_t1 <= porta_we;
      portb_we_t1 <= portb_we;
      porta_re_t1 <= porta_re;
      portb_re_t1 <= portb_re;

      a_stb_l_t1 <= a_stb_l;
      a_ack_l_t1 <= a_ack_l;
      b_stb_l_t1 <= b_stb_l;
      b_ack_l_t1 <= b_ack_l;
    end if;
  end process;

  porta_we_rising <= (porta_we = '0') and (porta_we_t1 = '1'); -- falling as inverted
  portb_we_rising <= (portb_we = '0') and (portb_we_t1 = '1'); --  "
  porta_re_rising <= (porta_re = '0') and (porta_re_t1 = '1'); -- falling as inverted
  portb_re_rising <= (portb_re = '0') and (portb_re_t1 = '1'); --  "
  --
  a_stb_l_rising  <= (a_stb_l = '1') and (a_stb_l_t1 = '0');
  a_ack_l_rising  <= (a_ack_l = '1') and (a_ack_l_t1 = '0');
  b_stb_l_rising  <= (b_stb_l = '1') and (b_stb_l_t1 = '0');
  b_ack_l_rising  <= (b_ack_l = '1') and (b_ack_l_t1 = '0');
  --
  -- GROUP A
  -- in mode 1
  --
  -- d4=1 (porta = input)
  --   pc7,6 io (d3=1 input, d3=0 output)
  --   pc5 output a_ibf
  --   pc4 input  a_stb_l
  --   pc3 output a_intr
  --
  -- d4=0 (porta = output)
  --   pc7 output a_obf_l
  --   pc6 input  a_ack_l
  --   pc5,4 io (d3=1 input, d3=0 output)
  --   pc3 output a_intr
  --
  -- GROUP B
  -- in mode 1
  -- d1=1 (portb = input)
  --   pc2 input  b_stb_l
  --   pc1 output b_ibf
  --   pc0 output b_intr
  --
  -- d1=0 (portb = output)
  --   pc2 input  b_ack_l
  --   pc1 output b_obf_l
  --   pc0 output b_intr


  -- WHEN AN INPUT
  --
  -- stb_l a low on this input latches input data
  -- ibf   a high on this output indicates data latched. set by stb_l and reset by rising edge of RD_L
  -- intr  a high on this output indicates interrupt. set by stb_l high, ibf high and inte high. reset by falling edge of RD_L
  -- inte A controlled by bit/set PC4
  -- inte B controlled by bit/set PC2

  -- WHEN AN OUTPUT
  --
  -- obf_l output will go low when cpu has written data
  -- ack_l input - a low on this clears obf_l
  -- intr  output set when ack_l is high, obf_l is high and inte is one. reset by falling edge of WR_L
  -- inte A controlled by bit/set PC6
  -- inte B controlled by bit/set PC2

  -- GROUP A
  -- in mode 2
  --
  -- porta = IO
  --
  --  control bits 2..0 still control groupb/c lower 2..0
  --
  --
  --  PC7 output a_obf
  --  PC6 input  a_ack_l
  --  PC5 output a_ibf
  --  PC4 input  a_stb_l
  --  PC3 is still interrupt out
  p_control_flags : process(RESET, CLK)
    variable we   : boolean;
    variable set1 : boolean;
    variable set2 : boolean;
  begin
    if (RESET = '1') then
      a_obf_l <= '1';
      a_inte1 <= '0';
      a_ibf   <= '0';
      a_inte2 <= '0';
      a_intr  <= '0';
      --
      b_inte  <= '0';
      b_obf_l <= '1';
      b_ibf   <= '0';
      b_intr  <= '0';
    elsif rising_edge(CLK) then
      we := (I_CS_L = '0') and (I_WR_L = '0') and (I_ADDR = "11") and (I_DATA(7) = '0');

      if (ENA = '1') then
        if (mode_clear = '1') then
          a_obf_l <= '1';
          a_inte1 <= '0';
          a_ibf   <= '0';
          a_inte2 <= '0';
          a_intr  <= '0';
          --
          b_inte  <= '0';
          b_obf_l <= '1';
          b_ibf   <= '0';
          b_intr  <= '0';
        else
          if (bit_mask(7) = '1') and we then
            a_obf_l <= I_DATA(0);
          else
            if porta_we_rising then
              a_obf_l <= '0';
            elsif (a_ack_l = '0') then
              a_obf_l <= '1';
            end if;
          end if;
          --
          if (bit_mask(6) = '1') and we then a_inte1 <= I_DATA(0); end if; -- bus set when mode1 & input?
          --
          if (bit_mask(5) = '1') and we then
            a_ibf   <= I_DATA(0);
          else
            if porta_re_rising then
              a_ibf <= '0';
            elsif (a_stb_l = '0') then
              a_ibf <= '1';
            end if;
          end if;
          --
          if (bit_mask(4) = '1') and we then a_inte2 <= I_DATA(0); end if; -- bus set when mode1 & output?
          --
          set1 := a_ack_l_rising and (a_obf_l = '1') and (a_inte1 = '1');
          set2 := a_stb_l_rising and (a_ibf   = '1') and (a_inte2 = '1');
          --
          if (bit_mask(3) = '1') and we then
            a_intr  <= I_DATA(0);
          else
            if (groupa_mode(1) = '1') then
              if (porta_we = '1') or (porta_re = '1') then
                 a_intr <= '0';
               elsif set1 or set2 then
                 a_intr <= '1';
               end if;
            else
              if    (r_control(4) = '0') then -- output
                if (porta_we = '1') then -- falling ?
                  a_intr <= '0';
                elsif set1 then
                  a_intr <= '1';
                end if;
              elsif (r_control(4) = '1') then -- input
                if (porta_re = '1') then -- falling ?
                  a_intr <= '0';
                elsif set2 then
                  a_intr <= '1';
                end if;
              end if;
            end if;
          end if;
          --
          if (bit_mask(2) = '1') and we then b_inte  <= I_DATA(0); end if; -- bus set?

          if (bit_mask(1) = '1') and we then
            b_obf_l <= I_DATA(0);
          else
            if (r_control(1) = '0') then -- output
              if portb_we_rising then
                b_obf_l <= '0';
              elsif (b_ack_l = '0') then
                b_obf_l <= '1';
              end if;
            else
              if portb_re_rising then
                b_ibf <= '0';
              elsif (b_stb_l = '0') then
                b_ibf <= '1';
              end if;
            end if;
          end if;

          if (bit_mask(0) = '1') and we then
            b_intr  <= I_DATA(0);
          else
            if (r_control(1) = '0') then -- output
              if (portb_we = '1') then -- falling ?
                b_intr <= '0';
              elsif b_ack_l_rising and (b_obf_l = '1') and (b_inte = '1') then
                b_intr <= '1';
              end if;
            else
              if (portb_re = '1') then -- falling ?
                b_intr <= '0';
              elsif b_stb_l_rising and (b_ibf = '1') and (b_inte = '1') then
                b_intr <= '1';
              end if;
            end if;
          end if;

        end if;
      end if;
    end if;
  end process;

  p_porta : process(r_porta, r_control, groupa_mode, r_porta, I_PA, porta_ipreg, a_ack_l)
  begin
    -- D4    GROUPA porta         1 = input, 0 = output
    O_PA       <= x"FF"; -- if not driven, float high
    O_PA_OE_L  <= x"FF";
    porta_read <= x"00";

    if    (groupa_mode = "00") then -- simple io
      if (r_control(4) = '0') then -- output
        O_PA       <= r_porta;
        O_PA_OE_L  <= x"00";
      end if;
      porta_read <= I_PA;
    elsif (groupa_mode = "01") then -- strobed
      if (r_control(4) = '0') then -- output
        O_PA       <= r_porta;
        O_PA_OE_L  <= x"00";
      end if;
      porta_read <= porta_ipreg;
    else -- if (groupa_mode(1) = '1') then -- bi dir
      if (a_ack_l = '0') then -- output enable
        O_PA       <= r_porta;
        O_PA_OE_L  <= x"00";
      end if;
      porta_read <= porta_ipreg; -- latched data
    end if;

  end process;

  p_portb : process(r_portb, r_control, groupb_mode, r_portb, I_PB, portb_ipreg)
  begin
    O_PB       <= x"FF"; -- if not driven, float high
    O_PB_OE_L  <= x"FF";
    portb_read <= x"00";

    if (groupb_mode = '0') then -- simple io
      if (r_control(1) = '0') then -- output
        O_PB       <= r_portb;
        O_PB_OE_L  <= x"00";
      end if;
      portb_read <= I_PB;
    else -- strobed mode
      if (r_control(1) = '0') then -- output
        O_PB       <= r_portb;
        O_PB_OE_L  <= x"00";
      end if;
      portb_read <= portb_ipreg;
    end if;
  end process;

  p_portc_out : process(r_portc, r_control, groupa_mode, groupb_mode,
                        a_obf_l, a_ibf, a_intr,b_obf_l, b_ibf, b_intr)
  begin
    O_PC       <= x"FF"; -- if not driven, float high
    O_PC_OE_L  <= x"FF";

    -- bits 7..4
    if    (groupa_mode = "00") then -- simple io
      if (r_control(3) = '0') then -- output
        O_PC     (7 downto 4)  <= r_portc(7 downto 4);
        O_PC_OE_L(7 downto 4)  <= x"0";
      end if;
    elsif (groupa_mode = "01") then -- mode1

      if (r_control(4) = '0') then -- port a output
        O_PC     (7) <= a_obf_l;
        O_PC_OE_L(7) <= '0';
        -- 6 is ack_l input
        if (r_control(3) = '0') then -- port c output
          O_PC     (5 downto 4) <= r_portc(5 downto 4);
          O_PC_OE_L(5 downto 4) <= "00";
        end if;
      else -- port a input
        if (r_control(3) = '0') then -- port c output
          O_PC     (7 downto 6) <= r_portc(7 downto 6);
          O_PC_OE_L(7 downto 6) <= "00";
        end if;
        O_PC     (5) <= a_ibf;
        O_PC_OE_L(5) <= '0';
        -- 4 is stb_l input
      end if;

    else -- if (groupa_mode(1) = '1') then -- mode2
      O_PC     (7) <= a_obf_l;
      O_PC_OE_L(7) <= '0';
      -- 6 is ack_l input
      O_PC     (5) <= a_ibf;
      O_PC_OE_L(5) <= '0';
      -- 4 is stb_l input
    end if;

    -- bit 3 (controlled by group a)
    if    (groupa_mode = "00") then -- group a steals this bit
      --if (groupb_mode = '0') then -- we will let bit 3 be driven, data sheet is a bit confused about this
        if (r_control(0) = '0') then -- ouput (note, groupb control bit)
          O_PC     (3) <= r_portc(3);
          O_PC_OE_L(3) <= '0';
        end if;
      --
    else -- stolen
      O_PC     (3) <= a_intr;
      O_PC_OE_L(3) <= '0';
    end if;

    -- bits 2..0
    if    (groupb_mode = '0') then -- simple io
      if (r_control(0) = '0') then -- output
        O_PC     (2 downto 0)  <= r_portc(2 downto 0);
        O_PC_OE_L(2 downto 0)  <= "000";
      end if;
    else
      -- mode 1
      -- 2 is input
      if (r_control(1) = '0') then -- output
        O_PC     (1) <= b_obf_l;
        O_PC_OE_L(1) <= '0';
      else -- input
        O_PC     (1) <= b_ibf;
        O_PC_OE_L(1) <= '0';
      end if;
      O_PC     (0) <= b_intr;
      O_PC_OE_L(0) <= '0';
    end if;
  end process;

  p_portc_in : process(r_portc, I_PC, r_control, groupa_mode, groupb_mode, a_ibf, b_obf_l,
                       a_obf_l, a_inte1, a_inte2, a_intr, b_inte, b_ibf, b_intr)
  begin
    portc_read <= x"00";

    a_stb_l <= '1';
    a_ack_l <= '1';
    b_stb_l <= '1';
    b_ack_l <= '1';

    if    (groupa_mode = "01") then -- mode1 or 2
      if (r_control(4) = '0') then -- port a output
        a_ack_l <= I_PC(6);
      else -- port a input
        a_stb_l <= I_PC(4);
      end if;
    elsif (groupa_mode(1) = '1') then -- mode 2
      a_ack_l <= I_PC(6);
      a_stb_l <= I_PC(4);
    end if;

    if (groupb_mode = '1') then
      if (r_control(1) = '0') then -- output
        b_ack_l <= I_PC(2);
      else -- input
        b_stb_l <= I_PC(2);
      end if;
    end if;

    if    (groupa_mode = "00") then -- simple io
      portc_read(7 downto 3) <= I_PC(7 downto 3);
    elsif (groupa_mode = "01") then
      if (r_control(4) = '0') then -- port a output
        portc_read(7 downto 3) <= a_obf_l & a_inte1 & I_PC(5 downto 4) & a_intr;
      else -- input
        portc_read(7 downto 3) <= I_PC(7 downto 6) & a_ibf & a_inte2 & a_intr;
      end if;
    else -- mode 2
      portc_read(7 downto 3) <= a_obf_l & a_inte1 & a_ibf & a_inte2 & a_intr;
    end if;

    if    (groupb_mode = '0') then -- simple io
      portc_read(2 downto 0) <= I_PC(2 downto 0);
    else
      if (r_control(1) = '0') then -- output
        portc_read(2 downto 0) <= b_inte & b_obf_l & b_intr;
      else -- input
        portc_read(2 downto 0) <= b_inte & b_ibf   & b_intr;
      end if;
    end if;
  end process;

  p_ipreg : process
  begin
    wait until rising_edge(CLK);
    --   pc4 input  a_stb_l
    --   pc2 input  b_stb_l

    if (ENA = '1') then
      if (a_stb_l = '0') then
        porta_ipreg <= I_PA;
      end if;

      if (mode_clear = '1') then
        portb_ipreg <= (others => '0');
      elsif (b_stb_l = '0') then
        portb_ipreg <= I_PB;
      end if;
    end if;
  end process;

end architecture RTL;