-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmipssingle.vhd
565 lines (494 loc) · 18.8 KB
/
mipssingle.vhd
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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
-- mips.vhd
-- From Section 7.6 of Digital Design & Computer Architecture
-- Updated to VHDL 2008 26 July 2011 [email protected]
library IEEE;
use IEEE.STD_LOGIC_1164.all; use IEEE.NUMERIC_STD_UNSIGNED.all;
entity testbench is
end;
architecture test of testbench is
component top
port(clk, reset: in STD_LOGIC;
writedata, dataadr: out STD_LOGIC_VECTOR(31 downto 0);
memwrite: out STD_LOGIC);
end component;
signal writedata, dataadr: STD_LOGIC_VECTOR(31 downto 0);
signal clk, reset, memwrite: STD_LOGIC;
begin
-- instantiate device to be tested
dut: top port map(clk, reset, writedata, dataadr, memwrite);
-- Generate clock with 10 ns period
process begin
clk <= '1';
wait for 5 ns;
clk <= '0';
wait for 5 ns;
end process;
-- Generate reset for first two clock cycles
process begin
reset <= '1';
wait for 22 ns;
reset <= '0';
wait;
end process;
-- check that 0xffff7f02 gets written to address 0x54(=84) at end of program
process (clk) begin
if (clk'event and clk = '0' and memwrite = '1') then
if (to_integer(dataadr) = 84 and writedata = x"ffff7f02") then
report "NO ERRORS: Simulation succeeded" severity failure;
else
report "Simulation failed" severity failure;
end if;
end if;
end process;
end;
library IEEE;
use IEEE.STD_LOGIC_1164.all; use IEEE.NUMERIC_STD_UNSIGNED.all;
entity top is -- top-level design for testing
port(clk, reset: in STD_LOGIC;
writedata, dataadr: buffer STD_LOGIC_VECTOR(31 downto 0);
memwrite: buffer STD_LOGIC);
end;
architecture test of top is
component mips
port(clk, reset: in STD_LOGIC;
pc: out STD_LOGIC_VECTOR(31 downto 0);
instr: in STD_LOGIC_VECTOR(31 downto 0);
memwrite: out STD_LOGIC;
aluout, writedata: out STD_LOGIC_VECTOR(31 downto 0);
readdata: in STD_LOGIC_VECTOR(31 downto 0));
end component;
component imem
port(a: in STD_LOGIC_VECTOR(5 downto 0);
rd: out STD_LOGIC_VECTOR(31 downto 0));
end component;
component dmem
port(clk, we: in STD_LOGIC;
a, wd: in STD_LOGIC_VECTOR(31 downto 0);
rd: out STD_LOGIC_VECTOR(31 downto 0));
end component;
signal pc, instr,
readdata: STD_LOGIC_VECTOR(31 downto 0);
begin
-- instantiate processor and memories
mips1: mips port map(clk, reset, pc, instr, memwrite, dataadr,
writedata, readdata);
imem1: imem port map(pc(7 downto 2), instr);
dmem1: dmem port map(clk, memwrite, dataadr, writedata, readdata);
end;
library IEEE;
use IEEE.STD_LOGIC_1164.all; use STD.TEXTIO.all;
use IEEE.NUMERIC_STD_UNSIGNED.all;
entity dmem is -- data memory
port(clk, we: in STD_LOGIC;
a, wd: in STD_LOGIC_VECTOR(31 downto 0);
rd: out STD_LOGIC_VECTOR(31 downto 0));
end;
architecture behave of dmem is
begin
process is
type ramtype is array (63 downto 0) of STD_LOGIC_VECTOR(31 downto 0);
variable mem: ramtype;
begin
-- read or write memory
loop
if clk'event and clk = '1' then
if (we = '1') then mem(to_integer(a(7 downto 2))) := wd;
end if;
end if;
rd <= mem(to_integer(a(7 downto 2)));
wait on clk, a;
end loop;
end process;
end;
library IEEE;
use IEEE.STD_LOGIC_1164.all; use STD.TEXTIO.all;
use IEEE.NUMERIC_STD_UNSIGNED.all;
entity imem is -- instruction memory
port(a: in STD_LOGIC_VECTOR(5 downto 0);
rd: out STD_LOGIC_VECTOR(31 downto 0));
end;
architecture behave of imem is
begin
process is
file mem_file: TEXT;
variable L: line;
variable ch: character;
variable i, index, result: integer;
type ramtype is array (63 downto 0) of STD_LOGIC_VECTOR(31 downto 0);
variable mem: ramtype;
begin
-- initialize memory from file
for i in 0 to 63 loop -- set all contents low
mem(i) := (others => '0');
end loop;
index := 0;
FILE_OPEN(mem_file,"C:\Users\Matheus\Documents\memfile3.dat", READ_MODE);
while not endfile(mem_file) loop
readline(mem_file, L);
result := 0;
for i in 1 to 8 loop
read(L, ch);
if '0' <= ch and ch <= '9' then
result := character'pos(ch) - character'pos('0');
elsif 'a' <= ch and ch <= 'f' then
result := character'pos(ch) - character'pos('a')+10;
else report "Format error on line " & integer'image(index)
severity error;
end if;
mem(index)(35-i*4 downto 32-i*4) :=to_std_logic_vector(result,4);
end loop;
index := index + 1;
end loop;
-- read memory
loop
rd <= mem(to_integer(a));
wait on a;
end loop;
end process;
end;
library IEEE; use IEEE.STD_LOGIC_1164.all;
entity mips is -- single cycle MIPS processor
port(clk, reset: in STD_LOGIC;
pc: out STD_LOGIC_VECTOR(31 downto 0);
instr: in STD_LOGIC_VECTOR(31 downto 0);
memwrite: out STD_LOGIC;
aluout, writedata: out STD_LOGIC_VECTOR(31 downto 0);
readdata: in STD_LOGIC_VECTOR(31 downto 0));
end;
architecture struct of mips is
component controller
port(op, funct: in STD_LOGIC_VECTOR(5 downto 0);
zero: in STD_LOGIC;
memtoreg, memwrite: out STD_LOGIC;
pcsrc, alusrc: out STD_LOGIC;
regdst, regwrite: out STD_LOGIC;
jump: out STD_LOGIC;
alucontrol: out STD_LOGIC_VECTOR(2 downto 0);
immsrc: out STD_LOGIC);
end component;
component datapath
port(clk, reset: in STD_LOGIC;
memtoreg, pcsrc: in STD_LOGIC;
alusrc, regdst: in STD_LOGIC;
regwrite, jump: in STD_LOGIC;
alucontrol: in STD_LOGIC_VECTOR(2 downto 0);
immsrc: in STD_LOGIC;
zero: out STD_LOGIC;
pc: buffer STD_LOGIC_VECTOR(31 downto 0);
instr: in STD_LOGIC_VECTOR(31 downto 0);
aluout, writedata: buffer STD_LOGIC_VECTOR(31 downto 0);
readdata: in STD_LOGIC_VECTOR(31 downto 0));
end component;
signal memtoreg, alusrc, regdst, regwrite, jump, pcsrc, immsrc: STD_LOGIC;
signal zero: STD_LOGIC;
signal alucontrol: STD_LOGIC_VECTOR(2 downto 0);
begin
cont: controller port map(instr(31 downto 26), instr(5 downto 0),
zero, memtoreg, memwrite, pcsrc, alusrc,
regdst, regwrite, jump, alucontrol, immsrc);
dp: datapath port map(clk, reset, memtoreg, pcsrc, alusrc, regdst,
regwrite, jump, alucontrol, immsrc, zero, pc, instr,
aluout, writedata, readdata);
end;
library IEEE; use IEEE.STD_LOGIC_1164.all;
entity controller is -- single cycle control decoder
port(op, funct: in STD_LOGIC_VECTOR(5 downto 0);
zero: in STD_LOGIC;
memtoreg, memwrite: out STD_LOGIC;
pcsrc, alusrc: out STD_LOGIC;
regdst, regwrite: out STD_LOGIC;
jump: out STD_LOGIC;
alucontrol: out STD_LOGIC_VECTOR(2 downto 0);
immsrc: out STD_LOGIC);
end;
architecture struct of controller is
component maindec
port(op: in STD_LOGIC_VECTOR(5 downto 0);
memtoreg, memwrite: out STD_LOGIC;
branch, alusrc: out STD_LOGIC;
regdst, regwrite: out STD_LOGIC;
jump: out STD_LOGIC;
aluop: out STD_LOGIC_VECTOR(1 downto 0);
zerosrc: out STD_LOGIC;
immsrc: out STD_LOGIC);
end component;
component aludec
port(funct: in STD_LOGIC_VECTOR(5 downto 0);
aluop: in STD_LOGIC_VECTOR(1 downto 0);
alucontrol: out STD_LOGIC_VECTOR(2 downto 0));
end component;
signal aluop: STD_LOGIC_VECTOR(1 downto 0);
signal branch: STD_LOGIC;
signal zerosrc: STD_LOGIC;
signal mux_zero: STD_LOGIC;
begin
md: maindec port map(op, memtoreg, memwrite, branch,
alusrc, regdst, regwrite, jump, aluop, zerosrc, immsrc);
ad: aludec port map(funct, aluop, alucontrol);
-- é, basicamente, um mux para poder implementar o bne - branch on not equal
mux_zero <= zero when zerosrc = '0' else not zero;
pcsrc <= branch and mux_zero;
end;
library IEEE; use IEEE.STD_LOGIC_1164.all;
entity maindec is -- main control decoder
port(op: in STD_LOGIC_VECTOR(5 downto 0);
memtoreg, memwrite: out STD_LOGIC;
branch, alusrc: out STD_LOGIC;
regdst, regwrite: out STD_LOGIC;
jump: out STD_LOGIC;
aluop: out STD_LOGIC_VECTOR(1 downto 0);
zerosrc: out STD_LOGIC;
immsrc: out STD_LOGIC);
end;
architecture behave of maindec is
signal controls: STD_LOGIC_VECTOR(10 downto 0);
begin
process(all) begin
case op is
when "000000" => controls <= "11000001000"; -- RTYPE
when "100011" => controls <= "10100100000"; -- LW
when "101011" => controls <= "00101000000"; -- SW
when "000100" => controls <= "00010000100"; -- BEQ
when "001000" => controls <= "10100000000"; -- ADDI
when "000010" => controls <= "00000010000"; -- J
when "001101" => controls <= "10100001101"; -- ORI
when "000101" => controls <= "00010000110"; -- BNE
when others => controls <= "-----------"; -- illegal op
end case;
end process;
(regwrite, regdst, alusrc, branch, memwrite,
memtoreg, jump, aluop(1 downto 0), zerosrc, immsrc) <= controls;
end;
library IEEE; use IEEE.STD_LOGIC_1164.all;
entity aludec is -- ALU control decoder
port(funct: in STD_LOGIC_VECTOR(5 downto 0);
aluop: in STD_LOGIC_VECTOR(1 downto 0);
alucontrol: out STD_LOGIC_VECTOR(2 downto 0));
end;
architecture behave of aludec is
begin
process(all) begin
case aluop is
when "00" => alucontrol <= "010"; -- add (for lw/sw/addi)
when "01" => alucontrol <= "110"; -- sub (for beq or bne)
when "11" => alucontrol <= "001"; -- or (for ori)
when others => case funct is -- R-type instructions
when "100000" => alucontrol <= "010"; -- add
when "100010" => alucontrol <= "110"; -- sub
when "100100" => alucontrol <= "000"; -- and
when "100101" => alucontrol <= "001"; -- or
when "101010" => alucontrol <= "111"; -- slt
when others => alucontrol <= "---"; -- ???
end case;
end case;
end process;
end;
library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_ARITH.all;
entity datapath is -- MIPS datapath
port(clk, reset: in STD_LOGIC;
memtoreg, pcsrc: in STD_LOGIC;
alusrc, regdst: in STD_LOGIC;
regwrite, jump: in STD_LOGIC;
alucontrol: in STD_LOGIC_VECTOR(2 downto 0);
immsrc: in STD_LOGIC;
zero: out STD_LOGIC;
pc: buffer STD_LOGIC_VECTOR(31 downto 0);
instr: in STD_LOGIC_VECTOR(31 downto 0);
aluout, writedata: buffer STD_LOGIC_VECTOR(31 downto 0);
readdata: in STD_LOGIC_VECTOR(31 downto 0));
end;
architecture struct of datapath is
component alu
port(a, b: in STD_LOGIC_VECTOR(31 downto 0);
alucontrol: in STD_LOGIC_VECTOR(2 downto 0);
result: buffer STD_LOGIC_VECTOR(31 downto 0);
zero: out STD_LOGIC);
end component;
component regfile
port(clk: in STD_LOGIC;
we3: in STD_LOGIC;
ra1, ra2, wa3: in STD_LOGIC_VECTOR(4 downto 0);
wd3: in STD_LOGIC_VECTOR(31 downto 0);
rd1, rd2: out STD_LOGIC_VECTOR(31 downto 0));
end component;
component adder
port(a, b: in STD_LOGIC_VECTOR(31 downto 0);
y: out STD_LOGIC_VECTOR(31 downto 0));
end component;
component sl2
port(a: in STD_LOGIC_VECTOR(31 downto 0);
y: out STD_LOGIC_VECTOR(31 downto 0));
end component;
component signext
port(a: in STD_LOGIC_VECTOR(15 downto 0);
y: out STD_LOGIC_VECTOR(31 downto 0));
end component;
component unsignext
port(a: in STD_LOGIC_VECTOR(15 downto 0);
y: out STD_LOGIC_VECTOR(31 downto 0));
end component;
component flopr generic(width: integer);
port(clk, reset: in STD_LOGIC;
d: in STD_LOGIC_VECTOR(width-1 downto 0);
q: out STD_LOGIC_VECTOR(width-1 downto 0));
end component;
component mux2 generic(width: integer);
port(d0, d1: in STD_LOGIC_VECTOR(width-1 downto 0);
s: in STD_LOGIC;
y: out STD_LOGIC_VECTOR(width-1 downto 0));
end component;
signal writereg: STD_LOGIC_VECTOR(4 downto 0);
signal pcjump, pcnext,
pcnextbr, pcplus4,
pcbranch: STD_LOGIC_VECTOR(31 downto 0);
signal signimm, unsignimm, imm, immsh: STD_LOGIC_VECTOR(31 downto 0);
signal srca, srcb, result: STD_LOGIC_VECTOR(31 downto 0);
begin
-- next PC logic
pcjump <= pcplus4(31 downto 28) & instr(25 downto 0) & "00";
pcreg: flopr generic map(32) port map(clk, reset, pcnext, pc);
pcadd1: adder port map(pc, X"00000004", pcplus4);
immsht: sl2 port map(imm, immsh);
pcadd2: adder port map(pcplus4, immsh, pcbranch);
pcbrmux: mux2 generic map(32) port map(pcplus4, pcbranch,
pcsrc, pcnextbr);
pcmux: mux2 generic map(32) port map(pcnextbr, pcjump, jump, pcnext);
-- register file logic
rf: regfile port map(clk, regwrite, instr(25 downto 21),
instr(20 downto 16), writereg, result, srca,
writedata);
wrmux: mux2 generic map(5) port map(instr(20 downto 16),
instr(15 downto 11),
regdst, writereg);
resmux: mux2 generic map(32) port map(aluout, readdata,
memtoreg, result);
se: signext port map(instr(15 downto 0), signimm);
us: unsignext port map(instr(15 downto 0), unsignimm);
immux: mux2 generic map(32) port map(signimm, unsignimm, immsrc, imm);
-- ALU logic
srcbmux: mux2 generic map(32) port map(writedata, imm, alusrc,
srcb);
mainalu: alu port map(srca, srcb, alucontrol, aluout, zero);
end;
library IEEE; use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD_UNSIGNED.all;
entity regfile is -- three-port register file
port(clk: in STD_LOGIC;
we3: in STD_LOGIC;
ra1, ra2, wa3: in STD_LOGIC_VECTOR(4 downto 0);
wd3: in STD_LOGIC_VECTOR(31 downto 0);
rd1, rd2: out STD_LOGIC_VECTOR(31 downto 0));
end;
architecture behave of regfile is
type ramtype is array (31 downto 0) of STD_LOGIC_VECTOR(31 downto 0);
signal mem: ramtype;
begin
-- three-ported register file
-- read two ports combinationally
-- write third port on rising edge of clock
-- register 0 hardwired to 0
-- note: for pipelined processor, write third port
-- on falling edge of clk
process(clk) begin
if rising_edge(clk) then
if we3 = '1' then mem(to_integer(wa3)) <= wd3;
end if;
end if;
end process;
process(all) begin
if (to_integer(ra1) = 0) then rd1 <= X"00000000"; -- register 0 holds 0
else rd1 <= mem(to_integer(ra1));
end if;
if (to_integer(ra2) = 0) then rd2 <= X"00000000";
else rd2 <= mem(to_integer(ra2));
end if;
end process;
end;
library IEEE; use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD_UNSIGNED.all;
entity adder is -- adder
port(a, b: in STD_LOGIC_VECTOR(31 downto 0);
y: out STD_LOGIC_VECTOR(31 downto 0));
end;
architecture behave of adder is
begin
y <= a + b;
end;
library IEEE; use IEEE.STD_LOGIC_1164.all;
entity sl2 is -- shift left by 2
port(a: in STD_LOGIC_VECTOR(31 downto 0);
y: out STD_LOGIC_VECTOR(31 downto 0));
end;
architecture behave of sl2 is
begin
y <= a(29 downto 0) & "00";
end;
library IEEE; use IEEE.STD_LOGIC_1164.all;
entity signext is -- sign extender
port(a: in STD_LOGIC_VECTOR(15 downto 0);
y: out STD_LOGIC_VECTOR(31 downto 0));
end;
architecture behave of signext is
begin
y <= X"ffff" & a when a(15) else X"0000" & a;
end;
library IEEE; use IEEE.STD_LOGIC_1164.all;
entity unsignext is -- unsign extender
port(a: in STD_LOGIC_VECTOR(15 downto 0);
y: out STD_LOGIC_VECTOR(31 downto 0));
end;
architecture behave of unsignext is
begin
y <= X"0000" & a;
end;
library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_ARITH.all;
entity flopr is -- flip-flop with synchronous reset
generic(width: integer);
port(clk, reset: in STD_LOGIC;
d: in STD_LOGIC_VECTOR(width-1 downto 0);
q: out STD_LOGIC_VECTOR(width-1 downto 0));
end;
architecture asynchronous of flopr is
begin
process(clk, reset) begin
if reset then q <= (others => '0');
elsif rising_edge(clk) then
q <= d;
end if;
end process;
end;
library IEEE; use IEEE.STD_LOGIC_1164.all;
entity mux2 is -- two-input multiplexer
generic(width: integer);
port(d0, d1: in STD_LOGIC_VECTOR(width-1 downto 0);
s: in STD_LOGIC;
y: out STD_LOGIC_VECTOR(width-1 downto 0));
end;
architecture behave of mux2 is
begin
y <= d1 when s else d0;
end;
library IEEE; use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD_UNSIGNED.all;
entity alu is
port(a, b: in STD_LOGIC_VECTOR(31 downto 0);
alucontrol: in STD_LOGIC_VECTOR(2 downto 0);
result: buffer STD_LOGIC_VECTOR(31 downto 0);
zero: out STD_LOGIC);
end;
architecture behave of alu is
signal condinvb, sum: STD_LOGIC_VECTOR(31 downto 0);
begin
condinvb <= not b when alucontrol(2) else b;
sum <= a + condinvb + alucontrol(2);
process(all) begin
case alucontrol(1 downto 0) is
when "00" => result <= a and b;
when "01" => result <= a or b;
when "10" => result <= sum;
when "11" => result <= (0 => sum(31), others => '0');
when others => result <= (others => 'X');
end case;
end process;
zero <= '1' when result = X"00000000" else '0';
end;