OpenCores
URL https://opencores.org/ocsvn/plasma/plasma/trunk

Subversion Repositories plasma

[/] [plasma/] [trunk/] [vhdl/] [control.vhd] - Blame information for rev 7

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 rhoads
---------------------------------------------------------------------
2
-- TITLE: Controller / Opcode Decoder
3
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4
-- DATE CREATED: 2/8/01
5
-- FILENAME: control.vhd
6
-- PROJECT: MIPS CPU core
7
-- COPYRIGHT: Software placed into the public domain by the author.
8
--    Software 'as is' without warranty.  Author liable for nothing.
9
-- DESCRIPTION:
10
--    Controls the CPU by decoding the opcode and generating control 
11
--    signals to the rest of the CPU.
12
--    This entity decodes the MIPS opcode into a Very-Long-Word-Instruction.
13
--    The 32-bit opcode is converted to a 
14
--       6+6+6+16+5+2+3+3+2+2+3+2+4 = 60 bit VLWI opcode.
15
--    Based on information found in:
16
--       "MIPS RISC Architecture" by Gerry Kane and Joe Heinrich
17
--       and "The Designer's Guide to VHDL" by Peter J. Ashenden
18
---------------------------------------------------------------------
19
library ieee;
20
use ieee.std_logic_1164.all;
21
use work.mips_pack.all;
22
 
23
entity control is
24
   port(opcode       : in  std_logic_vector(31 downto 0);
25
        intr_signal  : in  std_logic;
26 7 rhoads
        pause_in     : in  std_logic;
27 2 rhoads
        rs_index     : out std_logic_vector(5 downto 0);
28
        rt_index     : out std_logic_vector(5 downto 0);
29
        rd_index     : out std_logic_vector(5 downto 0);
30
        imm_out      : out std_logic_vector(15 downto 0);
31
        alu_func     : out alu_function_type;
32
        shift_func   : out shift_function_type;
33
        mult_func    : out mult_function_type;
34
        branch_func  : out branch_function_type;
35
        a_source_out : out a_source_type;
36
        b_source_out : out b_source_type;
37
        c_source_out : out c_source_type;
38
        pc_source_out: out pc_source_type;
39
        mem_source_out:out mem_source_type);
40
end; --entity control
41
 
42
architecture logic of control is
43
--   type alu_function_type is (alu_nothing, alu_add, alu_subtract, 
44
--      alu_less_than, alu_less_than_signed, alu_equal, alu_not_equal,
45
--      alu_ltz, alu_lez, alu_eqz, alu_nez, alu_gez, alu_gtz,
46
--      alu_or, alu_and, alu_xor, alu_nor);
47
--   type shift_function_type is (
48
--      shift_nothing, shift_left_unsigned,  
49
--      shift_right_signed, shift_right_unsigned);
50
--   type mult_function_type is (
51
--      mult_nothing, mult_read_lo, mult_read_hi, mult_write_lo, 
52
--      mult_write_hi, mult_mult, mult_divide, mult_signed_divide);
53
--   type a_source_type is (from_reg_source, from_imm10_6);
54
--   type b_source_type is (from_reg_target, from_imm, from_signed_imm);
55
--   type c_source_type is (from_null, from_alu, from_shift, 
56
--      from_mult, from_memory, from_pc, from_imm_shift16,
57
--      from_reg_source_nez, from_reg_source_eqz);
58
--   type pc_source_type is (from_inc4, from_inc8, from_reg_source, 
59
--      from_opcode25_0, from_branch, from_lbranch);
60
begin
61
 
62
control_proc: process(opcode, intr_signal)
63
   variable op, func       : std_logic_vector(5 downto 0);
64
   variable rs, rt, rd     : std_logic_vector(5 downto 0);
65
   variable re, rtx        : std_logic_vector(4 downto 0);
66
   variable imm            : std_logic_vector(15 downto 0);
67
   variable alu_function   : alu_function_type;
68
   variable shift_function : shift_function_type;
69
   variable mult_function  : mult_function_type;
70
   variable a_source       : a_source_type;
71
   variable b_source       : b_source_type;
72
   variable c_source       : c_source_type;
73
   variable pc_source      : pc_source_type;
74
   variable branch_function: branch_function_type;
75
   variable mem_source     : mem_source_type;
76
begin
77
   alu_function := alu_nothing;
78
   shift_function := shift_nothing;
79
   mult_function := mult_nothing;
80
   a_source := a_from_reg_source;
81
   b_source := b_from_reg_target;
82
   c_source := c_from_null;
