1 |
2 |
madsilicon |
-----------------------------------------------------------------
|
2 |
|
|
-- --
|
3 |
|
|
-----------------------------------------------------------------
|
4 |
|
|
-- --
|
5 |
|
|
-- Copyright (C) 2015 Stefano Tonello --
|
6 |
|
|
-- --
|
7 |
|
|
-- This source file may be used and distributed without --
|
8 |
|
|
-- restriction provided that this copyright statement is not --
|
9 |
|
|
-- removed from the file and that any derivative work contains --
|
10 |
|
|
-- the original copyright notice and the associated disclaimer.--
|
11 |
|
|
-- --
|
12 |
|
|
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY --
|
13 |
|
|
-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED --
|
14 |
|
|
-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS --
|
15 |
|
|
-- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR --
|
16 |
|
|
-- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, --
|
17 |
|
|
-- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES --
|
18 |
|
|
-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE --
|
19 |
|
|
-- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR --
|
20 |
|
|
-- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF --
|
21 |
|
|
-- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT --
|
22 |
|
|
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT --
|
23 |
|
|
-- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE --
|
24 |
|
|
-- POSSIBILITY OF SUCH DAMAGE. --
|
25 |
|
|
-- --
|
26 |
|
|
-----------------------------------------------------------------
|
27 |
|
|
|
28 |
|
|
---------------------------------------------------------------
|
29 |
|
|
-- RV01 top-level module
|
30 |
|
|
---------------------------------------------------------------
|
31 |
|
|
|
32 |
|
|
library IEEE;
|
33 |
|
|
use IEEE.std_logic_1164.all;
|
34 |
|
|
use IEEE.numeric_std.all;
|
35 |
|
|
use STD.textio.all;
|
36 |
|
|
|
37 |
|
|
library WORK;
|
38 |
|
|
use work.RV01_CONSTS_PKG.all;
|
39 |
|
|
use work.RV01_TYPES_PKG.all;
|
40 |
|
|
use work.RV01_FUNCS_PKG.all;
|
41 |
|
|
use work.RV01_PLIC_PKG.all;
|
42 |
|
|
|
43 |
|
|
entity RV01_TOP is
|
44 |
|
|
generic(
|
45 |
|
|
-- synthesis translate_off
|
46 |
|
|
ST_FILE : string := "NONE";
|
47 |
|
|
WB_FILE : string := "NONE";
|
48 |
|
|
-- synthesis translate_on
|
49 |
|
|
IMEM_SIZE : natural := 1024*32; -- 128Kb
|
50 |
|
|
DMEM_SIZE : natural := 1024*16; -- 64Kb
|
51 |
|
|
IOMEM_SIZE : natural := 1024; -- 4Kb
|
52 |
|
|
IMEM_SIZE_PO2 : std_logic := '1';
|
53 |
|
|
DMEM_SIZE_PO2 : std_logic := '1';
|
54 |
|
|
IMEM_LOWM : std_logic := '1';
|
55 |
|
|
BHT_SIZE : natural := 256;
|
56 |
|
|
EI_SRC_CNT : natural := 8;
|
57 |
|
|
EI_TRIG_TYPE : PLIC_TRIG_TYPE := LEVEL;
|
58 |
|
|
EI_REQ_MAXCNT : natural := 16;
|
59 |
|
|
CFG_FLAGS : std_logic_vector(16-1 downto 0) := "00000000"&"01100111";
|
60 |
|
|
SIMULATION_ONLY : std_logic := '0'
|
61 |
|
|
);
|
62 |
|
|
port(
|
63 |
|
|
CLK_i : in std_logic; -- clock
|
64 |
|
|
RST_i : in std_logic; -- reset
|
65 |
|
|
CHK_ENB_i : in std_logic; -- check-enable
|
66 |
|
|
-- External Interrupt Request
|
67 |
|
|
EI_REQ_i : std_logic_vector(EI_SRC_CNT-1 downto 0);
|
68 |
|
|
-- Host interface
|
69 |
|
|
MFROMHOST_WE_i : in std_logic; -- MFROMHOST write-enable
|
70 |
|
|
MFROMHOST_i : in std_logic_vector(SDLEN-1 downto 0); -- MFROMHOST data-in
|
71 |
|
|
-- Data port
|
72 |
|
|
DP_WE_i : in std_logic; -- DP write-enable
|
73 |
|
|
DP_ADR_i : in std_logic_vector(ALEN-1 downto 0); -- DP address
|
74 |
|
|
DP_DAT_i : in std_logic_vector(SDLEN-1 downto 0); -- DP data-in
|
75 |
|
|
-- Control port
|
76 |
|
|
CP_RE_i : in std_logic; -- CP read-enable
|
77 |
|
|
CP_WE_i : in std_logic; -- CP write-enable
|
78 |
|
|
CP_ADR_i : in std_logic_vector(17-1 downto 0); -- CP address
|
79 |
|
|
CP_DAT_i : in std_logic_vector(SDLEN-1 downto 0); -- CP data-in
|
80 |
|
|
|
81 |
|
|
-- Host interface
|
82 |
|
|
MTOHOST_OE_o : out std_logic; -- MTOHOST output-enable
|
83 |
|
|
MTOHOST_o : out std_logic_vector(SDLEN-1 downto 0); -- MTOHOST data-out
|
84 |
|
|
-- Data port
|
85 |
|
|
DP_DAT_o : out std_logic_vector(SDLEN-1 downto 0); -- DP data-out
|
86 |
|
|
-- Control port
|
87 |
|
|
CP_DAT_o : out std_logic_vector(SDLEN-1 downto 0) -- CP data-out
|
88 |
|
|
);
|
89 |
|
|
end RV01_TOP;
|
90 |
|
|
|
91 |
|
|
architecture ARC of RV01_TOP is
|
92 |
|
|
|
93 |
|
|
constant L2IMEM_SIZE : natural := log2(IMEM_SIZE);
|
94 |
|
|
constant L2DMEM_SIZE : natural := log2(DMEM_SIZE);
|
95 |
|
|
constant L2IOMEM_SIZE : natural := log2(DMEM_SIZE);
|
96 |
|
|
|
97 |
|
|
constant PARALLEL_EXECUTION_ENABLED : std_logic := CFG_FLAGS(0);
|
98 |
|
|
constant PLIC_PRESENT : std_logic := CFG_FLAGS(6);
|
99 |
|
|
|
100 |
|
|
constant PLIC_ABASE : natural := DMEM_SIZE;
|
101 |
|
|
constant PLIC_AWIDTH : natural := log2(EI_SRC_CNT+3);
|
102 |
|
|
constant PLIC_AMAX : natural := ((EI_SRC_CNT+3)-1);
|
103 |
|
|
|
104 |
|
|
component RV01_CPU_2W is
|
105 |
|
|
generic(
|
106 |
|
|
-- synthesis translate_off
|
107 |
|
|
ST_FILENAME : string := "NONE";
|
108 |
|
|
WB_FILENAME : string := "NONE";
|
109 |
|
|
-- synthesis translate_on
|
110 |
|
|
IMEM_SIZE : natural := 1024*32; -- 128Kb
|
111 |
|
|
DMEM_SIZE : natural := 1024*16; -- 64Kb
|
112 |
|
|
IMEM_LOWM : std_logic := '1';
|
113 |
|
|
BHT_SIZE : natural := 256;
|
114 |
|
|
CFG_FLAGS : std_logic_vector(16-1 downto 0) := "00000000"&"01100111";
|
115 |
|
|
SIMULATION_ONLY : std_logic := '1'
|
116 |
|
|
);
|
117 |
|
|
port(
|
118 |
|
|
CLK_i : in std_logic;
|
119 |
|
|
RST_i : in std_logic;
|
120 |
|
|
-- instruction memory interface
|
121 |
|
|
INSTR_i : in std_logic_vector(ILEN*2-1 downto 0);
|
122 |
|
|
-- data memory interface
|
123 |
|
|
DDAT0_i : in std_logic_vector(SDLEN-1 downto 0);
|
124 |
|
|
DDAT1_i : in std_logic_vector(SDLEN-1 downto 0);
|
125 |
|
|
IADR_ERR_i : in std_logic;
|
126 |
|
|
DADR0_ERR_i : in std_logic;
|
127 |
|
|
DADR1_ERR_i : in std_logic;
|
128 |
|
|
IDADR_CFLT_i : in std_logic;
|
129 |
|
|
-- check-enable (simulation-only)
|
130 |
|
|
CHK_ENB_i : in std_logic;
|
131 |
|
|
-- External Interrupt (from PLIC)
|
132 |
|
|
EXT_INT_i : in std_logic;
|
133 |
|
|
-- Host interface
|
134 |
|
|
MFROMHOST_WE_i : in std_logic;
|
135 |
|
|
MFROMHOST_i : in std_logic_vector(SDLEN-1 downto 0);
|
136 |
|
|
-- Control port
|
137 |
|
|
CP_RE_i : in std_logic;
|
138 |
|
|
CP_WE_i : in std_logic;
|
139 |
|
|
CP_ADR_i : in std_logic_vector(17-1 downto 0);
|
140 |
|
|
CP_D_i : in std_logic_vector(SDLEN-1 downto 0);
|
141 |
|
|
|
142 |
|
|
HALT_o : out std_logic;
|
143 |
|
|
-- instruction memory interface
|
144 |
|
|
IADR_o : out unsigned(ALEN-1 downto 0);
|
145 |
|
|
-- data memory interface
|
146 |
|
|
DRE_o : out std_logic_vector(2-1 downto 0);
|
147 |
|
|
DBE_o : out std_logic_vector(4-1 downto 0);
|
148 |
|
|
DWE0_o : out std_logic;
|
149 |
|
|
DADR0_o : out unsigned(ALEN-1 downto 0);
|
150 |
|
|
DADR1_o : out unsigned(ALEN-1 downto 0);
|
151 |
|
|
DIADR0_o : out unsigned(ALEN-1 downto 0);
|
152 |
|
|
DIADR1_o : out unsigned(ALEN-1 downto 0);
|
153 |
|
|
DIMS_o : out std_logic_vector(2-1 downto 0);
|
154 |
|
|
DDAT0_o : out std_logic_vector(SDLEN-1 downto 0);
|
155 |
|
|
-- Host interface
|
156 |
|
|
MTOHOST_OE_o : out std_logic;
|
157 |
|
|
MTOHOST_o : out std_logic_vector(SDLEN-1 downto 0);
|
158 |
|
|
-- Control port
|
159 |
|
|
CP_Q_o : out std_logic_vector(SDLEN-1 downto 0)
|
160 |
|
|
);
|
161 |
|
|
end component;
|
162 |
|
|
|
163 |
|
|
component RV01_PLIC is
|
164 |
|
|
generic(
|
165 |
|
|
SRC_CNT : natural := 8;
|
166 |
|
|
TRIG_TYPE : PLIC_TRIG_TYPE := LEVEL;
|
167 |
|
|
REQ_MAXCNT : natural := 16
|
168 |
|
|
);
|
169 |
|
|
port(
|
170 |
|
|
CLK_i : in std_logic;
|
171 |
|
|
RST_i : in std_logic;
|
172 |
|
|
REG_A_i : in std_logic_vector(log2(SRC_CNT+1)-1 downto 0);
|
173 |
|
|
REG_WE_i : in std_logic;
|
174 |
|
|
REG_D_i : in std_logic_vector(SDLEN-1 downto 0);
|
175 |
|
|
REQ_i : in std_logic_vector(SRC_CNT-1 downto 0);
|
176 |
|
|
|
177 |
|
|
REG_Q_o : out std_logic_vector(SDLEN-1 downto 0);
|
178 |
|
|
EIP_o : out std_logic
|
179 |
|
|
);
|
180 |
|
|
end component;
|
181 |
|
|
|
182 |
|
|
component RV01_RAM_1RW1R_BE is
|
183 |
|
|
generic(
|
184 |
|
|
-- I/O data bus width
|
185 |
|
|
DWIDTH : integer := 16;
|
186 |
|
|
-- word count
|
187 |
|
|
WCOUNT : integer := 256
|
188 |
|
|
);
|
189 |
|
|
port(
|
190 |
|
|
CLK_i : in std_logic;
|
191 |
|
|
A_i : in unsigned(log2(WCOUNT)-1 downto 0);
|
192 |
|
|
DPRA_i : in unsigned(log2(WCOUNT)-1 downto 0);
|
193 |
|
|
D_i : in std_logic_vector(DWIDTH-1 downto 0);
|
194 |
|
|
BE_i : in std_logic_vector(DWIDTH/8-1 downto 0);
|
195 |
|
|
WE_i : in std_logic;
|
196 |
|
|
|
197 |
|
|
Q_o : out std_logic_vector(DWIDTH-1 downto 0);
|
198 |
|
|
DPQ_o : out std_logic_vector(DWIDTH-1 downto 0)
|
199 |
|
|
);
|
200 |
|
|
end component;
|
201 |
|
|
|
202 |
|
|
component RV01_RAM_1RW_BE is
|
203 |
|
|
generic(
|
204 |
|
|
-- I/O data bus width
|
205 |
|
|
DWIDTH : integer := 16;
|
206 |
|
|
-- word count
|
207 |
|
|
WCOUNT : integer := 256
|
208 |
|
|
);
|
209 |
|
|
port(
|
210 |
|
|
CLK_i : in std_logic;
|
211 |
|
|
A_i : in unsigned(log2(WCOUNT)-1 downto 0);
|
212 |
|
|
D_i : in std_logic_vector(DWIDTH-1 downto 0);
|
213 |
|
|
BE_i : in std_logic_vector(DWIDTH/8-1 downto 0);
|
214 |
|
|
WE_i : in std_logic;
|
215 |
|
|
|
216 |
|
|
Q_o : out std_logic_vector(DWIDTH-1 downto 0)
|
217 |
|
|
);
|
218 |
|
|
end component;
|
219 |
|
|
|
220 |
|
|
signal HALT : std_logic;
|
221 |
|
|
signal EXT_INT : std_logic;
|
222 |
|
|
signal INSTR : std_logic_vector(ILEN*2-1 downto 0);
|
223 |
|
|
signal DDATI0 : std_logic_vector(SDLEN-1 downto 0);
|
224 |
|
|
signal DDATI1 : std_logic_vector(SDLEN-1 downto 0);
|
225 |
|
|
signal IWE0 : std_logic;
|
226 |
|
|
signal IADR0 : unsigned(ALEN-1 downto 0);
|
227 |
|
|
signal IADR1 : unsigned(ALEN-1 downto 0);
|
228 |
|
|
signal IBE : std_logic_vector(4-1 downto 0);
|
229 |
|
|
signal IDATI : std_logic_vector(ILEN-1 downto 0);
|
230 |
|
|
signal DWE0 : std_logic;
|
231 |
|
|
signal DBE : std_logic_vector(4-1 downto 0);
|
232 |
|
|
signal DRE : std_logic_vector(2-1 downto 0);
|
233 |
|
|
signal DADR0 : unsigned(ALEN-1 downto 0);
|
234 |
|
|
signal DADR1 : unsigned(ALEN-1 downto 0);
|
235 |
|
|
signal DIADR0 : unsigned(ALEN-1 downto 0);
|
236 |
|
|
signal DIADR1 : unsigned(ALEN-1 downto 0);
|
237 |
|
|
signal DIMS,DIMS_q : std_logic_vector(2-1 downto 0);
|
238 |
|
|
signal DDATO : std_logic_vector(SDLEN-1 downto 0);
|
239 |
|
|
|
240 |
|
|
signal IWE0_RAM : std_logic;
|
241 |
|
|
signal IADR0_RAM : unsigned(log2(IMEM_SIZE)-1 downto 0);
|
242 |
|
|
signal IADR1_RAM : unsigned(log2(IMEM_SIZE)-1 downto 0);
|
243 |
|
|
signal IADR0_RAM_PX : unsigned(log2(IMEM_SIZE)-2 downto 0);
|
244 |
|
|
signal IADR1_RAM_PX : unsigned(log2(IMEM_SIZE)-2 downto 0);
|
245 |
|
|
signal IBE0_RAM : std_logic_vector(8-1 downto 0);
|
246 |
|
|
signal IDATI_RAM : std_logic_vector(ILEN*2-1 downto 0);
|
247 |
|
|
signal DWE0_RAM : std_logic;
|
248 |
|
|
signal DADR0_RAM : unsigned(log2(DMEM_SIZE)-1 downto 0);
|
249 |
|
|
signal DADR1_RAM : unsigned(log2(DMEM_SIZE)-1 downto 0);
|
250 |
|
|
signal DDATI0_RAM : std_logic_vector(SDLEN-1 downto 0);
|
251 |
|
|
signal DDATI1_RAM : std_logic_vector(SDLEN-1 downto 0);
|
252 |
|
|
signal DBE_RAM : std_logic_vector(4-1 downto 0);
|
253 |
|
|
|
254 |
|
|
signal IDI_RAM : std_logic_vector(ILEN*2-1 downto 0);
|
255 |
|
|
signal DDI_RAM : std_logic_vector(SDLEN-1 downto 0);
|
256 |
|
|
|
257 |
|
|
signal DP_ADR_MS : std_logic;
|
258 |
|
|
signal DP_ADR_MS_q : std_logic;
|
259 |
|
|
signal DP_IADR : unsigned(ALEN-1 downto 0);
|
260 |
|
|
signal DP_DADR : unsigned(ALEN-1 downto 0);
|
261 |
|
|
signal DP_IOADR_MS : std_logic;
|
262 |
|
|
signal DP_IOADR_MS_q : std_logic;
|
263 |
|
|
signal DP_IOADR : unsigned(ALEN-1 downto 0);
|
264 |
|
|
|
265 |
|
|
signal IADR_ERR,IADR_ERR_q : std_logic;
|
266 |
|
|
signal DADR0_ERR,DADR0_ERR_q : std_logic;
|
267 |
|
|
signal DADR1_ERR,DADR1_ERR_q : std_logic;
|
268 |
|
|
signal IDADR_CFLT : std_logic;
|
269 |
|
|
signal IADR0_RAM_WS,IADR0_RAM_WS_q : std_logic;
|
270 |
|
|
|
271 |
|
|
signal IOMS : std_logic_vector(2-1 downto 0);
|
272 |
|
|
signal IOMS_q : std_logic_vector(2-1 downto 0);
|
273 |
|
|
signal DADR_IO : unsigned(ALEN-1 downto 0);
|
274 |
|
|
signal DWE_IO : std_logic;
|
275 |
|
|
signal DDATI_IO : std_logic_vector(SDLEN-1 downto 0);
|
276 |
|
|
signal DDATO_IO : std_logic_vector(SDLEN-1 downto 0);
|
277 |
|
|
|
278 |
|
|
signal DADR_PLIC : std_logic_vector(PLIC_AWIDTH-1 downto 0);
|
279 |
|
|
signal DWE_PLIC : std_logic;
|
280 |
|
|
signal DDATI_PLIC : std_logic_vector(SDLEN-1 downto 0);
|
281 |
|
|
signal DDATO_PLIC : std_logic_vector(SDLEN-1 downto 0);
|
282 |
|
|
|
283 |
|
|
begin
|
284 |
|
|
|
285 |
|
|
---------------------------------------------------
|
286 |
|
|
-- CPU module
|
287 |
|
|
---------------------------------------------------
|
288 |
|
|
|
289 |
|
|
U_CPU : RV01_CPU_2W
|
290 |
|
|
generic map(
|
291 |
|
|
-- synthesis translate_off
|
292 |
|
|
ST_FILENAME => ST_FILE,
|
293 |
|
|
WB_FILENAME => WB_FILE,
|
294 |
|
|
-- synthesis translate_on
|
295 |
|
|
IMEM_SIZE => IMEM_SIZE,
|
296 |
|
|
DMEM_SIZE => DMEM_SIZE,
|
297 |
|
|
IMEM_LOWM => IMEM_LOWM,
|
298 |
|
|
BHT_SIZE => BHT_SIZE,
|
299 |
|
|
CFG_FLAGS => CFG_FLAGS,
|
300 |
|
|
SIMULATION_ONLY => SIMULATION_ONLY
|
301 |
|
|
)
|
302 |
|
|
port map(
|
303 |
|
|
CLK_i => CLK_i,
|
304 |
|
|
RST_i => RST_i,
|
305 |
|
|
INSTR_i => INSTR,
|
306 |
|
|
DDAT0_i => DDATI0,
|
307 |
|
|
DDAT1_i => DDATI1,
|
308 |
|
|
IADR_ERR_i => IADR_ERR_q,
|
309 |
|
|
DADR0_ERR_i => DADR0_ERR_q,
|
310 |
|
|
DADR1_ERR_i => DADR1_ERR_q,
|
311 |
|
|
IDADR_CFLT_i => IDADR_CFLT,
|
312 |
|
|
--
|
313 |
|
|
CHK_ENB_i => CHK_ENB_i,
|
314 |
|
|
--
|
315 |
|
|
EXT_INT_i => EXT_INT,
|
316 |
|
|
--
|
317 |
|
|
MFROMHOST_WE_i => MFROMHOST_WE_i,
|
318 |
|
|
MFROMHOST_i => MFROMHOST_i,
|
319 |
|
|
--
|
320 |
|
|
CP_RE_i => CP_RE_i,
|
321 |
|
|
CP_WE_i => CP_WE_i,
|
322 |
|
|
CP_ADR_i => CP_ADR_i,
|
323 |
|
|
CP_D_i => CP_DAT_i,
|
324 |
|
|
|
325 |
|
|
HALT_o => HALT,
|
326 |
|
|
-- IRE_o => IRE, -- to be added!
|
327 |
|
|
IADR_o => IADR1,
|
328 |
|
|
DRE_o => DRE,
|
329 |
|
|
DBE_o => DBE,
|
330 |
|
|
DWE0_o => DWE0,
|
331 |
|
|
DADR0_o => DADR0,
|
332 |
|
|
DADR1_o => DADR1,
|
333 |
|
|
DIADR0_o => DIADR0,
|
334 |
|
|
DIADR1_o => DIADR1,
|
335 |
|
|
DIMS_o => DIMS,
|
336 |
|
|
DDAT0_o => DDATO,
|
337 |
|
|
--
|
338 |
|
|
MTOHOST_OE_o => MTOHOST_OE_o,
|
339 |
|
|
MTOHOST_o => MTOHOST_o,
|
340 |
|
|
--
|
341 |
|
|
CP_Q_o => CP_DAT_o
|
342 |
|
|
);
|
343 |
|
|
|
344 |
|
|
---------------------------------------------------
|
345 |
|
|
-- Address space
|
346 |
|
|
---------------------------------------------------
|
347 |
|
|
|
348 |
|
|
-- if IMEM_LOWM = '1', instruction memory is located
|
349 |
|
|
-- on lower portion of address space (starting from
|
350 |
|
|
-- address zero), with data memory located above it
|
351 |
|
|
-- (starting from address IMEM_SIZE).
|
352 |
|
|
-- if IMEM_LOWM = '0', data memory is located
|
353 |
|
|
-- on lower portion of address space (starting from
|
354 |
|
|
-- address zero), with instruction memory located
|
355 |
|
|
-- above it (starting from address DMEM_SIZE).
|
356 |
|
|
-- I/O memory (when present) is treated as another
|
357 |
|
|
-- type of data memory and is always located after
|
358 |
|
|
-- instr. and data memory.
|
359 |
|
|
-- From the exception processing point of view, I/O
|
360 |
|
|
-- memory is treated a data one.
|
361 |
|
|
-- I/O memory differs from instr. and data memories
|
362 |
|
|
-- because:
|
363 |
|
|
-- 1) it doesn't support concurrent access from CPU,
|
364 |
|
|
-- and byte-write.
|
365 |
|
|
-- 2) no check is performed that actual storage is
|
366 |
|
|
-- available for a given address (e.g. reads from
|
367 |
|
|
-- un-mapped addresses return garbage, without
|
368 |
|
|
-- triggering any exception).
|
369 |
|
|
|
370 |
|
|
---------------------------------------------------
|
371 |
|
|
-- Instruction/Data Memory Selection flags
|
372 |
|
|
---------------------------------------------------
|
373 |
|
|
|
374 |
|
|
-- Instructions/data memory selection flags tell which
|
375 |
|
|
-- type of RAM (instruction vs. data) is the target of
|
376 |
|
|
-- a load/store instruction or a DP operation.
|
377 |
|
|
-- For load/store instructions these flags are provided
|
378 |
|
|
-- by CPU using DIMS_o output) while for DP operations
|
379 |
|
|
-- selection flag is generated here.
|
380 |
|
|
|
381 |
|
|
-- DP_ADR_MS selects between instruction and data memories.
|
382 |
|
|
-- if DP_ADR_MS = '0', address belong to instr. memory,
|
383 |
|
|
-- if DP_ADR_MS = '1', address belong to data memory.
|
384 |
|
|
-- DP_IOADR_MS selects between I/O and data memory.
|
385 |
|
|
-- if DP_IOADR_MS = '1', address belong to I/O memory,
|
386 |
|
|
-- if DP_IOADR_MS = '0', address belong to true data memory.
|
387 |
|
|
|
388 |
|
|
-- DP_ADR_MS | DP_IOADR_MS | mem. type
|
389 |
|
|
--------------------------------------
|
390 |
|
|
-- 0 | x | instr. memory
|
391 |
|
|
-- 1 | 0 | "true" data memory
|
392 |
|
|
-- 1 | 1 | I/O data memory
|
393 |
|
|
|
394 |
|
|
GL1: if IMEM_LOWM = '1' generate
|
395 |
|
|
-- instr. memory is located on lower portion of address space,
|
396 |
|
|
-- I/O memory (if present) is located after data memory.
|
397 |
|
|
DP_ADR_MS <= '0' when (to_unsigned(DP_ADR_i)/4 < IMEM_SIZE) else '1';
|
398 |
|
|
DP_IADR <= to_unsigned(DP_ADR_i);
|
399 |
|
|
DP_DADR <= to_unsigned(DP_ADR_i) - IMEM_SIZE*4;
|
400 |
|
|
DP_IOADR_MS <= '0' when (to_unsigned(DP_ADR_i)/4 < IMEM_SIZE+DMEM_SIZE) else '1';
|
401 |
|
|
--DP_IOADR <= to_unsigned(DP_ADR_i) - (IMEM_SIZE*4 - DMEM_SIZE*4);
|
402 |
|
|
end generate;
|
403 |
|
|
|
404 |
|
|
GL0: if IMEM_LOWM = '0' generate
|
405 |
|
|
-- instr. memory is located on upper portion of address space,
|
406 |
|
|
-- I/O memory (if present) is located after instr. memory.
|
407 |
|
|
DP_ADR_MS <= '0' when (to_unsigned(DP_ADR_i)/4 > DMEM_SIZE) else '1';
|
408 |
|
|
DP_IADR <= to_unsigned(DP_ADR_i) - DMEM_SIZE*4;
|
409 |
|
|
DP_DADR <= to_unsigned(DP_ADR_i);
|
410 |
|
|
DP_IOADR_MS <= '0' when (to_unsigned(DP_ADR_i)/4 < IMEM_SIZE+DMEM_SIZE) else '1';
|
411 |
|
|
--DP_IOADR <= to_unsigned(DP_ADR_i) - (IMEM_SIZE*4 - DMEM_SIZE*4);
|
412 |
|
|
end generate;
|
413 |
|
|
|
414 |
|
|
-- Note: DADR0 and DADR1 are data memory addresses, so there's no need to
|
415 |
|
|
-- subtract IMEM_SIZE from them!
|
416 |
|
|
|
417 |
|
|
-- I/O memory selection flags
|
418 |
|
|
|
419 |
|
|
GIOM0_GT0: if(IOMEM_SIZE > 0) generate
|
420 |
|
|
IOMS(0) <= '1' when (DADR0(ALEN-1 downto 2) >= DMEM_SIZE) else '0';
|
421 |
|
|
IOMS(1) <= '1' when (DADR1(ALEN-1 downto 2) >= DMEM_SIZE) else '0';
|
422 |
|
|
end generate;
|
423 |
|
|
|
424 |
|
|
GIOM0_EQ0: if(IOMEM_SIZE = 0) generate
|
425 |
|
|
IOMS(0) <= '0';
|
426 |
|
|
IOMS(1) <= '0';
|
427 |
|
|
end generate;
|
428 |
|
|
|
429 |
|
|
-- Memory Selection flag registers: these registers are
|
430 |
|
|
-- needed to mux instruction and data RAM's output during
|
431 |
|
|
-- load or DP read operations (because of synchronous
|
432 |
|
|
-- behavior of RAM's, output data is available with a
|
433 |
|
|
-- delay of one cycle, requiring a similarly delayed
|
434 |
|
|
-- version of selection flags).
|
435 |
|
|
|
436 |
|
|
process(CLK_i)
|
437 |
|
|
begin
|
438 |
|
|
if(CLK_i = '1' and CLK_i'event) then
|
439 |
|
|
DP_ADR_MS_q <= DP_ADR_MS;
|
440 |
|
|
DP_IOADR_MS_q <= DP_IOADR_MS;
|
441 |
|
|
DIMS_q <= DIMS;
|
442 |
|
|
IOMS_q <= IOMS;
|
443 |
|
|
end if;
|
444 |
|
|
end process;
|
445 |
|
|
|
446 |
|
|
---------------------------------------------------
|
447 |
|
|
-- Address error and conflict flags
|
448 |
|
|
---------------------------------------------------
|
449 |
|
|
|
450 |
|
|
-- An instruction address triggers an error if it
|
451 |
|
|
-- simply falls outside of the instruction address space
|
452 |
|
|
-- given by [0:IMEM_SIZE*4-4)
|
453 |
|
|
|
454 |
|
|
-- A load/store address triggers an error if:
|
455 |
|
|
-- 1) it targets instruction RAM (DIMS* = '1') and it
|
456 |
|
|
-- falls outside of the instruction address space
|
457 |
|
|
-- given by [0:IMEM_SIZE*4-4), OR
|
458 |
|
|
-- 2) it targets data RAM (DIMS* = '0') and it falls
|
459 |
|
|
-- outside of the data address space given by
|
460 |
|
|
-- [0:(DMEM_SIZE+IOMEM_SIZE)*4-4).
|
461 |
|
|
|
462 |
|
|
-- This flag gets asserted if data port #0 address is
|
463 |
|
|
-- outside of address space.
|
464 |
|
|
|
465 |
|
|
DADR0_ERR <= '1' when (
|
466 |
|
|
(DIMS(0) = '0' and DIADR0(ALEN-1 downto 2) >= IMEM_SIZE) or
|
467 |
|
|
(DIMS(0) = '1' and DADR0(ALEN-1 downto 2) >= DMEM_SIZE + IOMEM_SIZE)
|
468 |
|
|
) else '0';
|
469 |
|
|
|
470 |
|
|
-- This flag gets asserted if data port #1 address is
|
471 |
|
|
-- outside of address space.
|
472 |
|
|
|
473 |
|
|
DADR1_ERR <= '1' when (
|
474 |
|
|
(DIMS(1) = '0' and DIADR1(ALEN-1 downto 2) >= IMEM_SIZE) or
|
475 |
|
|
(DIMS(1) = '1' and DADR1(ALEN-1 downto 2) >= DMEM_SIZE + IOMEM_SIZE)
|
476 |
|
|
) else '0';
|
477 |
|
|
|
478 |
|
|
-- This flag gets asserted if instruction port address
|
479 |
|
|
-- is outside of address space.
|
480 |
|
|
|
481 |
|
|
IADR_ERR <= '1' when (
|
482 |
|
|
IADR1(ALEN-3 downto 3) >= IMEM_SIZE/2
|
483 |
|
|
) else '0';
|
484 |
|
|
|
485 |
|
|
-- Error flag pipe registers (added to relax
|
486 |
|
|
-- timing constraints).
|
487 |
|
|
|
488 |
|
|
process(CLK_i)
|
489 |
|
|
begin
|
490 |
|
|
if(CLK_i = '1' and CLK_i'event) then
|
491 |
|
|
if(RST_i = '1') then
|
492 |
|
|
IADR_ERR_q <= '0';
|
493 |
|
|
DADR0_ERR_q <= '0';
|
494 |
|
|
DADR1_ERR_q <= '0';
|
495 |
|
|
else
|
496 |
|
|
IADR_ERR_q <= IADR_ERR;
|
497 |
|
|
DADR0_ERR_q <= DADR0_ERR;
|
498 |
|
|
DADR1_ERR_q <= DADR1_ERR;
|
499 |
|
|
end if;
|
500 |
|
|
end if;
|
501 |
|
|
end process;
|
502 |
|
|
|
503 |
|
|
-- This flag gets asserted if a concurrent access from
|
504 |
|
|
-- data ports is attemped on instruction sub-space or
|
505 |
|
|
-- on I/O sub-space.
|
506 |
|
|
|
507 |
|
|
IDADR_CFLT <= '1' when (
|
508 |
|
|
(
|
509 |
|
|
(DIMS(0) = '0' and DRE(0) = '1') and
|
510 |
|
|
(DIMS(1) = '0' and DRE(1) = '1')
|
511 |
|
|
) or (
|
512 |
|
|
(DIMS(0) = '0' and DWE0 = '1') and
|
513 |
|
|
(DIMS(1) = '0' and DRE(1) = '1')
|
514 |
|
|
) or (
|
515 |
|
|
(IOMS(0) = '1' and DRE(0) = '1') and
|
516 |
|
|
(IOMS(1) = '1' and DRE(1) = '1')
|
517 |
|
|
) or (
|
518 |
|
|
(IOMS(0) = '1' and DWE0 = '1') and
|
519 |
|
|
(IOMS(1) = '1' and DRE(1) = '1')
|
520 |
|
|
)
|
521 |
|
|
) else '0';
|
522 |
|
|
|
523 |
|
|
---------------------------------------------------
|
524 |
|
|
-- Instruction RAM
|
525 |
|
|
---------------------------------------------------
|
526 |
|
|
|
527 |
|
|
-- Instruction RAM is dual-port RAM with 1 read/write
|
528 |
|
|
-- port and 1 read-only port.
|
529 |
|
|
-- Read-only port id used for instructions fecthing,
|
530 |
|
|
-- read/write port is used to access memory through
|
531 |
|
|
-- load/store operations.
|
532 |
|
|
|
533 |
|
|
GPX0_1 : if(PARALLEL_EXECUTION_ENABLED = '1') generate
|
534 |
|
|
|
535 |
|
|
-- Instruction RAM word width is twice data RAM one
|
536 |
|
|
-- because instructions RAM must provides two
|
537 |
|
|
-- adjacent instructions per cycle.
|
538 |
|
|
|
539 |
|
|
U_RAMI : RV01_RAM_1RW1R_BE
|
540 |
|
|
generic map(
|
541 |
|
|
DWIDTH => ILEN*2,
|
542 |
|
|
WCOUNT => IMEM_SIZE/2
|
543 |
|
|
)
|
544 |
|
|
port map(
|
545 |
|
|
CLK_i => CLK_i,
|
546 |
|
|
A_i => IADR0_RAM_PX(log2(IMEM_SIZE)-2 downto 0),
|
547 |
|
|
DPRA_i => IADR1_RAM_PX(log2(IMEM_SIZE)-2 downto 0),
|
548 |
|
|
D_i => IDI_RAM,
|
549 |
|
|
WE_i => IWE0_RAM,
|
550 |
|
|
BE_i => IBE0_RAM,
|
551 |
|
|
|
552 |
|
|
Q_o => IDATI_RAM,
|
553 |
|
|
DPQ_o => INSTR
|
554 |
|
|
);
|
555 |
|
|
|
556 |
|
|
end generate; -- GPX0_1
|
557 |
|
|
|
558 |
|
|
GPX0_0 : if(PARALLEL_EXECUTION_ENABLED = '0') generate
|
559 |
|
|
|
560 |
|
|
-- Instruction RAM word width equals data RAM one
|
561 |
|
|
-- because instructions RAM must provides one
|
562 |
|
|
-- instruction per cycle.
|
563 |
|
|
|
564 |
|
|
U_RAMI : RV01_RAM_1RW1R_BE
|
565 |
|
|
generic map(
|
566 |
|
|
DWIDTH => ILEN,
|
567 |
|
|
WCOUNT => IMEM_SIZE
|
568 |
|
|
)
|
569 |
|
|
port map(
|
570 |
|
|
CLK_i => CLK_i,
|
571 |
|
|
A_i => IADR0_RAM,
|
572 |
|
|
DPRA_i => IADR1_RAM,
|
573 |
|
|
D_i => IDI_RAM(ILEN-1 downto 0),
|
574 |
|
|
WE_i => IWE0_RAM,
|
575 |
|
|
BE_i => IBE0_RAM(4-1 downto 0),
|
576 |
|
|
|
577 |
|
|
Q_o => IDATI_RAM(ILEN-1 downto 0),
|
578 |
|
|
DPQ_o => INSTR(ILEN-1 downto 0)
|
579 |
|
|
);
|
580 |
|
|
|
581 |
|
|
IDATI_RAM(ILEN*2-1 downto ILEN) <= (others => '0');
|
582 |
|
|
INSTR(ILEN*2-1 downto ILEN) <= (others => '0');
|
583 |
|
|
|
584 |
|
|
end generate; -- GPX0_0
|
585 |
|
|
|
586 |
|
|
---------------------------------------------------
|
587 |
|
|
-- Instruction memory signals
|
588 |
|
|
---------------------------------------------------
|
589 |
|
|
|
590 |
|
|
-- inst. RAM read/write port address
|
591 |
|
|
|
592 |
|
|
GPX5_1 : if(PARALLEL_EXECUTION_ENABLED = '1') generate
|
593 |
|
|
|
594 |
|
|
-- Inst. RAM read/write address has three possible
|
595 |
|
|
-- sources:
|
596 |
|
|
-- 1) DP port address
|
597 |
|
|
-- 2) data port #0 address
|
598 |
|
|
-- 3) data port #1 address
|
599 |
|
|
|
600 |
|
|
GPO_1 : if(IMEM_SIZE_PO2 = '1') generate
|
601 |
|
|
|
602 |
|
|
-- Inst. memory size is a power-of-2: address is generated
|
603 |
|
|
-- as a simple subset of DIADR0, DIADR0 or DP_IADR.
|
604 |
|
|
|
605 |
|
|
process(DIMS(0),DIMS(1),DRE,DWE0,HALT,DIADR0,DIADR1,DP_IADR,DBE)
|
606 |
|
|
begin
|
607 |
|
|
if(HALT = '0') then
|
608 |
|
|
-- cpu data memory ports address
|
609 |
|
|
if(DIMS(0) = '0' and (DRE(0) = '1' or DWE0 = '1')) then
|
610 |
|
|
-- port #0 address
|
611 |
|
|
IADR0_RAM_PX <= DIADR0(L2IMEM_SIZE+2-1 downto 3);
|
612 |
|
|
IADR0_RAM_WS <= DIADR0(2);
|
613 |
|
|
else
|
614 |
|
|
-- port #1 address
|
615 |
|
|
IADR0_RAM_PX <= DIADR1(L2IMEM_SIZE+2-1 downto 3);
|
616 |
|
|
IADR0_RAM_WS <= DIADR1(2);
|
617 |
|
|
end if;
|
618 |
|
|
IBE <= DBE;
|
619 |
|
|
else
|
620 |
|
|
-- DP port address
|
621 |
|
|
IADR0_RAM_PX <= DP_IADR(L2IMEM_SIZE+2-1 downto 3);
|
622 |
|
|
IADR0_RAM_WS <= DP_IADR(2);
|
623 |
|
|
IBE <= (others => '1');
|
624 |
|
|
end if;
|
625 |
|
|
end process;
|
626 |
|
|
|
627 |
|
|
end generate; -- GPO_1
|
628 |
|
|
|
629 |
|
|
GPO_0 : if(IMEM_SIZE_PO2 = '0') generate
|
630 |
|
|
|
631 |
|
|
-- Inst. memory size is NOT a power-of-2: address is generated
|
632 |
|
|
-- as a subset of DIADR0, DIADR0 or DP_IADR, except when it exceeds
|
633 |
|
|
-- memory size (when this occur, address is forced to all-0).
|
634 |
|
|
|
635 |
|
|
process(DIMS(0),DIMS(1),DRE,DWE0,HALT,DIADR0,DIADR1,DP_IADR,DBE)
|
636 |
|
|
begin
|
637 |
|
|
if(HALT = '0') then
|
638 |
|
|
-- cpu data memory ports address
|
639 |
|
|
if(DIMS(0) = '0' and (DRE(0) = '1' or DWE0 = '1')) then
|
640 |
|
|
-- port #0 address
|
641 |
|
|
if(DIADR0(L2IMEM_SIZE+2-1 downto 3) < IMEM_SIZE/2) then
|
642 |
|
|
IADR0_RAM_PX <= DIADR0(L2IMEM_SIZE+2-1 downto 3);
|
643 |
|
|
else
|
644 |
|
|
IADR0_RAM_PX <= (others => '0');
|
645 |
|
|
end if;
|
646 |
|
|
IADR0_RAM_WS <= DIADR0(2);
|
647 |
|
|
else
|
648 |
|
|
-- port #1 address
|
649 |
|
|
if(DIADR1(L2IMEM_SIZE+2-1 downto 3) < IMEM_SIZE/2) then
|
650 |
|
|
IADR0_RAM_PX <= DIADR1(L2IMEM_SIZE+2-1 downto 3);
|
651 |
|
|
else
|
652 |
|
|
IADR0_RAM_PX <= (others => '0');
|
653 |
|
|
end if;
|
654 |
|
|
IADR0_RAM_WS <= DIADR1(2);
|
655 |
|
|
end if;
|
656 |
|
|
IBE <= DBE;
|
657 |
|
|
else
|
658 |
|
|
-- DP port address
|
659 |
|
|
if(DP_IADR(L2IMEM_SIZE+2-1 downto 3) < IMEM_SIZE/2) then
|
660 |
|
|
IADR0_RAM_PX <= DP_IADR(L2IMEM_SIZE+2-1 downto 3);
|
661 |
|
|
else
|
662 |
|
|
IADR0_RAM_PX <= (others => '0');
|
663 |
|
|
end if;
|
664 |
|
|
IADR0_RAM_WS <= DP_IADR(2);
|
665 |
|
|
IBE <= (others => '1');
|
666 |
|
|
end if;
|
667 |
|
|
end process;
|
668 |
|
|
|
669 |
|
|
end generate; -- GPO_0
|
670 |
|
|
|
671 |
|
|
end generate; -- GPX5_1
|
672 |
|
|
|
673 |
|
|
GPX5_0 : if(PARALLEL_EXECUTION_ENABLED = '0') generate
|
674 |
|
|
|
675 |
|
|
-- Inst. RAM read/write address has two possible
|
676 |
|
|
-- sources:
|
677 |
|
|
-- 1) DP port address
|
678 |
|
|
-- 2) data port #0 address
|
679 |
|
|
|
680 |
|
|
GPO_1 : if(IMEM_SIZE_PO2 = '1') generate
|
681 |
|
|
|
682 |
|
|
-- Inst. memory size is a power-of-2: address is generated
|
683 |
|
|
-- as a simple subset of DIADR0, DIADR0 or DP_IADR.
|
684 |
|
|
|
685 |
|
|
process(DIMS(0),DIMS(1),DRE,DWE0,HALT,DIADR0,DIADR1,DP_IADR,DBE)
|
686 |
|
|
begin
|
687 |
|
|
if(HALT = '0') then
|
688 |
|
|
-- cpu data memory ports address
|
689 |
|
|
if(DIMS(0) = '0' and (DRE(0) = '1' or DWE0 = '1')) then
|
690 |
|
|
-- port #0 address
|
691 |
|
|
IADR0_RAM <= DIADR0(L2IMEM_SIZE+2-1 downto 2);
|
692 |
|
|
else
|
693 |
|
|
-- port #1 address
|
694 |
|
|
IADR0_RAM <= DIADR1(L2IMEM_SIZE+2-1 downto 2);
|
695 |
|
|
end if;
|
696 |
|
|
IBE <= DBE;
|
697 |
|
|
else
|
698 |
|
|
-- DP port address
|
699 |
|
|
IADR0_RAM <= DP_IADR(L2IMEM_SIZE+2-1 downto 2);
|
700 |
|
|
IBE <= (others => '1');
|
701 |
|
|
end if;
|
702 |
|
|
IADR0_RAM_WS <= '0';
|
703 |
|
|
end process;
|
704 |
|
|
|
705 |
|
|
end generate; -- GPO_1
|
706 |
|
|
|
707 |
|
|
GPO_0 : if(IMEM_SIZE_PO2 = '0') generate
|
708 |
|
|
|
709 |
|
|
-- Inst. memory size is NOT a power-of-2: address is generated
|
710 |
|
|
-- as a subset of DIADR0, DIADR0 or DP_IADR, except when it exceeds
|
711 |
|
|
-- memory size (when this occur, address is forced to all-0).
|
712 |
|
|
|
713 |
|
|
process(DIMS(0),DIMS(1),DRE,DWE0,HALT,DIADR0,DIADR1,DP_IADR,DBE)
|
714 |
|
|
begin
|
715 |
|
|
if(HALT = '0') then
|
716 |
|
|
-- cpu data memory ports address
|
717 |
|
|
if(DIMS(0) = '0' and (DRE(0) = '1' or DWE0 = '1')) then
|
718 |
|
|
-- port #0 address
|
719 |
|
|
if(DIADR0(L2IMEM_SIZE+2-1 downto 2) < IMEM_SIZE) then
|
720 |
|
|
IADR0_RAM <= DIADR0(L2IMEM_SIZE+2-1 downto 2);
|
721 |
|
|
else
|
722 |
|
|
IADR0_RAM <= (others => '0');
|
723 |
|
|
end if;
|
724 |
|
|
else
|
725 |
|
|
-- port #1 address
|
726 |
|
|
if(DIADR1(L2IMEM_SIZE+2-1 downto 2) < IMEM_SIZE) then
|
727 |
|
|
IADR0_RAM <= DIADR1(L2IMEM_SIZE+2-1 downto 2);
|
728 |
|
|
else
|
729 |
|
|
IADR0_RAM <= (others => '0');
|
730 |
|
|
end if;
|
731 |
|
|
end if;
|
732 |
|
|
IBE <= DBE;
|
733 |
|
|
else
|
734 |
|
|
-- DP port address
|
735 |
|
|
if(DP_IADR(L2IMEM_SIZE+2-1 downto 2) < IMEM_SIZE) then
|
736 |
|
|
IADR0_RAM <= DP_IADR(L2IMEM_SIZE+2-1 downto 2);
|
737 |
|
|
else
|
738 |
|
|
IADR0_RAM <= (others => '0');
|
739 |
|
|
end if;
|
740 |
|
|
IBE <= (others => '1');
|
741 |
|
|
end if;
|
742 |
|
|
IADR0_RAM_WS <= '0';
|
743 |
|
|
end process;
|
744 |
|
|
|
745 |
|
|
end generate; -- GPO_0
|
746 |
|
|
|
747 |
|
|
end generate; -- GPX5_0
|
748 |
|
|
|
749 |
|
|
-- Inst. RAM read/write port WE has two possible
|
750 |
|
|
-- sources:
|
751 |
|
|
-- 1) DP port WE
|
752 |
|
|
-- 2) data port #0 WE
|
753 |
|
|
|
754 |
|
|
-- inst. RAM read/write port write-enable
|
755 |
|
|
IWE0_RAM <= (DWE0 and not DIMS(0)) when (HALT = '0') else
|
756 |
|
|
(DP_WE_i and not DP_ADR_MS);
|
757 |
|
|
|
758 |
|
|
-- DP port and data port #0 provide only SDLEN bit
|
759 |
|
|
-- of data, which are mapped both the lower and upper
|
760 |
|
|
-- halves of instruction RAM data word, the selection
|
761 |
|
|
-- of the half to be actually written to memory being
|
762 |
|
|
-- performed through byte-enable signals.
|
763 |
|
|
|
764 |
|
|
-- inst. RAM data-in
|
765 |
|
|
IDI_RAM(ILEN-1 downto 0) <= DDATO when (HALT = '0') else DP_DAT_i;
|
766 |
|
|
|
767 |
|
|
GPX1_1 : if(PARALLEL_EXECUTION_ENABLED = '1') generate
|
768 |
|
|
IDI_RAM(ILEN*2-1 downto ILEN) <= DDATO when (HALT = '0') else DP_DAT_i;
|
769 |
|
|
end generate; -- GPX1_1
|
770 |
|
|
|
771 |
|
|
GPX1_0 : if(PARALLEL_EXECUTION_ENABLED = '0') generate
|
772 |
|
|
IDI_RAM(ILEN*2-1 downto ILEN) <= (others => '0');
|
773 |
|
|
end generate; -- GPX1_0
|
774 |
|
|
|
775 |
|
|
-- Inst. RAM byte-enable signals, in every cycle only
|
776 |
|
|
-- the lower 4 bits or the upper 4 bits can be non-zero.
|
777 |
|
|
-- Mapping of DP port or data port DBE signals on
|
778 |
|
|
-- lower/upper 4 bits being controlled by DP or data
|
779 |
|
|
-- port address LSb.
|
780 |
|
|
|
781 |
|
|
GPX2_1 : if(PARALLEL_EXECUTION_ENABLED = '1') generate
|
782 |
|
|
|
783 |
|
|
IBE0_RAM(4-1 downto 0) <=
|
784 |
|
|
IBE when (IADR0_RAM_WS = '0') else (others => '0');
|
785 |
|
|
|
786 |
|
|
IBE0_RAM(8-1 downto 4) <=
|
787 |
|
|
IBE when (IADR0_RAM_WS = '1') else (others => '0');
|
788 |
|
|
|
789 |
|
|
end generate; -- GPX2_1
|
790 |
|
|
|
791 |
|
|
GPX2_0 : if(PARALLEL_EXECUTION_ENABLED = '0') generate
|
792 |
|
|
|
793 |
|
|
IBE0_RAM(4-1 downto 0) <= IBE;
|
794 |
|
|
|
795 |
|
|
IBE0_RAM(8-1 downto 4) <= (others => '0');
|
796 |
|
|
|
797 |
|
|
end generate; -- GPX2_0
|
798 |
|
|
|
799 |
|
|
GPX3_1 : if(PARALLEL_EXECUTION_ENABLED = '1') generate
|
800 |
|
|
|
801 |
|
|
-- Inst. RAM read-only address (2-word address)
|
802 |
|
|
IADR1_RAM_PX <= IADR1(L2IMEM_SIZE+2-1 downto 3);
|
803 |
|
|
|
804 |
|
|
end generate; -- GPX3_1
|
805 |
|
|
|
806 |
|
|
GPX3_0 : if(PARALLEL_EXECUTION_ENABLED = '0') generate
|
807 |
|
|
|
808 |
|
|
-- Inst. RAM read-only address (1-word address)
|
809 |
|
|
IADR1_RAM <= IADR1(L2IMEM_SIZE+2-1 downto 2);
|
810 |
|
|
|
811 |
|
|
end generate; -- GPX3_0
|
812 |
|
|
|
813 |
|
|
-- Data-out word selector must be latched to account for
|
814 |
|
|
-- RAM sync. behavior.
|
815 |
|
|
|
816 |
|
|
process(CLK_i)
|
817 |
|
|
begin
|
818 |
|
|
if(CLK_i = '1' and CLK_i'event) then
|
819 |
|
|
IADR0_RAM_WS_q <= IADR0_RAM_WS;
|
820 |
|
|
end if;
|
821 |
|
|
end process;
|
822 |
|
|
|
823 |
|
|
GPX4_1 : if(PARALLEL_EXECUTION_ENABLED = '1') generate
|
824 |
|
|
|
825 |
|
|
-- Select word of instruction memory data-out (2 words)
|
826 |
|
|
-- to be sent to CPU.
|
827 |
|
|
|
828 |
|
|
IDATI <= IDATI_RAM(ILEN*2-1 downto ILEN) when IADR0_RAM_WS_q = '1'
|
829 |
|
|
else IDATI_RAM(ILEN-1 downto 0);
|
830 |
|
|
|
831 |
|
|
end generate; -- GPX4_1
|
832 |
|
|
|
833 |
|
|
GPX4_0 : if(PARALLEL_EXECUTION_ENABLED = '0') generate
|
834 |
|
|
|
835 |
|
|
IDATI <= IDATI_RAM(ILEN-1 downto 0);
|
836 |
|
|
|
837 |
|
|
end generate; -- GPX4_0
|
838 |
|
|
|
839 |
|
|
---------------------------------------------------
|
840 |
|
|
-- Data memory signals
|
841 |
|
|
---------------------------------------------------
|
842 |
|
|
|
843 |
|
|
-- Data RAM port #0 is used for DP and therfore the related
|
844 |
|
|
-- address, data-in and write-enable signals are driven by
|
845 |
|
|
-- DP port when DMA-enable signals HALT is asserted.
|
846 |
|
|
|
847 |
|
|
-- Data RAM port #0 is a read-only port and thus doesn't have
|
848 |
|
|
-- associated data-in and write-enable signals.
|
849 |
|
|
|
850 |
|
|
-- Note: DADR0/1 are byte addresses, while data RAM is accessed
|
851 |
|
|
-- using word addresses, therefore DADR0/1 LS 2 bits must be
|
852 |
|
|
-- discarded.
|
853 |
|
|
|
854 |
|
|
GPO2_1: if(DMEM_SIZE_PO2 = '1') generate
|
855 |
|
|
|
856 |
|
|
-- Data memory size is a power-of-2: address is generated
|
857 |
|
|
-- as a simple subset of DADR0 or DP_ADR.
|
858 |
|
|
|
859 |
|
|
DADR0_RAM <= DADR0(L2DMEM_SIZE+2-1 downto 2) when (HALT = '0') else
|
860 |
|
|
DP_DADR(L2DMEM_SIZE+2-1 downto 2);
|
861 |
|
|
|
862 |
|
|
GPX_1 : if(PARALLEL_EXECUTION_ENABLED = '1') generate
|
863 |
|
|
DADR1_RAM <= DADR1(L2DMEM_SIZE+2-1 downto 2);
|
864 |
|
|
end generate;
|
865 |
|
|
|
866 |
|
|
GPX_0 : if(PARALLEL_EXECUTION_ENABLED = '0') generate
|
867 |
|
|
DADR1_RAM <= (others => '0');
|
868 |
|
|
end generate;
|
869 |
|
|
|
870 |
|
|
end generate;
|
871 |
|
|
|
872 |
|
|
GPO2_0: if(DMEM_SIZE_PO2 = '0') generate
|
873 |
|
|
|
874 |
|
|
-- Data memory size is NOT a power-of-2: address is generated
|
875 |
|
|
-- as a subset of DADR0 or DP_ADR, except when it exceeds
|
876 |
|
|
-- memory size (when this occur, address is forced to all-0).
|
877 |
|
|
|
878 |
|
|
process(DADR0,DP_DADR,HALT)
|
879 |
|
|
begin
|
880 |
|
|
if(HALT = '0') then
|
881 |
|
|
if(DADR0((L2DMEM_SIZE+2)-1 downto 2) < DMEM_SIZE) then
|
882 |
|
|
DADR0_RAM <= DADR0((L2DMEM_SIZE+2)-1 downto 2);
|
883 |
|
|
else
|
884 |
|
|
DADR0_RAM <= (others => '0');
|
885 |
|
|
end if;
|
886 |
|
|
else
|
887 |
|
|
if(DP_DADR((L2DMEM_SIZE+2)-1 downto 2) < DMEM_SIZE) then
|
888 |
|
|
DADR0_RAM <= DP_DADR((L2DMEM_SIZE+2)-1 downto 2);
|
889 |
|
|
else
|
890 |
|
|
DADR0_RAM <= (others => '0');
|
891 |
|
|
end if;
|
892 |
|
|
end if;
|
893 |
|
|
end process;
|
894 |
|
|
|
895 |
|
|
GPX_1 : if(PARALLEL_EXECUTION_ENABLED = '1') generate
|
896 |
|
|
|
897 |
|
|
process(DADR1)
|
898 |
|
|
begin
|
899 |
|
|
if(DADR1((L2DMEM_SIZE+2)-1 downto 2) < DMEM_SIZE) then
|
900 |
|
|
DADR1_RAM <= DADR1((L2DMEM_SIZE+2)-1 downto 2);
|
901 |
|
|
else
|
902 |
|
|
DADR1_RAM <= (others => '0');
|
903 |
|
|
end if;
|
904 |
|
|
end process;
|
905 |
|
|
|
906 |
|
|
end generate;
|
907 |
|
|
|
908 |
|
|
GPX_0 : if(PARALLEL_EXECUTION_ENABLED = '0') generate
|
909 |
|
|
DADR1_RAM <= (others => '0');
|
910 |
|
|
end generate;
|
911 |
|
|
|
912 |
|
|
end generate;
|
913 |
|
|
|
914 |
|
|
-- data RAM write-enable
|
915 |
|
|
DWE0_RAM <= (DWE0 and DIMS(0) and not(IOMS(0))) when (HALT = '0') else
|
916 |
|
|
(DP_WE_i and DP_ADR_MS and not(DP_IOADR_MS));
|
917 |
|
|
|
918 |
|
|
-- data RAM data-in
|
919 |
|
|
DDI_RAM <= DDATO when HALT = '0' else DP_DAT_i;
|
920 |
|
|
|
921 |
|
|
-- CPU data-in (supplied either by instruction memory, data memory
|
922 |
|
|
-- or some I/O module)
|
923 |
|
|
|
924 |
|
|
DDATI0 <=
|
925 |
|
|
DDATI0_RAM when (DIMS_q(0) = '1' and IOMS_q(0) = '0') else
|
926 |
|
|
DDATO_PLIC when (DIMS_q(0) = '1' and IOMS_q(0) = '1') else
|
927 |
|
|
IDATI;
|
928 |
|
|
|
929 |
|
|
GPX6_1 : if(PARALLEL_EXECUTION_ENABLED = '1') generate
|
930 |
|
|
DDATI1 <=
|
931 |
|
|
DDATI1_RAM when (DIMS_q(1) = '1' and IOMS_q(1) = '0') else
|
932 |
|
|
DDATO_PLIC when (DIMS_q(1) = '1' and IOMS_q(1) = '1') else
|
933 |
|
|
IDATI;
|
934 |
|
|
end generate;
|
935 |
|
|
|
936 |
|
|
GPX6_0 : if(PARALLEL_EXECUTION_ENABLED = '0') generate
|
937 |
|
|
DDATI1 <= (others => '0');
|
938 |
|
|
end generate;
|
939 |
|
|
|
940 |
|
|
DBE_RAM <= DBE when (HALT = '0') else (others => '1');
|
941 |
|
|
|
942 |
|
|
---------------------------------------------------
|
943 |
|
|
-- Data RAM
|
944 |
|
|
---------------------------------------------------
|
945 |
|
|
|
946 |
|
|
GPX7_1 : if(PARALLEL_EXECUTION_ENABLED = '1') generate
|
947 |
|
|
|
948 |
|
|
-- data RAM is dual-port RAM with 1 read/write port and
|
949 |
|
|
-- 1 read-only port (two reads, or one read and one write
|
950 |
|
|
-- can be performed in parallel).
|
951 |
|
|
|
952 |
|
|
U_RAMD : RV01_RAM_1RW1R_BE
|
953 |
|
|
generic map(
|
954 |
|
|
DWIDTH => SDLEN,
|
955 |
|
|
WCOUNT => DMEM_SIZE
|
956 |
|
|
)
|
957 |
|
|
port map(
|
958 |
|
|
CLK_i => CLK_i,
|
959 |
|
|
A_i => DADR0_RAM,
|
960 |
|
|
DPRA_i => DADR1_RAM,
|
961 |
|
|
D_i => DDI_RAM,
|
962 |
|
|
WE_i => DWE0_RAM,
|
963 |
|
|
BE_i => DBE_RAM,
|
964 |
|
|
|
965 |
|
|
Q_o => DDATI0_RAM,
|
966 |
|
|
DPQ_o => DDATI1_RAM
|
967 |
|
|
);
|
968 |
|
|
|
969 |
|
|
end generate;
|
970 |
|
|
|
971 |
|
|
GPX7_0 : if(PARALLEL_EXECUTION_ENABLED = '0') generate
|
972 |
|
|
|
973 |
|
|
-- data RAM is single-port RAM with 1 read/write port.
|
974 |
|
|
|
975 |
|
|
U_RAMD : RV01_RAM_1RW_BE
|
976 |
|
|
generic map(
|
977 |
|
|
DWIDTH => SDLEN,
|
978 |
|
|
WCOUNT => DMEM_SIZE
|
979 |
|
|
)
|
980 |
|
|
port map(
|
981 |
|
|
CLK_i => CLK_i,
|
982 |
|
|
A_i => DADR0_RAM,
|
983 |
|
|
D_i => DDI_RAM,
|
984 |
|
|
WE_i => DWE0_RAM,
|
985 |
|
|
BE_i => DBE_RAM,
|
986 |
|
|
|
987 |
|
|
Q_o => DDATI0_RAM
|
988 |
|
|
);
|
989 |
|
|
|
990 |
|
|
DDATI1_RAM <= (others => '0');
|
991 |
|
|
|
992 |
|
|
end generate;
|
993 |
|
|
|
994 |
|
|
---------------------------------------------------
|
995 |
|
|
-- I/O memory signals
|
996 |
|
|
---------------------------------------------------
|
997 |
|
|
|
998 |
|
|
GPX8_1 : if(PARALLEL_EXECUTION_ENABLED = '1') generate
|
999 |
|
|
|
1000 |
|
|
process(IOMS,DRE,DWE0,HALT,DADR0,DADR1,DP_ADR_i)
|
1001 |
|
|
begin
|
1002 |
|
|
if(HALT = '0') then
|
1003 |
|
|
-- cpu data memory ports address
|
1004 |
|
|
if(IOMS(0) = '1' and (DRE(0) = '1' or DWE0 = '1')) then
|
1005 |
|
|
-- port #0 address
|
1006 |
|
|
DADR_IO <= DADR0;
|
1007 |
|
|
else
|
1008 |
|
|
-- port #1 address
|
1009 |
|
|
DADR_IO <= DADR1;
|
1010 |
|
|
end if;
|
1011 |
|
|
else
|
1012 |
|
|
-- DP port address
|
1013 |
|
|
DADR_IO <= to_unsigned(DP_ADR_i);
|
1014 |
|
|
end if;
|
1015 |
|
|
end process;
|
1016 |
|
|
|
1017 |
|
|
end generate;
|
1018 |
|
|
|
1019 |
|
|
GPX8_0 : if(PARALLEL_EXECUTION_ENABLED = '0') generate
|
1020 |
|
|
|
1021 |
|
|
process(IOMS,DRE,DWE0,HALT,DADR0,DP_ADR_i)
|
1022 |
|
|
begin
|
1023 |
|
|
if(HALT = '0') then
|
1024 |
|
|
-- port #0 address
|
1025 |
|
|
DADR_IO <= DADR0;
|
1026 |
|
|
else
|
1027 |
|
|
-- DP port address
|
1028 |
|
|
DADR_IO <= to_unsigned(DP_ADR_i);
|
1029 |
|
|
end if;
|
1030 |
|
|
end process;
|
1031 |
|
|
|
1032 |
|
|
end generate;
|
1033 |
|
|
|
1034 |
|
|
-- I/O memory write-enable
|
1035 |
|
|
DWE_IO <= (DWE0 and DIMS(0) and IOMS(0)) when (HALT = '0') else
|
1036 |
|
|
(DP_WE_i and DP_ADR_MS and DP_IOADR_MS);
|
1037 |
|
|
|
1038 |
|
|
-- I/O memory data-in
|
1039 |
|
|
DDATI_IO <= DDATO when HALT = '0' else DP_DAT_i;
|
1040 |
|
|
|
1041 |
|
|
---------------------------------------------------
|
1042 |
|
|
-- I/O modules
|
1043 |
|
|
---------------------------------------------------
|
1044 |
|
|
|
1045 |
|
|
GPLIC_1 : if(PLIC_PRESENT = '1') generate
|
1046 |
|
|
|
1047 |
|
|
-- PLIC Module
|
1048 |
|
|
|
1049 |
|
|
U_PLIC : RV01_PLIC
|
1050 |
|
|
generic map(
|
1051 |
|
|
SRC_CNT => EI_SRC_CNT,
|
1052 |
|
|
TRIG_TYPE => EI_TRIG_TYPE,
|
1053 |
|
|
REQ_MAXCNT => EI_REQ_MAXCNT
|
1054 |
|
|
)
|
1055 |
|
|
port map(
|
1056 |
|
|
CLK_i => CLK_i,
|
1057 |
|
|
RST_i => RST_i,
|
1058 |
|
|
REG_A_i => DADR_PLIC,
|
1059 |
|
|
REG_WE_i => DWE_PLIC,
|
1060 |
|
|
REG_D_i => DDATI_IO,
|
1061 |
|
|
REQ_i => EI_REQ_i,
|
1062 |
|
|
|
1063 |
|
|
REG_Q_o => DDATO_PLIC,
|
1064 |
|
|
EIP_o => EXT_INT
|
1065 |
|
|
);
|
1066 |
|
|
|
1067 |
|
|
-- PLIC address is a subset of I/O address space.
|
1068 |
|
|
|
1069 |
|
|
process(DADR_IO)
|
1070 |
|
|
variable TMP : unsigned(ALEN-1 downto 0);
|
1071 |
|
|
begin
|
1072 |
|
|
TMP := DADR_IO/4 - PLIC_ABASE;
|
1073 |
|
|
DADR_PLIC <= to_std_logic_vector(TMP(PLIC_AWIDTH-1 downto 0));
|
1074 |
|
|
end process;
|
1075 |
|
|
|
1076 |
|
|
-- PLIC write-enable is set to DWE_IO when I/O address
|
1077 |
|
|
-- falls in PLIC address range.
|
1078 |
|
|
|
1079 |
|
|
DWE_PLIC <= DWE_IO when (to_unsigned(DADR_PLIC) <= PLIC_AMAX) else '0';
|
1080 |
|
|
|
1081 |
|
|
-- PLIC is the only I/O module present, so I/O
|
1082 |
|
|
-- memory data-out is coincident with PLIC data-out.
|
1083 |
|
|
|
1084 |
|
|
DDATO_IO <= DDATO_PLIC;
|
1085 |
|
|
|
1086 |
|
|
end generate; -- GPLIC_1
|
1087 |
|
|
|
1088 |
|
|
GPLIC_0 : if(PLIC_PRESENT = '0') generate
|
1089 |
|
|
DDATO_PLIC <= (others => '0');
|
1090 |
|
|
EXT_INT <= '0';
|
1091 |
|
|
DDATO_IO <= (others => '0');
|
1092 |
|
|
end generate; -- GPLIC_0
|
1093 |
|
|
|
1094 |
|
|
---------------------------------------------------
|
1095 |
|
|
-- DP port data-out (same as data RAM data-out)
|
1096 |
|
|
---------------------------------------------------
|
1097 |
|
|
|
1098 |
|
|
GIOM1_GT0 : if(IOMEM_SIZE > 0) generate
|
1099 |
|
|
DP_DAT_o <=
|
1100 |
|
|
DDATI0_RAM when (DP_ADR_MS_q = '1' and DP_IOADR_MS_q = '0') else
|
1101 |
|
|
DDATO_IO when (DP_ADR_MS_q = '1' and DP_IOADR_MS_q = '1') else
|
1102 |
|
|
IDATI;
|
1103 |
|
|
end generate;
|
1104 |
|
|
|
1105 |
|
|
GIOM1_EQ0 : if(IOMEM_SIZE = 0) generate
|
1106 |
|
|
DP_DAT_o <=
|
1107 |
|
|
DDATI0_RAM when (DP_ADR_MS_q = '1') else
|
1108 |
|
|
IDATI;
|
1109 |
|
|
end generate;
|
1110 |
|
|
|
1111 |
|
|
end ARC;
|