Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
20705 Discussions

RPA FLEX 10K problem with data bus

Altera_Forum
Honored Contributor II
1,080 Views

Hi All 

 

This may well be the wrong place to ask this question. If so, I apologize in advance... just ignore my ignorance. On the off chance I am in the right place... 

 

The project I am currently working on requires an on-device RAM block that can be written to and read from over the onboard data bus. The simulations all run OK, but when I install the solution onto the real hardware the RAM block does not function at all as expecting. Here is my VHDL code (and I believe all the ports are pinned correctly). I have reduced it down to the bear essentials... the full version routes many of the memory registers to various other blocks around the circuit.... but I can't even get the noddy version to function correctly. 

 

LIBRARY ieee; 

USE ieee.std_logic_1164.all; 

USE ieee.std_logic_arith.all; 

--------------------------------------------------------- 

ENTITY basic_ram IS 

PORT ( 

clock : IN STD_LOGIC; 

addr : IN INTEGER RANGE 0 TO 30; -- Data port address 

data : INOUT STD_LOGIC_VECTOR(7 DOWNTO 0); -- Data port 

awr_n : IN STD_LOGIC; -- Date port write 

ard_n : IN STD_LOGIC); -- Data port read 

 

END basic_ram; 

--------------------------------------------------------- 

ARCHITECTURE behavior OF basic_ram IS 

 

TYPE vector_array IS ARRAY (0 TO 30) OF STD_LOGIC_VECTOR(7 DOWNTO 0); 

SIGNAL memory : vector_array; 

 

BEGIN 

 

PROCESS(clock) 

BEGIN 

 

IF RISING_EDGE(clock) THEN 

 

IF (awr_n='1') THEN 

 

memory(addr) <= data; 

 

ELSIF (ard_n='1') THEN 

 

data <= memory(addr); 

 

ELSE  

 

data <= "ZZZZZZZZ"; 

 

END IF; 

 

END IF; 

 

END PROCESS; 

 

END behavior; 

 

I have also written a simple application that uses the altera_write and altera_read commands to poke and peek the various addresses. At present what I can do is write to memory address 0x0000 and the content will be stored correctly. However, when I read back 0x0004, 0x0008 (all addresses divisible by 4 - maybe the first two bits of the address bus are not useable) that all contain the value I poked into 0x0000. All other addresses return 0xFF. 

 

I used the following fiocon command to get the ttf on to the device: 

 

fiocon -ttf simple_ram.ttf -ca 20.0 -cb 10.0 -pca 1 -pcf 0 

 

The card is from the RPA Flex 10K series and the device is the EPK10K100ARC240-1. 

 

This is really bugging me as I would think that this would be a very trivial implementation but I'm utterly stuck, and yet again feeling like a fool for not being able to figure it out. 

 

Many thanks in advance for any guidance you might be able to offer. 

 

Kurt
0 Kudos
5 Replies
Altera_Forum
Honored Contributor II
423 Views

Hi, 

 

Not sure how you are wr/rd to your ram but I don't see you are tristating your bidirectional data pins correctly. You better have two internal buses one for reading your ram and one for writing to your ram then mux them to the bidirectiona pins. You need to avoid bus contention with external drive. When you want to receive input from external device your pins must be tristated.
0 Kudos
Altera_Forum
Honored Contributor II
423 Views

I wonder how you connected your integer type address port. The results seem to show, that it's connected incorrectly. Also it's not clear, how you tested the entity. If you connected it to a soft processor I/O, a chip select is probably missing.

0 Kudos
Altera_Forum
Honored Contributor II
423 Views

Thanks Kaz - before I added the "ELSE data <= "ZZZZZZZZ";" line I did get data contention errors with Quartus on compilation. Now it compiles without such errors so I had assumed that I had tri-stated correctly. I will take another look... 

 

Kindest regards, Kurt
0 Kudos
Altera_Forum
Honored Contributor II
423 Views

Hi FvM 

 