83
   pc_source := from_inc4;
84
   branch_function := branch_eq;
85
   mem_source := mem_none;
86
   op := opcode(31 downto 26);
87
   rs := '0' & opcode(25 downto 21);
88
   rt := '0' & opcode(20 downto 16);
89
   rtx := opcode(20 downto 16);
90
   rd := '0' & opcode(15 downto 11);
91
   re := opcode(10 downto 6);
92
   func := opcode(5 downto 0);
93
   imm := opcode(15 downto 0);
94
 
95
   case op is
96
   when "000000" =>   --00 SPECIAL
97
      case func is
98
      when "000000" =>   --00 SLL   r[rd]=r[rt]<<re;
99
         a_source := a_from_imm10_6;
100
         c_source := c_from_shift;
101
         shift_function := shift_left_unsigned;
102
      when "000010" =>   --02 SRL   r[rd]=u[rt]>>re;
103
         a_source := a_from_imm10_6;
104
         c_source := c_from_shift;
105
         shift_function := shift_right_unsigned;
106
      when "000011" =>   --03 SRA   r[rd]=r[rt]>>re;
107
         a_source := a_from_imm10_6;
108
         c_source := c_from_shift;
109
         shift_function := shift_right_signed;
110
      when "000100" =>   --04 SLLV  r[rd]=r[rt]<<r[rs];
111
         c_source := c_from_shift;
112
         shift_function := shift_left_unsigned;
113
      when "000110" =>   --06 SRLV  r[rd]=u[rt]>>r[rs];
114
         c_source := c_from_shift;
115
         shift_function := shift_right_unsigned;
116
      when "000111" =>   --07 SRAV  r[rd]=r[rt]>>r[rs];
117
         c_source := c_from_shift;
118
         shift_function := shift_right_signed;
119
      when "001000" =>   --08 JR    s->pc_next=r[rs];
120
         pc_source := from_branch;
121
         alu_function := alu_add;
122
         branch_function := branch_yes;
123
      when "001001" =>   --09 JALR  r[rd]=s->pc_next; s->pc_next=r[rs];
124 6 rhoads
         c_source := c_from_pc_plus4;
125 2 rhoads
         pc_source := from_branch;
126
         alu_function := alu_add;
127
         branch_function := branch_yes;
128
      when "001010" =>   --0a MOVZ  if(!r[rt]) r[rd]=r[rs]; /*IV*/
129
--         c_source := c_from_reg_source_eqz;
130
      when "001011" =>   --0b MOVN  if(r[rt]) r[rd]=r[rs];  /*IV*/
131
--         c_source := from_reg_source_nez;
132
      when "001100" =>   --0c SYSCALL
133
--         if(r[4]==0) printf("0x%8.8lx ",r[5]);
134
      when "001101" =>   --0d BREAK s->wakeup=1;
135
      when "001111" =>   --0f SYNC  s->wakeup=1;
136
      when "010000" =>   --10 MFHI  r[rd]=s->hi;
137
         c_source := c_from_mult;
138
         mult_function := mult_read_hi;
139
      when "010001" =>   --11 FTHI  s->hi=r[rs];
140
         mult_function := mult_write_hi;
141
      when "010010" =>   --12 MFLO  r[rd]=s->lo;
142
         c_source := c_from_mult;
143
         mult_function := mult_read_lo;
144
      when "010011" =>   --13 MTLO  s->lo=r[rs];
145
         mult_function := mult_write_lo;
146
      when "011000" =>   --18 MULT  s->lo=r[rs]*r[rt]; s->hi=0;
147
         mult_function := mult_mult;
148
      when "011001" =>   --19 MULTU s->lo=r[rs]*r[rt]; s->hi=0;
149
         mult_function := mult_mult;
150
      when "011010" =>   --1a DIV   s->lo=r[rs]/r[rt]; s->hi=r[rs]%r[rt];
151
         mult_function := mult_signed_divide;
152
      when "011011" =>   --1b DIVU  s->lo=r[rs]/r[rt]; s->hi=r[rs]%r[rt];
153
         mult_function := mult_divide;
154
      when "100000" =>   --20 ADD   r[rd]=r[rs]+r[rt];
155
         c_source := c_from_alu;
156
         alu_function := alu_add;
157
      when "100001" =>   --21 ADDU  r[rd]=r[rs]+r[rt];
158
         c_source := c_from_alu;
159
         alu_function := alu_add;
160
      when "100010" =>   --22 SUB   r[rd]=r[rs]-r[rt];
161
         c_source := c_from_alu;
162
         alu_function := alu_subtract;
