Forum Discussion
Altera_Forum
Honored Contributor
16 years agoThank you for your reply,
1- I assume that is the Logic Locked region assignments you are referring to; I have not quite been able to utilize this feature properly, but the design I am working on actually uses four different copies of my memory controller, which is each contained within a logic locked region. 2- I looked at the operation in Signal Tap, and it appears as if all the timings are correct. I actually tried increasing the hold time, decreasing the memory clock etc. in order to get the design to work. 3- Are you referring to the Timing Analyzer's ability to set path constraints? The VHDL source is quite large but I will give it a shot. Right now the code is set up so that the memory can be written and read from separate sources. The SRAM being used is the CY7C1470V25. I plan on making the controller much more complexed once I get this simplified controller working properly! Thank you again.
LIBRARY WORK;
USE WORK.cy7c147.all;
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
ENTITY mem_controller_cy7c147 IS
GENERIC (
address_width : INTEGER := 12;
data_width : INTEGER := 32
);
PORT (
--Write Control Ports.
data_in : IN STD_LOGIC_VECTOR(data_width-1 DOWNTO 0);
write_address : IN STD_LOGIC_VECTOR(address_width-1 DOWNTO 0);
we : IN STD_LOGIC;
--Read Control Ports.
read_address : IN STD_LOGIC_VECTOR(address_width-1 DOWNTO 0);
--Reset
rst : IN STD_LOGIC;
--Memory Clock
mem_clk : IN STD_LOGIC;
--Data Output
data_out : OUT STD_LOGIC_VECTOR(data_width-1 DOWNTO 0);
data_ready : OUT STD_LOGIC;
--External Memory Signals
ext_data : INOUT STD_LOGIC_VECTOR(chip_data_width-1 DOWNTO 0);
ext_address : OUT STD_LOGIC_VECTOR(chip_address_width-1 DOWNTO 0);
ext_we : OUT STD_LOGIC;
ext_oe : OUT STD_LOGIC
);
END mem_controller_cy7c147;
ARCHITECTURE behavioral OF mem_controller_cy7c147 IS
TYPE sm_ext_mem_controller IS (idle, wr_init, wr_latch, wr_end, rd_init, rd_wait0, rd_wait1, rd_end);
SIGNAL state : sm_ext_mem_controller := idle;
SIGNAL buff_read_data : STD_LOGIC_VECTOR(data_width-1 DOWNTO 0);
SIGNAL buff_write_data : STD_LOGIC_VECTOR(data_width-1 DOWNTO 0);
--External Buffers
SIGNAL buff_ext_data : STD_LOGIC_VECTOR(chip_data_width-1 DOWNTO 0);
SIGNAL buff_ext_address : STD_LOGIC_VECTOR(chip_address_width-1 DOWNTO 0);
SIGNAL buff_ext_we_L : STD_LOGIC;
SIGNAL buff_ext_oe_L : STD_LOGIC;
--Read control signals
SIGNAL modified : STD_LOGIC := '0'; --Signals that the memory has been modified and should be read.
SIGNAL current_address : STD_LOGIC_VECTOR(address_width-1 DOWNTO 0); --Current address's data latched into the buff_read_data register.
BEGIN
buff_ext_address(chip_address_width-1 DOWNTO address_width) <= (OTHERS=>'0'); --Map the unused address lines to 0.
PROCESS(rst,mem_clk)
BEGIN
IF(rst='1')THEN
state <= idle;
ELSIF(RISING_EDGE(mem_clk)) THEN
CASE state IS
WHEN idle=>
--Clock domain transfer registers.
buff_write_data <= data_in;
buff_ext_data <= (OTHERS=>'Z'); --The data bus should be tri-stated in the IDLE state since we are reading.
buff_ext_oe_L <= '0'; --Ouput enable should be enabled in the IDLE state.
buff_ext_we_L <= '1'; --Disable write in the IDLE State.
IF(we='1')THEN
buff_ext_address(address_width-1 DOWNTO 0) <= write_address; --Put the write address on the bus.
buff_ext_oe_L <= '1'; --Disable the chips output enable.
modified <= '1'; --We need to signal the controller to read next chance it gets.
state <= wr_init;
ELSIF(modified = '1' OR current_address/=read_address)THEN
buff_ext_address(address_width-1 DOWNTO 0) <= read_address; --Put the read address on the bus.
modified <= '0';
state <= rd_init;
END IF;
--Write State Machine
WHEN wr_init=>
buff_ext_we_L <= '0';--Enable the Write Enable.
state <= wr_latch;
WHEN wr_latch=> --Memory gives one cycle to put data out.
buff_ext_we_L <= '1'; --Disable the Write Enable.
buff_ext_data(chip_data_width-1 DOWNTO data_width) <= (OTHERS=>'0');
buff_ext_data(data_width-1 DOWNTO 0) <= buff_write_data;
state <= wr_end;
WHEN wr_end=> --Data latched into memory.
IF(we='0')THEN
buff_ext_data <= (OTHERS=>'Z'); --The data bus should be tri-stated in the IDLE state since we are reading.
buff_ext_oe_L <= '0'; --Ouput enable should be enabled in the IDLE state.
state <= idle;
END IF;
--Read State Machine
WHEN rd_init => --First address out here.
state <= rd_wait0;
WHEN rd_wait0 => --Pause for a cycle (A read takes 3 cycles to get out of memory.)
state <= rd_wait1;
WHEN rd_wait1 =>
state <= rd_end;
WHEN rd_end =>
buff_read_data <= ext_data(data_width-1 DOWNTO 0);
current_address <= buff_ext_address(address_width-1 DOWNTO 0);
state <= idle;
END CASE;
END IF;
END PROCESS;
--This process block controls the data ready signal.
PROCESS(current_address, read_address)
BEGIN
data_ready <= '1';
IF(current_address /= read_address) THEN
data_ready <= '0';
END IF;
END PROCESS;
data_out <= buff_read_data;
ext_address <= buff_ext_address;
ext_data <= buff_ext_data;
ext_oe <= buff_ext_oe_L;
ext_we <= buff_ext_we_L;
END behavioral;