1 | -- mips.vhd
|
2 | -- From Section 7.6 of Digital Design & Computer Architecture
|
3 | -- Updated to VHDL 2008 26 July 2011 David_Harris@hmc.edu
|
4 | -- Modified at U de Montreal 2015
|
5 |
|
6 | library IEEE;
|
7 | use IEEE.STD_LOGIC_1164.all; use IEEE.NUMERIC_STD.all;
|
8 |
|
9 | entity One_Cycle_MIPS is
|
10 | signal RTdata, dataadr: STD_LOGIC_VECTOR(31 downto 0);
|
11 | signal clk, reset, memwrite: STD_LOGIC := '0';
|
12 | signal pc, instr,
|
13 | readdata: STD_LOGIC_VECTOR(31 downto 0);
|
14 |
|
15 | ------------Data Memory----------------------------
|
16 | type ramtype is array (63 downto 0) of STD_LOGIC_VECTOR(31 downto 0);
|
17 | signal mem: ramtype;
|
18 | ----============Pgm to execute==================================
|
19 | type MemInstType is array (0 to 63) of STD_LOGIC_VECTOR(31 downto 0);
|
20 | constant MemInst: MemInstType := (
|
21 | X"20020005", -- main: addi $2, $0, 5
|
22 | X"2003000c", -- addi $3, $0, 12
|
23 | X"2067fff7", -- addi $7, $3, â9
|
24 | X"00e22025", -- or $4, $7, $2
|
25 | X"00642824", -- and $5, $3, $4
|
26 | X"00a42820", -- add $5, $5, $4
|
27 | X"10a7000a", -- beq $5, $7, end
|
28 | X"0064202a", -- slt $4, $3, $4
|
29 | X"10800001", -- beq $4, $0, around
|
30 | X"20050000", -- addi $5, $0, 0
|
31 | X"00e2202a", -- around: slt $4, $7, $2
|
32 | X"00853820", -- add $7, $4, $5
|
33 | X"00e23822", -- sub $7, $7, $2
|
34 | X"ac670044", -- sw $7, 68($3)
|
35 | X"8c020050", -- lw $2, 80($0)
|
36 | X"08000011", -- j end
|
37 | X"20020001", -- addi $2, $0, 1
|
38 | X"ac020054", -- end: sw $2, 84($0)
|
39 | others => X"00000000");
|
40 |
|
41 | -- Signaux MIPS----------------------------------------------
|
42 | signal memtoreg, alusrc, regdst, regwrite, pcsrc: STD_LOGIC;
|
43 | signal jump, adr3contr: STD_LOGIC_VECTOR(1 downto 0);
|
44 | signal zero: STD_LOGIC;
|
45 | signal alucontrol: STD_LOGIC_VECTOR(2 downto 0);
|
46 |
|
47 | -- Format Instructions-------------------------------------------------
|
48 | alias op : std_logic_vector (5 downto 0) is instr(31 downto 26);
|
49 | alias funct : std_logic_vector (5 downto 0) is instr(5 downto 0);
|
50 | alias rs : std_logic_vector (4 downto 0) is instr(25 downto 21);
|
51 | alias rt : std_logic_vector (4 downto 0) is instr(20 downto 16);
|
52 | alias rd : std_logic_vector (4 downto 0) is instr(15 downto 11);
|
53 | alias imm : std_logic_vector (15 downto 0) is instr(15 downto 0);
|
54 | alias shift : std_logic_vector (4 downto 0) is instr(10 downto 6);
|
55 |
|
56 | ------Signaux Controller-----------------------------------
|
57 | signal aluop: STD_LOGIC_VECTOR(1 downto 0);
|
58 | signal branch: STD_LOGIC;
|
59 | -----Signaux Maindec---------------------------
|
60 | signal controls: STD_LOGIC_VECTOR(11 downto 0);
|
61 |
|
62 | --Signaux DATAPATH---------------------------------
|
63 | signal aluout, lui, wd3, ori, shift_tmp, shift_out: std_logic_vector (31 downto 0);
|
64 | signal writereg, adr3: STD_LOGIC_VECTOR(4 downto 0);
|
65 | signal PCJump, pcnext, pcnextbr, pcplus4, PCBranch, SignImm, SignImmShiftLeft2:
|
66 | STD_LOGIC_VECTOR(31 downto 0);
|
67 | signal srca, srcb, result: STD_LOGIC_VECTOR(31 downto 0);
|
68 |
|
69 | -- Signaux Register File----------------------------------------
|
70 | type RFtype is array (31 downto 0) of STD_LOGIC_VECTOR(31 downto 0);
|
71 | signal RF: RFtype;
|
72 |
|
73 | end;
|
74 | --================ARCHITECTURE=========================================
|
75 | architecture test of One_Cycle_MIPS is
|
76 | begin
|
77 | clk <= NOT clk after 5 ns; -- Generate clock with 10 ns period
|
78 | reset <= '0', '1' after 1 ns, '0' after 2 ns;
|
79 |
|
80 | ---Instruction Memory----------------------------------------------
|
81 | instr <= MemInst(to_INTEGER(unsigned(pc(7 downto 2))));
|
82 |
|
83 | ------Data Memory R/W----------------------------------------------
|
84 | process (clk) is
|
85 | begin
|
86 | if clk'event and clk = '1' then
|
87 | if (memwrite = '1') then mem(to_integer(unsigned(dataadr(7 downto 2)))) <= RTdata;
|
88 | end if;
|
89 | end if;
|
90 | end process;
|
91 |
|
92 | readdata <= mem(to_integer(unsigned(dataadr(7 downto 2))));
|
93 |
|
94 | ---===============mips========================================
|
95 | -- Controller----------------------
|
96 | maindec: process(op, funct) begin
|
97 | case op is
|
98 | when "000000" =>
|
99 | if funct = "001000" then controls <= "000000100000"; -- JR
|
100 | elsif funct = "000000" then controls <= "110000000011"; -- SLL
|
101 | else controls <= "110000001000"; -- RTYPE
|
102 | end if;
|
103 | when "100011" => controls <= "101001000000"; -- LW
|
104 | when "101011" => controls <= "001010000000"; -- SW
|
105 | when "000100" => controls <= "000100000100"; -- BEQ
|
106 | when "000010" => controls <= "000000010000"; -- J
|
107 | when "001000" => controls <= "101000000100"; -- ADDI
|
108 | when "001111" => controls <= "100000000001"; -- LUI
|
109 | when "001101" => controls <= "100000001010"; -- ORI
|
110 | when "000011" => controls <= "100000100000"; -- JAL
|
111 | when others => controls <= "------------"; -- illegal op
|
112 | end case;
|
113 | end process;
|
114 | (regwrite, regdst, alusrc, branch, memwrite, memtoreg, jump(1),jump(0),
|
115 | aluop(1),aluop(0), adr3contr(1), adr3contr(0)) <= controls;
|
116 |
|
117 | Aludec: process(aluop, funct) begin
|
118 | case aluop is
|
119 | when "00" => alucontrol <= "010"; -- add (for lw/sw/addi)
|
120 | when "01" => alucontrol <= "110"; -- sub (for beq)
|
121 | when others => case funct is -- R-type instructions
|
122 | when "100000" => alucontrol <= "010"; -- add
|
123 | when "100010" => alucontrol <= "110"; -- sub
|
124 | when "100100" => alucontrol <= "000"; -- and
|
125 | when "100101" => alucontrol <= "001"; -- or
|
126 | when "101010" => alucontrol <= "111"; -- slt
|
127 | when others => alucontrol <= "---"; -- ???
|
128 | end case;
|
129 | end case;
|
130 | end process;
|
131 |
|
132 | pcsrc <= branch and zero;
|
133 |
|
134 | --===================DATAPATH======================================
|
135 | -- next PC logic----------------------------
|
136 | SignImm <= X"ffff" & imm when imm(15) = '1' else X"0000" & imm;
|
137 | SignImmShiftLeft2 <= SignImm(29 downto 0) & "00";
|
138 |
|
139 | Plus4: pcplus4 <= STD_LOGIC_VECTOR(unsigned(pc) + 4);
|
140 | BTA: PCBranch <= std_logic_vector(signed(pcplus4) + signed(SignImmShiftLeft2));
|
141 | JTA: PCJump <= pcplus4(31 downto 28) & instr(25 downto 0) & "00";
|
142 |
|
143 | pcnextbr <= PCBranch when pcsrc = '1' else pcplus4;
|
144 | pcnext <= PCJump when jump = "01" else pcnextbr when jump = "00" else srca when jump = "10";
|
145 |
|
146 | updatePC: process(clk, reset) begin
|
147 | if reset ='1' then PC <= (others => '0');
|
148 | elsif rising_edge(clk) then
|
149 | PC <= pcnext;
|
150 | end if;
|
151 | end process;
|
152 |
|
153 | -- Register File Logic----------------------------
|
154 | srca <= (others => '0') when (to_integer(unsigned(rs)) = 0) -- register 0 holds 0
|
155 | else RF(to_integer(unsigned(rs)));
|
156 | RTdata <= (others => '0') when (to_integer(unsigned(rt)) = 0)
|
157 | else RF(to_integer(unsigned(rt)));
|
158 | srcb <= SignImm when (alusrc = '1') else RTdata;
|
159 |
|
160 | lui <= imm & X"0000";
|
161 | ori <= X"0000" & imm;
|
162 |
|
163 | wd3 <= result when adr3contr = "00" else lui when adr3contr = "01"
|
164 | else (ori OR srca) when adr3contr = "10" else shift_out when adr3contr = "11"; -- DATA
|
165 | adr3 <= "11111" when jump = "10" else writereg; --jal $ra = 31
|
166 | writereg <= rd when regdst = '1' else rt;
|
167 | result <= readdata when memtoreg = '1' else aluout;
|
168 |
|
169 | process(clk) begin
|
170 | if rising_edge(clk) then
|
171 | if regwrite = '1' then RF(to_integer(unsigned(adr3))) <= wd3;
|
172 | end if;
|
173 | end if;
|
174 | end process;
|
175 |
|
176 | shift_tmp <= RTdata;
|
177 |
|
178 | process (shift, RTdata)
|
179 | variable i := integer range 0 to 31;
|
180 | i:=0;
|
181 |
|
182 | begin
|
183 | for i in 0 to (to_integer(unsigned(shift))) loop
|
184 | shift_tmp <= shift_tmp sll 1;
|
185 | end loop;
|
186 | end process;
|
187 |
|
188 | shift_out <= shift_tmp;{-- mips.vhd
|
189 | -- From Section 7.6 of Digital Design & Computer Architecture
|
190 | -- Updated to VHDL 2008 26 July 2011 David_Harris@hmc.edu
|
191 | -- Modified at U de Montreal 2015
|
192 |
|
193 | library IEEE;
|
194 | use IEEE.STD_LOGIC_1164.all; use IEEE.NUMERIC_STD.all;
|
195 |
|
196 | entity One_Cycle_MIPS is
|
197 | signal RTdata, dataadr: STD_LOGIC_VECTOR(31 downto 0);
|
198 | signal clk, reset, memwrite: STD_LOGIC := '0';
|
199 | signal pc, instr,
|
200 | readdata: STD_LOGIC_VECTOR(31 downto 0);
|
201 |
|
202 | ------------Data Memory----------------------------
|
203 | type ramtype is array (63 downto 0) of STD_LOGIC_VECTOR(31 downto 0);
|
204 | signal mem: ramtype;
|
205 | ----============Pgm to execute==================================
|
206 | type MemInstType is array (0 to 63) of STD_LOGIC_VECTOR(31 downto 0);
|
207 | constant MemInst: MemInstType := (
|
208 | X"20020005", -- main: addi $2, $0, 5
|
209 | X"2003000c", -- addi $3, $0, 12
|
210 | X"2067fff7", -- addi $7, $3, âÂÂ9
|
211 | X"00e22025", -- or $4, $7, $2
|
212 | X"00642824", -- and $5, $3, $4
|
213 | X"00a42820", -- add $5, $5, $4
|
214 | X"10a7000a", -- beq $5, $7, end
|
215 | X"0064202a", -- slt $4, $3, $4
|
216 | X"10800001", -- beq $4, $0, around
|
217 | X"20050000", -- addi $5, $0, 0
|
218 | X"00e2202a", -- around: slt $4, $7, $2
|
219 | X"00853820", -- add $7, $4, $5
|
220 | X"00e23822", -- sub $7, $7, $2
|
221 | X"ac670044", -- sw $7, 68($3)
|
222 | X"8c020050", -- lw $2, 80($0)
|
223 | X"08000011", -- j end
|
224 | X"20020001", -- addi $2, $0, 1
|
225 | X"ac020054", -- end: sw $2, 84($0)
|
226 | others => X"00000000");
|
227 |
|
228 | -- Signaux MIPS----------------------------------------------
|
229 | signal memtoreg, alusrc, regdst, regwrite, pcsrc: STD_LOGIC;
|
230 | signal jump, adr3contr: STD_LOGIC_VECTOR(1 downto 0);
|
231 | signal zero: STD_LOGIC;
|
232 | signal alucontrol: STD_LOGIC_VECTOR(2 downto 0);
|
233 |
|
234 | -- Format Instructions-------------------------------------------------
|
235 | alias op : std_logic_vector (5 downto 0) is instr(31 downto 26);
|
236 | alias funct : std_logic_vector (5 downto 0) is instr(5 downto 0);
|
237 | alias rs : std_logic_vector (4 downto 0) is instr(25 downto 21);
|
238 | alias rt : std_logic_vector (4 downto 0) is instr(20 downto 16);
|
239 | alias rd : std_logic_vector (4 downto 0) is instr(15 downto 11);
|
240 | alias imm : std_logic_vector (15 downto 0) is instr(15 downto 0);
|
241 | alias shift : std_logic_vector (4 downto 0) is instr(10 downto 6);
|
242 |
|
243 | ------Signaux Controller-----------------------------------
|
244 | signal aluop: STD_LOGIC_VECTOR(1 downto 0);
|
245 | signal branch: STD_LOGIC;
|
246 | -----Signaux Maindec---------------------------
|
247 | signal controls: STD_LOGIC_VECTOR(11 downto 0);
|
248 |
|
249 | --Signaux DATAPATH---------------------------------
|
250 | signal aluout, lui, wd3, ori, shift_tmp, shift_out: std_logic_vector (31 downto 0);
|
251 | signal writereg, adr3: STD_LOGIC_VECTOR(4 downto 0);
|
252 | signal PCJump, pcnext, pcnextbr, pcplus4, PCBranch, SignImm, SignImmShiftLeft2:
|
253 | STD_LOGIC_VECTOR(31 downto 0);
|
254 | signal srca, srcb, result: STD_LOGIC_VECTOR(31 downto 0);
|
255 |
|
256 | -- Signaux Register File----------------------------------------
|
257 | type RFtype is array (31 downto 0) of STD_LOGIC_VECTOR(31 downto 0);
|
258 | signal RF: RFtype;
|
259 |
|
260 | end;
|
261 | --================ARCHITECTURE=========================================
|
262 | architecture test of One_Cycle_MIPS is
|
263 | begin
|
264 | clk <= NOT clk after 5 ns; -- Generate clock with 10 ns period
|
265 | reset <= '0', '1' after 1 ns, '0' after 2 ns;
|
266 |
|
267 | ---Instruction Memory----------------------------------------------
|
268 | instr <= MemInst(to_INTEGER(unsigned(pc(7 downto 2))));
|
269 |
|
270 | ------Data Memory R/W----------------------------------------------
|
271 | process (clk) is
|
272 | begin
|
273 | if clk'event and clk = '1' then
|
274 | if (memwrite = '1') then mem(to_integer(unsigned(dataadr(7 downto 2)))) <= RTdata;
|
275 | end if;
|
276 | end if;
|
277 | end process;
|
278 |
|
279 | readdata <= mem(to_integer(unsigned(dataadr(7 downto 2))));
|
280 |
|
281 | ---===============mips========================================
|
282 | -- Controller----------------------
|
283 | maindec: process(op, funct) begin
|
284 | case op is
|
285 | when "000000" =>
|
286 | if funct = "001000" then controls <= "000000100000"; -- JR
|
287 | elsif funct = "000000" then controls <= "110000000011"; -- SLL
|
288 | else controls <= "110000001000"; -- RTYPE
|
289 | end if;
|
290 | when "100011" => controls <= "101001000000"; -- LW
|
291 | when "101011" => controls <= "001010000000"; -- SW
|
292 | when "000100" => controls <= "000100000100"; -- BEQ
|
293 | when "000010" => controls <= "000000010000"; -- J
|
294 | when "001000" => controls <= "101000000100"; -- ADDI
|
295 | when "001111" => controls <= "100000000001"; -- LUI
|
296 | when "001101" => controls <= "100000001010"; -- ORI
|
297 | when "000011" => controls <= "100000100000"; -- JAL
|
298 | when others => controls <= "------------"; -- illegal op
|
299 | end case;
|
300 | end process;
|
301 | (regwrite, regdst, alusrc, branch, memwrite, memtoreg, jump(1),jump(0),
|
302 | aluop(1),aluop(0), adr3contr(1), adr3contr(0)) <= controls;
|
303 |
|
304 | Aludec: process(aluop, funct) begin
|
305 | case aluop is
|
306 | when "00" => alucontrol <= "010"; -- add (for lw/sw/addi)
|
307 | when "01" => alucontrol <= "110"; -- sub (for beq)
|
308 | when others => case funct is -- R-type instructions
|
309 | when "100000" => alucontrol <= "010"; -- add
|
310 | when "100010" => alucontrol <= "110"; -- sub
|
311 | when "100100" => alucontrol <= "000"; -- and
|
312 | when "100101" => alucontrol <= "001"; -- or
|
313 | when "101010" => alucontrol <= "111"; -- slt
|
314 | when others => alucontrol <= "---"; -- ???
|
315 | end case;
|
316 | end case;
|
317 | end process;
|
318 |
|
319 | pcsrc <= branch and zero;
|
320 |
|
321 | --===================DATAPATH======================================
|
322 | -- next PC logic----------------------------
|
323 | SignImm <= X"ffff" & imm when imm(15) = '1' else X"0000" & imm;
|
324 | SignImmShiftLeft2 <= SignImm(29 downto 0) & "00";
|
325 |
|
326 | Plus4: pcplus4 <= STD_LOGIC_VECTOR(unsigned(pc) + 4);
|
327 | BTA: PCBranch <= std_logic_vector(signed(pcplus4) + signed(SignImmShiftLeft2));
|
328 | JTA: PCJump <= pcplus4(31 downto 28) & instr(25 downto 0) & "00";
|
329 |
|
330 | pcnextbr <= PCBranch when pcsrc = '1' else pcplus4;
|
331 | pcnext <= PCJump when jump = "01" else pcnextbr when jump = "00" else srca when jump = "10";
|
332 |
|
333 | updatePC: process(clk, reset) begin
|
334 | if reset ='1' then PC <= (others => '0');
|
335 | elsif rising_edge(clk) then
|
336 | PC <= pcnext;
|
337 | end if;
|
338 | end process;
|
339 |
|
340 | -- Register File Logic----------------------------
|
341 | srca <= (others => '0') when (to_integer(unsigned(rs)) = 0) -- register 0 holds 0
|
342 | else RF(to_integer(unsigned(rs)));
|
343 | RTdata <= (others => '0') when (to_integer(unsigned(rt)) = 0)
|
344 | else RF(to_integer(unsigned(rt)));
|
345 | srcb <= SignImm when (alusrc = '1') else RTdata;
|
346 |
|
347 | lui <= imm & X"0000";
|
348 | ori <= X"0000" & imm;
|
349 |
|
350 | wd3 <= result when adr3contr = "00" else lui when adr3contr = "01"
|
351 | else (ori OR srca) when adr3contr = "10" else shift_out when adr3contr = "11"; -- DATA
|
352 | adr3 <= "11111" when jump = "10" else writereg; --jal $ra = 31
|
353 | writereg <= rd when regdst = '1' else rt;
|
354 | result <= readdata when memtoreg = '1' else aluout;
|
355 |
|
356 | process(clk) begin
|
357 | if rising_edge(clk) then
|
358 | if regwrite = '1' then RF(to_integer(unsigned(adr3))) <= wd3;
|
359 | end if;
|
360 | end if;
|
361 | end process;
|
362 |
|
363 | shift_tmp <= RTdata;
|
364 |
|
365 | process (shift, RTdata)
|
366 | variable i := integer range 0 to 31;
|
367 | i:=0;
|
368 |
|
369 | begin
|
370 | for i in 0 to (to_integer(unsigned(shift))) loop
|
371 | shift_tmp <= shift_tmp sll 1;
|
372 | end loop;
|
373 | end process;
|
374 |
|
375 | shift_out <= shift_tmp;
|
376 |
|
377 | -- ALU logic -------------------------------------------------------
|
378 | process(alucontrol, srca, srcb)
|
379 | variable sum: STD_LOGIC_VECTOR(31 downto 0);
|
380 | begin
|
381 | if alucontrol(2) = '0'
|
382 | then sum := STD_LOGIC_VECTOR(signed(srca) + signed(srcb));
|
383 | else sum := STD_LOGIC_VECTOR(signed(srca) - signed(srcb));
|
384 | end if;
|
385 | case alucontrol(2 downto 0) is
|
386 | when "000" => aluout <= srca and srcb;
|
387 | when "001" => aluout <= srca or srcb;
|
388 | when "010"|"110" => aluout <= sum;
|
389 | when "111" => aluout <= (0 => sum(31), others => '0');
|
390 | when others => aluout <= (others => 'X');
|
391 | end case;
|
392 | end process;
|
393 |
|
394 | zero <= '1' when (aluout = X"00000000") else '0';
|
395 | dataadr <= aluout;
|
396 |
|
397 | --========================VERIFICATION=====================================
|
398 | -- check that 7 gets written to address 84 at end of program
|
399 | process (clk) begin
|
400 | if (clk'event and clk = '0' and memwrite = '1') then
|
401 | if (to_integer(unsigned(dataadr)) = 84 and
|
402 | to_integer(unsigned(RTdata)) = 7) then
|
403 | report "NO ERRORS: Simulation succeeded" severity failure;
|
404 | elsif (to_integer(unsigned(dataadr)) /= 80) then
|
405 | report "Simulation failed" severity failure;
|
406 | end if;
|
407 | end if;
|
408 | end process;
|
409 | end;
|
410 | }
|
411 |
|
412 | -- ALU logic -------------------------------------------------------
|
413 | process(alucontrol, srca, srcb)
|
414 | variable sum: STD_LOGIC_VECTOR(31 downto 0);
|
415 | begin
|
416 | if alucontrol(2) = '0'
|
417 | then sum := STD_LOGIC_VECTOR(signed(srca) + signed(srcb));
|
418 | else sum := STD_LOGIC_VECTOR(signed(srca) - signed(srcb));
|
419 | end if;
|
420 | case alucontrol(2 downto 0) is
|
421 | when "000" => aluout <= srca and srcb;
|
422 | when "001" => aluout <= srca or srcb;
|
423 | when "010"|"110" => aluout <= sum;
|
424 | when "111" => aluout <= (0 => sum(31), others => '0');
|
425 | when others => aluout <= (others => 'X');
|
426 | end case;
|
427 | end process;
|
428 |
|
429 | zero <= '1' when (aluout = X"00000000") else '0';
|
430 | dataadr <= aluout;
|