163
      when "100011" =>   --23 SUBU  r[rd]=r[rs]-r[rt];
164
         c_source := c_from_alu;
165
         alu_function := alu_subtract;
166
      when "100100" =>   --24 AND   r[rd]=r[rs]&r[rt];
167
         c_source := c_from_alu;
168
         alu_function := alu_and;
169
      when "100101" =>   --25 OR    r[rd]=r[rs]|r[rt];
170
         c_source := c_from_alu;
171
         alu_function := alu_or;
172
      when "100110" =>   --26 XOR   r[rd]=r[rs]^r[rt];
173
         c_source := c_from_alu;
174
         alu_function := alu_xor;
175
      when "100111" =>   --27 NOR   r[rd]=~(r[rs]|r[rt]);
176
         c_source := c_from_alu;
177
         alu_function := alu_nor;
178
      when "101010" =>   --2a SLT   r[rd]=r[rs]<r[rt];
179
         c_source := c_from_alu;
180
         alu_function := alu_less_than_signed;
181
      when "101011" =>   --2b SLTU  r[rd]=u[rs]<u[rt];
182
         c_source := c_from_alu;
183
         alu_function := alu_less_than;
184
      when "101101" =>   --2d DADDU r[rd]=r[rs]+u[rt];
185
         c_source := c_from_alu;
186
         alu_function := alu_add;
187
      when "110001" =>   --31 TGEU
188
      when "110010" =>   --32 TLT
189
      when "110011" =>   --33 TLTU
190
      when "110100" =>   --34 TEQ 
191
      when "110110" =>   --36 TNE 
192
      when others =>
193
      end case;
194
   when "000001" =>   --00 REGIMM
195
      rt := "000000";
196
      rd := "011111";
197
      a_source := a_from_pc;
198
      b_source := b_from_immX4;
199
      alu_function := alu_add;
200
      pc_source := from_branch;
201
      branch_function := branch_gtz;
202
      --if(test) pc=pc+imm*4
203
      case rtx is
204
      when "10000" =>   --10 BLTZAL  r[31]=s->pc_next; branch=r[rs]<0;
205 6 rhoads
         c_source := c_from_pc_plus4;
206 2 rhoads
         branch_function := branch_ltz;
207
      when "00000" =>   --00 BLTZ    branch=r[rs]<0;
208
         branch_function := branch_ltz;
209
      when "10001" =>   --11 BGEZAL  r[31]=s->pc_next; branch=r[rs]>=0;
210 6 rhoads
         c_source := c_from_pc_plus4;
211 2 rhoads
         branch_function := branch_gez;
212
      when "00001" =>   --01 BGEZ    branch=r[rs]>=0;
213
         branch_function := branch_gez;
214
      when "10010" =>   --12 BLTZALL r[31]=s->pc_next; lbranch=r[rs]<0;
215 6 rhoads
         c_source := c_from_pc_plus4;
216 2 rhoads
         pc_source := from_lbranch;
217
         branch_function := branch_ltz;
218
      when "00010" =>   --02 BLTZL   lbranch=r[rs]<0;
219
         pc_source := from_lbranch;
220
         branch_function := branch_ltz;
221
      when "10011" =>   --13 BGEZALL r[31]=s->pc_next; lbranch=r[rs]>=0;
222 6 rhoads
         c_source := c_from_pc_plus4;
223 2 rhoads
         pc_source := from_lbranch;
224
         branch_function := branch_gez;
225
      when "00011" =>   --03 BGEZL   lbranch=r[rs]>=0;
226
         pc_source := from_lbranch;
227
         branch_function := branch_gez;
228
          when others =>
229
          end case;
230
   when "000011" =>   --03 JAL    r[31]=s->pc_next; s->pc_next=(s->pc&0xf0000000)|target;
231 6 rhoads
      c_source := c_from_pc_plus4;
232 2 rhoads
      rd := "011111";
233
      pc_source := from_opcode25_0;
234
   when "000010" =>   --02 J      s->pc_next=(s->pc&0xf0000000)|target; 
235
      pc_source := from_opcode25_0;
236
   when "000100" =>   --04 BEQ    branch=r[rs]==r[rt];
237
      a_source := a_from_pc;
238
      b_source := b_from_immX4;
239
      alu_function := alu_add;
240
      pc_source := from_branch;
241
      branch_function := branch_eq;
242
   when "000101" =>   --05 BNE    branch=r[rs]!=r[rt];
243
      a_source := a_from_pc;
244
      b_source := b_from_immX4;
245
      alu_function := alu_add;
