Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
-------------------------------------------------------------------------------
-- Project ELE8304 : Circuits intégrés à très grande échelle
-------------------------------------------------------------------------------
-- File dpm.vhd
-- Author Mickael Fiorentino <mickael.fiorentino@polymtl.ca>
-- Lab GRM - Polytechnique Montreal
-- Date 2019-08-09
-------------------------------------------------------------------------------
-- Brief Dual-port memory
-- 1-cycle read, 1-cycle write
-- Load memory content from file
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_textio.all;
library std;
use std.textio.all;
entity dpm is
generic (
WIDTH : integer := 32;
DEPTH : integer := 10;
RESET : integer := 16#00000000#;
INIT : string := "memory.mem");
port (
-- Port A
i_a_clk : in std_logic; -- Clock
i_a_rstn : in std_logic; -- Reset Address
i_a_en : in std_logic; -- Port enable
i_a_we : in std_logic; -- Write enable
i_a_addr : in std_logic_vector(DEPTH-1 downto 0); -- Address port
i_a_write : in std_logic_vector(WIDTH-1 downto 0); -- Data write port
o_a_read : out std_logic_vector(WIDTH-1 downto 0); -- Data read port
-- Port B
i_b_clk : in std_logic; -- Clock
i_b_rstn : in std_logic; -- Reset Address
i_b_en : in std_logic; -- Port enable
i_b_we : in std_logic; -- Write enable
i_b_addr : in std_logic_vector(DEPTH-1 downto 0); -- Address port
i_b_write : in std_logic_vector(WIDTH-1 downto 0); -- Data write port
o_b_read : out std_logic_vector(WIDTH-1 downto 0)); -- Data read port
end entity dpm;
architecture beh of dpm is
type t_memory is array(0 to 2**DEPTH-1) of std_logic_vector(WIDTH-1 downto 0);
------------------------------------------------------------------------------
-- LOAD_MEM
------------------------------------------------------------------------------
impure function load_mem(constant file_name : in string) return t_memory is
file ramfile : text;
variable file_status : file_open_status;
variable L : line := null;
variable Lnum : natural := 0;
variable read_ok : boolean := true;
variable at_char : std_logic;
variable next_address : natural := 0;
variable next_address_u : unsigned(WIDTH-1 downto 0);
variable ram : t_memory;
begin
-- Init RAM to 0
ram := (others => (others => '0'));
if (file_name /= "") then
-- Open init file
file_open(f => ramfile, external_name => file_name,
open_kind => read_mode, status => file_status);
-- Check opening status
assert file_status = open_ok
report "load_mem: " & to_string(file_status) & " opening file " & file_name
severity error;
-- Read and parse memory file and fill ram with its content
loop
-- Exit condition
exit when not read_ok or endfile(ramfile);
-- Read line
readline(ramfile, L);
if L(L'left) = '@' then
-- Read address
read(L, at_char, read_ok);
hread(L, next_address_u, read_ok);
-- Check that read was ok
assert read_ok = true
report "load_mem: Error reading address at line: "
& to_string(Lnum) & " in file " & file_name
severity error;
-- Update next_address
next_address := to_integer(next_address_u);
else
-- Read data
hread(L, ram(next_address), read_ok);
-- Check that read was ok
assert read_ok = true
report "load_mem: Error reading data at address: "
& to_string(next_address) & " in file " & file_name
severity error;
-- Update next address
next_address := next_address + 1;
end if;
-- Increment Line number
Lnum := Lnum + 1;
end loop;
-- Close init file
file_close(f => ramfile);
end if;
return ram;
end function load_mem;
signal mem : t_memory := load_mem(INIT);
signal a_addr_r : std_logic_vector(DEPTH-1 downto 0);
signal b_addr_r : std_logic_vector(DEPTH-1 downto 0);
begin
o_a_read <= mem(to_integer(unsigned(a_addr_r)));
o_b_read <= mem(to_integer(unsigned(b_addr_r)));
------------------------------------------------------------------------------
-- DPM
------------------------------------------------------------------------------
p_dpm : process (i_a_clk, i_a_rstn, i_b_clk, i_b_rstn) is
begin
-- PORT A
if i_a_rstn = '0' then
a_addr_r <= (others => '0');
elsif rising_edge(i_a_clk) then
if i_a_en = '1' then
if i_a_we = '1' then
mem(to_integer(unsigned(i_a_addr))) <= i_a_write;
end if;
a_addr_r <= i_a_addr;
end if;
end if;
-- PORT B
if i_b_rstn = '0' then
b_addr_r <= (others => '0');
elsif rising_edge(i_b_clk) then
if i_b_en = '1' then
if i_b_we = '1' then
mem(to_integer(unsigned(i_b_addr))) <= i_b_write;
end if;
b_addr_r <= i_b_addr;
end if;
end if;
end process p_dpm;
end architecture beh;