Reputation: 87
I'm having a heck of a time trying to figure out how to connect the core generated Block RAM of a Xilinx Spartan 6 FPGA up to a bidirectional data bus. All the examples I can find say to just use the in and out data ports individually, but in my case I am forced to use it as a bidirectional data bus.
I am using VHDL.
The generated component has the following definition:
COMPONENT ram
PORT (
clka : IN STD_LOGIC;
wea : IN STD_LOGIC_VECTOR(0 DOWNTO 0);
addra : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
dina : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
douta : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)
);
END COMPONENT;
Which is instantiated as follows:
ram1 : ram
PORT MAP (
clka => clk,
wea => r_w,
addra => addr,
dina => din,
douta => dout
);
Can someone show me a process block that will connect dina
and douta
to an inout
port called data
?
I tried the following, with 0% success:
process(clk)
begin
if rising_edge(clk) then
if r_w = "1" then
-- Write
din <= data;
dout <= temp;
else
-- Read
din <= (others => 'Z');
data <= dout;
end if;
end if;
end process;
Thank you for your assistance!
Upvotes: 3
Views: 3038
Reputation: 30342
In the if r_w = "1"
block, you appear to be trying to drive to your dout
signal, which should be driven by the port douta
. That might explain one problem (unless temp
is all 'Z's).
Caveat for the following: I don't have anything to test this on right now, so it's all off the top of my head. Let me know if it's not helpful!
I don't think that a synchronous process is the best way to approach this. It's been a while since I've needed to do this, but here's what I think you need. Note that it's not a process, it goes right in the architecture.
din <= data when (r_w = '1') else (others => 'Z');
data <= dout when (r_w = '0') else (others => 'Z');
Explanation: when signals are being driven (or assigned to) by multiple sources, all but one of them must be 'Z'. The second line sets data
to be driven by 'Z' — but this actually "frees it up" (from the point of view of the resolver) to be driven by the port.
If you do need this to be synchronous, this should be trivial to adapt — but remember that '0'
and '1'
aren't the only possible cases for std_logic
, so think about an else
clause or others
in a case
block!
Upvotes: 1
Reputation: 7785
First of all, it's important to understand that internally to a modern FPGA (such as the Xilinx Spartan-6 you are talking about), there is not really any true bidirectional routing. Real bidirectional/tristate signals can only be used on I/O pins. Internal bidirectional/tristate signals can be emulated, but this is generally only done for interfacing with legacy HDL, not for anything new.
Now, regardless of whether there was true tristate or not, in order to hook up unidirectional dina
and douta
to the a "bidirectional" data
, you need some signal to control when the memory is driving or not. Since we have short names already, let's just call it oe
for "output enable". This signal will need to be controlled by your design in a way that make sense.
Given that, you can turn your two unidirectional signals in different directions plus your output enable direction selector into a logically bidirectional data bus with the following concurrent code (not in a process):
dina <= data;
data <= douta when oe = '1' else (others => 'Z');
Upvotes: 4