246
      pc_source := from_branch;
247
      branch_function := branch_ne;
248
   when "000110" =>   --06 BLEZ   branch=r[rs]<=0;
249
      a_source := a_from_pc;
250
      b_source := b_from_immX4;
251
      alu_function := alu_add;
252
      pc_source := from_branch;
253
      branch_function := branch_ltz;
254
   when "000111" =>   --07 BGTZ   branch=r[rs]>0;
255
      a_source := a_from_pc;
256
      b_source := b_from_immX4;
257
      alu_function := alu_add;
258
      pc_source := from_branch;
259
      branch_function := branch_gtz;
260
   when "001000" =>   --08 ADDI   r[rt]=r[rs]+(short)imm;
261
      b_source := b_from_signed_imm;
262
      c_source := c_from_alu;
263
      rd := rt;
264
      alu_function := alu_add;
265
   when "001001" =>   --09 ADDIU  u[rt]=u[rs]+(short)imm;
266
      b_source := b_from_signed_imm;
267
      c_source := c_from_alu;
268
      rd := rt;
269
      alu_function := alu_add;
270
   when "001010" =>   --0a SLTI   r[rt]=r[rs]<(short)imm;
271
      b_source := b_from_signed_imm;
272
      c_source := c_from_alu;
273
      rd := rt;
274
      alu_function := alu_less_than;
275
   when "001011" =>   --0b SLTIU  u[rt]=u[rs]<(unsigned long)(short)imm;
276
      b_source := b_from_imm;
277
      c_source := c_from_alu;
278
      rd := rt;
279
      alu_function := alu_less_than;
280
   when "001100" =>   --0c ANDI   r[rt]=r[rs]&imm;
281
      b_source := b_from_imm;
282
      c_source := c_from_alu;
283
      rd := rt;
284
      alu_function := alu_and;
285
   when "001101" =>   --0d ORI    r[rt]=r[rs]|imm;
286
      b_source := b_from_imm;
287
      c_source := c_from_alu;
288
      rd := rt;
289
      alu_function := alu_or;
290
   when "001110" =>   --0e XORI   r[rt]=r[rs]^imm;
291
      b_source := b_from_imm;
292
      c_source := c_from_alu;
293
      rd := rt;
294
      alu_function := alu_xor;
295
   when "001111" =>   --0f LUI    r[rt]=(imm<<16);
296
      c_source := c_from_imm_shift16;
297
      rd := rt;
298
   when "010000" =>   --10 COP0
299
      alu_function := alu_or;
300
      c_source := c_from_alu;
301
      if opcode(23) = '0' then  --move from CP0
302
         rs := '1' & opcode(15 downto 11);
303
         rt := "000000";
304
         rd := '0' & opcode(20 downto 16);
305
      else                      --move to CP0
306
         rs := "000000";
307
         rd(5) := '1';
308
      end if;
309
   when "010001" =>   --11 COP1
310
   when "010010" =>   --12 COP2
311
   when "010011" =>   --13 COP3
312
   when "010100" =>   --14 BEQL   lbranch=r[rs]==r[rt];
313
      a_source := a_from_pc;
314
      b_source := b_from_immX4;
315
      alu_function := alu_add;
316
      pc_source := from_lbranch;
317
      branch_function := branch_eq;
318
   when "010101" =>   --15 BNEL   lbranch=r[rs]!=r[rt];
319
      a_source := a_from_pc;
320
      b_source := b_from_immX4;
321
      alu_function := alu_add;
322
      pc_source := from_lbranch;
323
      branch_function := branch_ne;
324
   when "010110" =>   --16 BLEZL  lbranch=r[rs]<=0;
325
      a_source := a_from_pc;
326
      b_source := b_from_immX4;
327
      alu_function := alu_add;
328
      pc_source := from_lbranch;
329
      branch_function := branch_lez;
330
   when "010111" =>   --17 BGTZL  lbranch=r[rs]>0;
331
      a_source := a_from_pc;
332
      b_source := b_from_immX4;
333
      alu_function := alu_add;
334
      pc_source := from_lbranch;
335
      branch_function := branch_gtz;
336
   when "100000" =>   --20 LB     r[rt]=*(signed char*)ptr;
337
          a_source := a_from_reg_source;
338
          b_source := b_from_imm;
339
          alu_function := alu_add;
340
          rd := rt;
341
      c_source := c_from_memory;
342
          mem_source := mem_read8s;    --address=(short)imm+r[rs];
343
   when "100001" =>   --21 LH     r[rt]=*(signed short*)ptr;
