📄 sram.vhd
字号:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use std.textio.all;
entity sram is
Generic (
mem_words : integer := 524288;
word_size : integer := 16;
tAA : time := 15 ns;
tACE : time := 15 ns;
tOE : time := 7 ns;
tOH : time := 3 ns;
tCLZ : time := 1 ns;
tCHZ : time := 7 ns;
tOLZ : time := 1 ns;
tOHZ : time := 7 ns;
tCW : time := 10 ns;
tAW : time := 10 ns;
tAS : time := 0 ns;
tWP1 : time := 10 ns;
tWP2 : time := 15 ns;
tAH : time := 0 ns; -- unimplemented
tWR : time := 0 ns; -- unimplemented
tDW : time := 7 ns;
tDH : time := 0 ns; -- unimplemented
tWZ : time := 7 ns;
tOW : time := 3 ns
);
Port ( addr : in std_logic_vector(18 downto 0);
ceN : in std_logic;
oeN : in std_logic;
weN : in std_logic;
load : in std_logic;
filename : in string(1 to 12);
load_addr : in natural;
data : inout std_logic_vector(15 downto 0);
violation : out std_logic
);
end sram;
architecture Behavioral of sram is
type mem_array is array(0 to mem_words-1) of std_logic_vector(word_size-1 downto 0);
signal baddr : std_logic_vector(18 downto 0);
signal bceN, boeN, bweN : std_logic;
signal latchdata, ce_latchdata, we_latchdata : std_logic_vector(word_size-1 downto 0);
signal ce_cycle_start, we_cycle_start, ce_cycle_end, we_cycle_end : time;
signal ce_error, we_error : std_logic;
begin
violation <= ce_error or we_error;
process (addr)
begin
baddr <= (others => 'U') after tOH, addr after tAA;
end process;
process (ceN)
variable cycle_start : time;
begin
ce_error <= '0';
if (ceN = '0') then
if (weN = '0') then
ce_cycle_start <= now;
end if;
bceN <= 'U' after tCLZ, '0' after tACE;
elsif (ceN = '1') then
if (weN = '0') then
if (we_cycle_start > ce_cycle_start) then cycle_start := we_cycle_start;
else cycle_start := ce_cycle_start;
end if;
ce_cycle_end <= now;
if (now - cycle_start < tCW) then
ce_error <= 'U';
assert (false)
report "Chip enable to write end violation."
severity error;
end if;
if (not addr'stable(tAW)) then
ce_error <= 'U';
assert (false)
report "Address setup to write end violation."
severity error;
end if;
if (not data'stable(tDW)) then
ce_error <= 'U';
assert (false)
report "Data valid to write end violation."
severity error;
end if;
if (oeN = '1') then
if (not weN'stable(tWP1)) then
ce_error <= 'U';
assert (false)
report "Write pulse width violation."
severity error;
end if;
else
if (not weN'stable(tWP2)) then
ce_error <= 'U';
assert (false)
report "Write pulse width violation."
severity error;
end if;
end if;
ce_latchdata <= data;
end if;
bceN <= '1' after tCHZ;
end if;
end process;
process (oeN)
begin
if (oeN = '0') then
boeN <= 'U' after tOLZ, '0' after tOE;
else
boeN <= '1' after tOHZ;
end if;
end process;
process (weN)
variable cycle_start : time;
begin
we_error <= '0';
if (ceN = '1') then
bweN <= weN;
elsif (weN = '0' and ceN = '0') then
we_cycle_start <= now;
if (not addr'stable(tAS)) then
we_error <= 'U';
assert (false)
report "Address setup time violation."
severity error;
end if;
bweN <= '0' after tWZ;
elsif (weN = '1' and ceN = '0') then
if (we_cycle_start > ce_cycle_start) then cycle_start := we_cycle_start;
else cycle_start := ce_cycle_start;
end if;
we_cycle_end <= now;
if (not ceN'stable(tCW)) then
we_error <= 'U';
assert (false)
report "Chip enable to write end violation."
severity error;
end if;
if (not addr'stable(tAW)) then
we_error <= 'U';
assert (false)
report "Address setup to write end violation."
severity error;
end if;
if (not data'stable(tDW)) then
we_error <= 'U';
assert (false)
report "Data valid to write end violation."
severity error;
end if;
if (oeN = '1') then
if (now - cycle_start < tWP1) then
we_error <= 'U';
assert (false)
report "Write pulse width violation."
severity error;
end if;
else
if (now - cycle_start < tWP2) then
we_error <= 'U';
assert (false)
report "Write pulse width violation."
severity error;
end if;
end if;
if (data'event) then
we_latchdata <= data'last_value;
else
we_latchdata <= data;
end if;
bweN <= '1';
end if;
end process;
process (baddr, bceN, boeN, bweN, data, load)
variable mem : mem_array;
subtype nibble is std_logic_vector(3 downto 0);
procedure hex_to_vector(variable c : in character; variable v : out nibble) is
variable l : line;
begin
case c is
when '0' => v := x"0";
when '1' => v := x"1";
when '2' => v := x"2";
when '3' => v := x"3";
when '4' => v := x"4";
when '5' => v := x"5";
when '6' => v := x"6";
when '7' => v := x"7";
when '8' => v := x"8";
when '9' => v := x"9";
when 'A' => v := x"a";
when 'B' => v := x"b";
when 'C' => v := x"c";
when 'D' => v := x"d";
when 'E' => v := x"e";
when 'F' => v := x"f";
when others =>
write(l, string'("unknown character"));
writeline(output, l);
end case;
end procedure hex_to_vector;
procedure load_file(filename : in string; addr : in natural; mem : inout mem_array) is
file f : text is in filename;
variable l : line;
variable words : natural;
variable c : character;
variable b : nibble;
begin
readline(f, l);
words := l'length / 4;
for i in 0 to words-1 loop
read(l, c);
hex_to_vector(c, b);
mem(addr + i)(3 downto 0) := b;
read(l, c);
hex_to_vector(c, b);
mem(addr + i)(7 downto 4) := b;
read(l, c);
hex_to_vector(c, b);
mem(addr + i)(11 downto 8) := b;
read(l, c);
hex_to_vector(c, b);
mem(addr + i)(15 downto 12) := b;
end loop;
end procedure load_file;
begin
if (load'event and load = '1') then
load_file(filename, load_addr, mem);
elsif ((bceN'event and bceN = '1' and bweN = '0') or
(bweN'event and bweN = '1' and bceN = '0')) then
if (ce_cycle_end > we_cycle_end) then
mem(conv_integer(baddr)) := ce_latchdata;
else
mem(conv_integer(baddr)) := we_latchdata;
end if;
end if;
if (boeN /= '1' and (bceN = 'U' or boeN = 'U' or baddr = "UUUUUUUUUUUUUUUUUUU" or bweN = 'U')) then
data <= (others => 'U');
elsif (bceN = '0' and boeN = '0' and bweN = '1') then
data <= mem(conv_integer(baddr));
else
data <= (others => 'Z');
end if;
end process;
end Behavioral;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -