|
Message
From: cvs at opencores.org<cvs@o...>
Date: Sun Jan 20 12:21:04 CET 2008
Subject: [cvs-checkins] MODIFIED: jop ...
Date: 00/08/01 20:12:21 Added: jop/vhdl/memory sc_sram16_wr_2ws.vhd Log: SRAM16 with two waitstates for write access Revision Changes Path 1.1 jop/vhdl/memory/sc_sram16_wr_2ws.vhd http://www.opencores.org/cvsweb.shtml/jop/vhdl/memory/sc_sram16_wr_2ws.vhd?rev=1.1&content-type=text/x-cvsweb-markup Index: sc_sram16_wr_2ws.vhd =================================================================== -- -- sc_sram16.vhd -- -- SimpCon compliant external memory interface -- for 16-bit SRAM (e.g. Altera DE2 board) -- -- High 16-bit word is at lower address -- -- Connection between mem_sc and the external memory bus -- -- memory mapping -- -- 000000-x7ffff external SRAM (w mirror) max. 512 kW (4*4 MBit) -- -- RAM: 16 bit word -- -- -- 2006-08-01 Adapted from sc_ram32.vhd -- 2006-08-16 Rebuilding the already working (lost) version -- Use wait_state, din register without MUX -- 2007-06-04 changed SimpCon to records -- 2007-09-09 Additional input register for high data (correct SimpCon violation) -- 2008-01-20 Changed write access. Needs 2 waitstates now! -- Library IEEE; use IEEE.std_logic_1164.all; use ieee.numeric_std.all; use work.jop_types.all; use work.sc_pack.all; entity sc_mem_if is generic (ram_ws : integer; addr_bits : integer); port ( clk, reset : in std_logic; -- -- SimpCon memory interface -- sc_mem_out : in sc_mem_out_type; sc_mem_in : out sc_in_type; -- memory interface ram_addr : out std_logic_vector(addr_bits-1 downto 0); ram_dout : out std_logic_vector(15 downto 0); ram_din : in std_logic_vector(15 downto 0); ram_dout_en : out std_logic; ram_ncs : out std_logic; ram_noe : out std_logic; ram_nwe : out std_logic ); end sc_mem_if; architecture rtl of sc_mem_if is -- -- signals for mem interface -- type state_type is ( idl, rd1_h, rd2_h, rd1_l, rd2_l, wr1_h, wr2_h, wr3_h, wr_idl, wr1_l, wr2_l, wr3_l ); signal state : state_type; signal next_state : state_type; signal nwr_int : std_logic; signal wait_state : unsigned(3 downto 0); signal cnt : unsigned(1 downto 0); signal dout_ena : std_logic; signal rd_data_ena_h : std_logic; signal rd_data_ena_l : std_logic; signal inc_addr : std_logic; signal wr_low : std_logic; signal ram_dout_low : std_logic_vector(15 downto 0); signal ram_din_high : std_logic_vector(15 downto 0); signal ram_din_reg : std_logic_vector(31 downto 0); signal ram_ws_wr : integer; begin
ram_ws_wr <= 2; -- two wait states for write
ram_dout_en <= dout_ena;
sc_mem_in.rdy_cnt <= cnt;
--
-- Register memory address, write data and read data
--
process(clk, reset)
begin
if reset='1' then
ram_addr <= (others => '0');
ram_dout <= (others => '0');
ram_dout_low <= (others => '0');
elsif rising_edge(clk) then
if sc_mem_out.rd='1' or sc_mem_out.wr='1' then
ram_addr <= sc_mem_out.address(addr_bits-2 downto 0) & "0";
end if;
if inc_addr='1' then
ram_addr(0) <= '1';
end if;
if sc_mem_out.wr='1' then
ram_dout <= sc_mem_out.wr_data(31 downto 16);
ram_dout_low <= sc_mem_out.wr_data(15 downto 0);
end if;
if wr_low='1' then
ram_dout <= ram_dout_low;
end if;
-- use an addtional input register to adhire the SimpCon spec
-- to not change rd_data untill the full new word is available
-- results in input MUX at RAM data input
if rd_data_ena_h='1' then
ram_din_high <= ram_din;
end if;
if rd_data_ena_l='1' then
-- move first word to higher half
ram_din_reg(31 downto 16) <= ram_din_high;
-- read second word
ram_din_reg(15 downto 0) <= ram_din;
end if;
end if;
end process;
sc_mem_in.rd_data <= ram_din_reg;
--
-- next state logic
--
process(state, sc_mem_out, wait_state)
begin
next_state <= state;
case state is
when idl =>
if sc_mem_out.rd='1' then
if ram_ws=0 then
-- then we omit state rd1!
next_state <= rd2_h;
else
next_state <= rd1_h;
end if;
elsif sc_mem_out.wr='1' then
next_state <= wr1_h;
end if;
-- the WS state
when rd1_h =>
if wait_state=2 then
next_state <= rd2_h;
end if;
when rd2_h =>
-- go to read low word
if ram_ws=0 then
-- then we omit state rd1!
next_state <= rd2_l;
else
next_state <= rd1_l;
end if;
-- the WS state
when rd1_l =>
if wait_state=2 then
next_state <= rd2_l;
end if;
-- last read state
when rd2_l =>
next_state <= idl;
-- This should do to give us a pipeline
-- level of 2 for read
if sc_mem_out.rd='1' then
if ram_ws=0 then
-- then we omit state rd1!
next_state <= rd2_h;
else
next_state <= rd1_h;
end if;
elsif sc_mem_out.wr='1' then
next_state <= wr1_h;
end if;
when wr1_h =>
next_state <= wr2_h;
when wr2_h =>
next_state <= wr3_h;
when wr3_h =>
next_state <= wr_idl;
when wr_idl =>
next_state <= wr1_l;
when wr1_l =>
next_state <= wr2_l;
when wr2_l =>
next_state <= wr3_l;
when wr3_l =>
next_state <= idl;
end case;
end process;
--
-- state machine register
-- output register
--
process(clk, reset)
begin
if (reset='1') then
state <= idl;
dout_ena <= '0';
ram_ncs <= '1';
ram_noe <= '1';
rd_data_ena_h <= '0';
rd_data_ena_l <= '0';
inc_addr <= '0';
wr_low <= '0';
ram_nwe <= '1';
elsif rising_edge(clk) then
state <= next_state;
dout_ena <= '0';
ram_ncs <= '1';
ram_noe <= '1';
rd_data_ena_h <= '0';
rd_data_ena_l <= '0';
inc_addr <= '0';
wr_low <= '0';
ram_nwe <= '1';
case next_state is
when idl =>
-- the wait state
when rd1_h =>
ram_ncs <= '0';
ram_noe <= '0';
-- high word last read state
when rd2_h =>
ram_ncs <= '0';
ram_noe <= '0';
rd_data_ena_h <= '1';
inc_addr <= '1';
-- the wait state
when rd1_l =>
ram_ncs <= '0';
ram_noe <= '0';
-- low word last read state
when rd2_l =>
ram_ncs <= '0';
ram_noe <= '0';
rd_data_ena_l <= '1';
when wr1_h =>
ram_ncs <= '0';
when wr2_h =>
ram_nwe <= '0';
dout_ena <= '1';
ram_ncs <= '0';
when wr3_h =>
ram_ncs <= '0';
-- high word last write state
when wr_idl =>
ram_ncs <= '1';
dout_ena <= '1';
inc_addr <= '1';
wr_low <= '1';
when wr1_l =>
ram_ncs <= '0';
when wr2_l =>
ram_nwe <= '0';
dout_ena <= '1';
ram_ncs <= '0';
when wr3_l =>
ram_ncs <= '0';
end case;
end if;
end process;
--
-- wait_state processing
--
process(clk, reset)
begin
if (reset='1') then
wait_state <= (others => '1');
cnt <= "00";
elsif rising_edge(clk) then
wait_state <= wait_state-1;
cnt <= "11";
if next_state=idl then
cnt <= "00";
end if;
if sc_mem_out.rd='1' then
wait_state <= to_unsigned(ram_ws+1, 4);
end if;
if sc_mem_out.wr='1' then
wait_state <= to_unsigned(ram_ws_wr+1, 4);
end if;
if state=rd2_h then
wait_state <= to_unsigned(ram_ws+1, 4);
if ram_ws<3 then
cnt <= to_unsigned(ram_ws+1, 2);
else
cnt <= "11";
end if;
end if;
if state=wr_idl then
wait_state <= to_unsigned(ram_ws_wr+1, 4);
if ram_ws_wr<3 then
cnt <= to_unsigned(ram_ws_wr+1, 2);
else
cnt <= "11";
end if;
end if;
if state=rd1_l or state=rd2_l or state=wr1_l or state=wr2_l or state=wr3_l then
-- take care for pipelined cach transfer
-- there is no idl state and cnt should
-- go back to "11"
if sc_mem_out.rd='0' and sc_mem_out.wr='0' then
-- if wait_state<4 then
if wait_state(3 downto 2)="00" then
cnt <= wait_state(1 downto 0)-1;
end if;
end if;
end if;
end if;
end process;
end rtl;
|
 |