vhdlbusspartan

Driving GPIO pins shared with SRAM in VHDL


I've bought a Spartan 3A development board from Micronova (http://micro-nova.com/mercury) and I've got some problems interfacing with its SRAM.

This board has 30 GPIO pins that are shared with Cypress SRAM and two pins to switch between them.

Obviously, connecting two VHDL modules (one for controlling SRAM and the other to drive GPIO) to the same pin leads to "Multiple driver error" when synthetizing.

So, to solve the problem I've created a third module as a middle controller that connects both modules with another variable for choosing which one to operate.

This works well for output, but when it comes to read input I always get 1, independently of the real value.

I don't know which pins will be used as input and which ones are for output because I would like an independent module that I can use for other projects.

This is what I got so far:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity DMA2 is
    Port (
        IOphys      : inout STD_LOGIC_VECTOR (29 downto 0);
        IOin1       : out STD_LOGIC_VECTOR (29 downto 0);
        IOin2       : out STD_LOGIC_VECTOR (29 downto 0);
        IOout1      : in STD_LOGIC_VECTOR (29 downto 0);
        IOout2      : in STD_LOGIC_VECTOR (29 downto 0);
        SwitchEn2   : in STD_LOGIC
    );
end DMA2;

architecture Behavioral of DMA2 is

begin

IOin2 <= IOphys;
IOin1 <= IOphys;
IOphys <= IOout2 when SwitchEn2 = '1' else IOout1;

end Behavioral;

IOphys are the physical pins on the board, SwitchEn2 is for choosing the driving module and the others are the inputs and outputs of the modules.


Solution

  • You don't seem to be driving your outputs. As a starter, how about defining a tristate driver like so

    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    
    entity tristate is
    port (
       signal data_in         : out   std_logic;
       signal data_out        : in    std_logic;
       signal data_tristate   : inout std_logic;
       signal tristate_select : in    std_logic
    );
    
    architecture rtl of tristate is
    begin
    
       data_in <= data_tristate;
       data_tristate <= 'z' when tristate_select = '1' else data_out;
    
    end architecture;
    

    Then selecting between its use like so

    entity arbitrate_bus
    port(
       -- the pins
       IOphys        : inout STD_LOGIC_VECTOR (29 downto 0);
       IOin1         : out STD_LOGIC_VECTOR (29 downto 0);
       IOout1        : in STD_LOGIC_VECTOR (29 downto 0);
       IO_direction1 : in STD_LOGIC_VECTOR (29 downto 0);
       IOin2         : out STD_LOGIC_VECTOR (29 downto 0);
       IOout2        : in STD_LOGIC_VECTOR (29 downto 0);
       IO_direction2 : in STD_LOGIC_VECTOR (29 downto 0);
       SwitchEn2     : in STD_LOGIC
    );
    
    architecture like_this of arbitrate_bus is
      signal input : STD_LOGIC_VECTOR (29 downto 0);
      signal output_selected : STD_LOGIC_VECTOR (29 downto 0);
      signal direction_selected  : STD_LOGIC_VECTOR (29 downto 0);
    begin
    
        output_selected    <= IOout1 when SwitchEn2 = '0' else IOout2;
        direction_selected <= IO_direction1 when SwitchEn2 = '0' else IO_direction2;
    
        g_ts: for g in output_selected'range generate
        begin
           u_ts: entity tristate
           port map(
              data_in         => input(g),
              data_out        => output_selected(g),
              data_tristate   => IOphys(g),
              tristate_select => direction_selected(g)
          );
        end generate;
    
        IOin1 <= input;
        IOin2 <= input;
    
    end architecture;