Driving GPIO pins shared with SRAM in VHDL

1.1k views Asked by At

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.

2

There are 2 answers

0
OllieB On BEST ANSWER

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;
0
Charles Steinkuehler On

What value are you assigning to the pins that are supposed to be inputs?

You may be able to infer proper operation if you assign 'Z' to the IOout1 and IOout2 signals when that pin is supposed to be an input, but I recommend you actually instantiate tri-state I/O pins. In addition to multiplexing the output state, you should also multiplex the output enable between the two modules, then your input code should work properly.

So each module generates output signals and a set of output enables. These signals get multiplexed and tied to the one set of physical pins, with the output enables determining which pins are inputs and which are outputs. This way, everything in the FPGA is binary logic and you are not relying on the synthesizer to infer a tri-state bus.