344
          a_source := a_from_reg_source;
345
          b_source := b_from_imm;
346
          alu_function := alu_add;
347
          rd := rt;
348
      c_source := c_from_memory;
349
          mem_source := mem_read16s;   --address=(short)imm+r[rs];
350
   when "100010" =>   --22 LWL    //fixme
351
   when "100011" =>   --23 LW     r[rt]=*(long*)ptr;
352
          a_source := a_from_reg_source;
353
          b_source := b_from_imm;
354
          alu_function := alu_add;
355
          rd := rt;
356
      c_source := c_from_memory;
357
          mem_source := mem_read32;
358
   when "100100" =>   --24 LBU    r[rt]=*(unsigned char*)ptr;
359
          a_source := a_from_reg_source;
360
          b_source := b_from_imm;
361
          alu_function := alu_add;
362
          rd := rt;
363
      c_source := c_from_memory;
364
          mem_source := mem_read8;    --address=(short)imm+r[rs];
365
   when "100101" =>   --25 LHU    r[rt]=*(unsigned short*)ptr;
366
          a_source := a_from_reg_source;
367
          b_source := b_from_imm;
368
          alu_function := alu_add;
369
          rd := rt;
370
      c_source := c_from_memory;
371
          mem_source := mem_read16;    --address=(short)imm+r[rs];
372
   when "100110" =>   --26 LWR    //fixme
373
   when "101000" =>   --28 SB     *(char*)ptr=(char)r[rt];
374
          a_source := a_from_reg_source;
375
          b_source := b_from_imm;
376
          alu_function := alu_add;
377
          mem_source := mem_write8;   --address=(short)imm+r[rs];
378
   when "101001" =>   --29 SH     *(short*)ptr=(short)r[rt];
379
          a_source := a_from_reg_source;
380
          b_source := b_from_imm;
381
          alu_function := alu_add;
382
          mem_source := mem_write16;
383
   when "101010" =>   --2a SWL    //fixme
384
   when "101011" =>   --2b SW     *(long*)ptr=r[rt];
385
          a_source := a_from_reg_source;
386
          b_source := b_from_imm;
387
          alu_function := alu_add;
388
          mem_source := mem_write32;  --address=(short)imm+r[rs];
389
   when "101110" =>   --2e SWR    //fixme
390
   when "101111" =>   --2f CACHE
391
   when "110000" =>   --30 LL     r[rt]=*(long*)ptr;
392
   when "110001" =>   --31 LWC1 
393
   when "110010" =>   --32 LWC2 
394
   when "110011" =>   --33 LWC3 
395
   when "110101" =>   --35 LDC1 
396
   when "110110" =>   --36 LDC2 
397
   when "110111" =>   --37 LDC3 
398
   when "111000" =>   --38 SC     *(long*)ptr=r[rt]; r[rt]=1;
399
   when "111001" =>   --39 SWC1 
400
   when "111010" =>   --3a SWC2 
401
   when "111011" =>   --3b SWC3 
402
   when "111101" =>   --3d SDC1 
403
   when "111110" =>   --3e SDC2 
404
   when "111111" =>   --3f SDC3 
405
   when others =>
406
   end case;
407
 
408
   if c_source = c_from_null then
409
      rd := "000000";
410
   end if;
411
 
412 7 rhoads
   if pause_in = '1' then
413
      rd := "000000";
414
   end if;
415
 
416 2 rhoads
   if intr_signal = '1' then
417
      rs := "111111";  --interrupt vector
418
      rt := "000000";
419 6 rhoads
      rd := "101110";  --save PC in EPC
420
      alu_function := alu_or;
421
      shift_function := shift_nothing;
422
      mult_function := mult_nothing;
423
      branch_function := branch_yes;
424 2 rhoads
      a_source := a_from_reg_source;
425
      b_source := b_from_reg_target;
426 6 rhoads
      c_source := c_from_pc;
427
      pc_source := from_lbranch;
428
      mem_source := mem_none;
429 2 rhoads
   end if;
430
 
431
   rs_index <= rs;
432
   rt_index <= rt;
433
   rd_index <= rd;
434
   imm_out <= imm;
435
   alu_func <= alu_function;
436
   shift_func <= shift_function;
437
   mult_func <= mult_function;
438
   branch_func <= branch_function;
439
   a_source_out <= a_source;
440
   b_source_out <= b_source;
441
   c_source_out <= c_source;
442
   pc_source_out <= pc_source;
443
   mem_source_out <= mem_source;
444
 
445
end process;
446
 
447
end; --logic
448
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.