The entity was simulated using Quartus and then I loaded onto the Altera device which is on an RPA board (http://www.rpaelectronics.com/pdf/pci_fio.pdf). I have seen chip select used in other implementations, but did no understand its role, so I will look into that again. The address port is pinned directly to the 8-bit address bus on the RPA card. I'm wondering if it might be a simple case of not running the clock fast enough. I think the RPA data/address bus runs at 33Mhz, whereas I have the RAM block running at 20MHz... I don't quite see how this leads to the strange results, but worth a try I suppose. 

 

Many thanks for your suggestions... I'm hoping that I've just overlooked some small requirement related to the RPA board... fingers crossed! 

 

Kurt
0 Kudos
Altera_Forum
Honored Contributor II
423 Views

Hi Guys 

 

This is what eventually seems to have worked - it ain't pretty but it does the job: 

 

IBRARY ieee; 

USE ieee.std_logic_1164.all; 

USE ieee.std_logic_arith.all; 

--------------------------------------------------------- 

ENTITY basic_ram IS 

PORT ( 

clock : IN STD_LOGIC; 

addr : IN STD_LOGIC_VECTOR(4 DOWNTO 0); -- Data port address 

data : INOUT STD_LOGIC_VECTOR(7 DOWNTO 0); -- Data port 

awr_n : IN STD_LOGIC; -- Date port write 

ard_n : IN STD_LOGIC; -- Data port read 

acs_n : IN STD_LOGIC); -- Data port chip select 

 

END basic_ram; 

--------------------------------------------------------- 

ARCHITECTURE behavior OF basic_ram IS 

 

TYPE vector_array IS ARRAY (0 TO 31) OF STD_LOGIC_VECTOR(7 DOWNTO 0); 

SIGNAL memory : vector_array; 

 

BEGIN 

 

PROCESS(awr_n) 

BEGIN 

 

IF RISING_EDGE(awr_n) THEN 

 

IF acs_n='0' AND ard_n='1' THEN 

 

memory(CONV_INTEGER(UNSIGNED(addr))) <= data; 

 

END IF; 

 

END IF; 

 

END PROCESS; 

 

data <= memory(0) WHEN addr = "00000" ELSE 

memory(1) WHEN addr = "00001" ELSE 

memory(2) WHEN addr = "00010" ELSE  

memory(3) WHEN addr = "00011" ELSE 

memory(4) WHEN addr = "00100" ELSE 

memory(5) WHEN addr = "00101" ELSE 

memory(6) WHEN addr = "00110" ELSE 

memory(7) WHEN addr = "00111" ELSE 

memory(8) WHEN addr = "01000" ELSE 

memory(9) WHEN addr = "01001" ELSE 

memory(10) WHEN addr = "01010" ELSE 

memory(11) WHEN addr = "01011" ELSE 

memory(12) WHEN addr = "01100" ELSE 

memory(13) WHEN addr = "01101" ELSE 

memory(14) WHEN addr = "01110" ELSE 

memory(15) WHEN addr = "01111" ELSE 

memory(16) WHEN addr = "10001" ELSE 

memory(17) WHEN addr = "10010" ELSE 

memory(18) WHEN addr = "10011" ELSE 

memory(19) WHEN addr = "10100" ELSE 

memory(20) WHEN addr = "10101" ELSE 

memory(21) WHEN addr = "10110" ELSE 

memory(22) WHEN addr = "10111" ELSE 

memory(23) WHEN addr = "11000" ELSE 

memory(24) WHEN addr = "11001" ELSE 

memory(25) WHEN addr = "11010" ELSE 

memory(26) WHEN addr = "11011" ELSE 

memory(27) WHEN addr = "11100" ELSE 

memory(28) WHEN addr = "11101" ELSE 

memory(29) WHEN addr = "11110" ELSE 

memory(30) WHEN addr = "11111" ELSE 

(others => 'Z'); 

 

END behavior; 

 

I'm assuming that the WHEN/ELSE stuff could be collapsed into the following line: 

 

data <= memory(CONV_INTEGER(UNSIGNED(addr))); 

 

Thanks for the tips! Kurt
0 Kudos
Reply