Project

General

Profile

Download (15.3 KB) Statistics
| Branch: | Tag: | Revision:
1
---------------------------------------------------------------------
2
-- TITLE: Controller / Opcode Decoder
3
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4
-- DATE CREATED: 2/8/01
5
-- FILENAME: control.vhd
6
-- PROJECT: Plasma CPU core
7
-- COPYRIGHT: Software placed into the public domain by the author.
8
--    Software 'as is' without warranty.  Author liable for nothing.
9
-- NOTE:  MIPS(tm) is a registered trademark of MIPS Technologies.
10
--    MIPS Technologies does not endorse and is not associated with
11
--    this project.
12
-- DESCRIPTION:
13
--    Controls the CPU by decoding the opcode and generating control 
14
--    signals to the rest of the CPU.
15
--    This entity decodes the MIPS(tm) opcode into a 
16
--    Very-Long-Word-Instruction.  
17
--    The 32-bit opcode is converted to a 
18
--       6+6+6+16+4+2+4+3+2+2+3+2+4 = 60 bit VLWI opcode.
19
--    Based on information found in:
20
--       "MIPS RISC Architecture" by Gerry Kane and Joe Heinrich
21
--       and "The Designer's Guide to VHDL" by Peter J. Ashenden
22
---------------------------------------------------------------------
23
library ieee;
24
use ieee.std_logic_1164.all;
25
use work.mlite_pack.all;
26

    
27
entity control is
28
   port(opcode       : in  std_logic_vector(31 downto 0);
29
        intr_signal  : in  std_logic;
30
        rs_index     : out std_logic_vector(5 downto 0);
31
        rt_index     : out std_logic_vector(5 downto 0);
32
        rd_index     : out std_logic_vector(5 downto 0);
33
        imm_out      : out std_logic_vector(15 downto 0);
34
        alu_func     : out alu_function_type;
35
        shift_func   : out shift_function_type;
36
        mult_func    : out mult_function_type;
37
        branch_func  : out branch_function_type;
38
        a_source_out : out a_source_type;
39
        b_source_out : out b_source_type;
40
        c_source_out : out c_source_type;
41
        pc_source_out: out pc_source_type;
42
        mem_source_out:out mem_source_type;
43
        exception_out: out std_logic);
44
end; --entity control
45

    
46

    
47
architecture logic of control is
48
begin
49

    
50
control_proc: process(opcode, intr_signal) 
51
   variable op, func       : std_logic_vector(5 downto 0);
52
   variable rs, rt, rd     : std_logic_vector(5 downto 0);
53
   variable rtx            : std_logic_vector(4 downto 0);
54
   variable imm            : std_logic_vector(15 downto 0);
55
   variable alu_function   : alu_function_type;
56
   variable shift_function : shift_function_type;
57
   variable mult_function  : mult_function_type;
58
   variable a_source       : a_source_type;
59
   variable b_source       : b_source_type;
60
   variable c_source       : c_source_type;
61
   variable pc_source      : pc_source_type;
62
   variable branch_function: branch_function_type;
63
   variable mem_source     : mem_source_type;
64
   variable is_syscall     : std_logic;
65
begin
66
   alu_function := ALU_NOTHING;
67
   shift_function := SHIFT_NOTHING;
68
   mult_function := MULT_NOTHING;
69
   a_source := A_FROM_REG_SOURCE;
70
   b_source := B_FROM_REG_TARGET;
71
   c_source := C_FROM_NULL;
72
   pc_source := FROM_INC4;
73
   branch_function := BRANCH_EQ;
74
   mem_source := MEM_FETCH;
75
   op := opcode(31 downto 26);
76
   rs := '0' & opcode(25 downto 21);
77
   rt := '0' & opcode(20 downto 16);
78
   rtx := opcode(20 downto 16);
79
   rd := '0' & opcode(15 downto 11);
80
   func := opcode(5 downto 0);
81
   imm := opcode(15 downto 0);
82
   is_syscall := '0';
83

    
84
   case op is
85
   when "000000" =>   --SPECIAL
86
      case func is
87
      when "000000" =>   --SLL   r[rd]=r[rt]<<re;
88
         a_source := A_FROM_IMM10_6;
89
         c_source := C_FROM_SHIFT;
90
         shift_function := SHIFT_LEFT_UNSIGNED;
91

    
92
      when "000010" =>   --SRL   r[rd]=u[rt]>>re;
93
         a_source := A_FROM_IMM10_6;
94
         c_source := C_FROM_shift;
95
         shift_function := SHIFT_RIGHT_UNSIGNED;
96

    
97
      when "000011" =>   --SRA   r[rd]=r[rt]>>re;
98
         a_source := A_FROM_IMM10_6;
99
         c_source := C_FROM_SHIFT;
100
         shift_function := SHIFT_RIGHT_SIGNED;
101

    
102
      when "000100" =>   --SLLV  r[rd]=r[rt]<<r[rs];
103
         c_source := C_FROM_SHIFT;
104
         shift_function := SHIFT_LEFT_UNSIGNED;
105

    
106
      when "000110" =>   --SRLV  r[rd]=u[rt]>>r[rs];
107
         c_source := C_FROM_SHIFT;
108
         shift_function := SHIFT_RIGHT_UNSIGNED;
109

    
110
      when "000111" =>   --SRAV  r[rd]=r[rt]>>r[rs];
111
         c_source := C_FROM_SHIFT;
112
         shift_function := SHIFT_RIGHT_SIGNED;
113

    
114
      when "001000" =>   --JR    s->pc_next=r[rs];
115
         pc_source := FROM_BRANCH;
116
         alu_function := ALU_ADD;
117
         branch_function := BRANCH_YES;
118

    
119
      when "001001" =>   --JALR  r[rd]=s->pc_next; s->pc_next=r[rs];
120
         c_source := C_FROM_PC_PLUS4;
121
         pc_source := FROM_BRANCH;
122
         alu_function := ALU_ADD;
123
         branch_function := BRANCH_YES;
124

    
125
      --when "001010" =>   --MOVZ  if(!r[rt]) r[rd]=r[rs]; /*IV*/
126
      --when "001011" =>   --MOVN  if(r[rt]) r[rd]=r[rs];  /*IV*/
127

    
128
      when "001100" =>   --SYSCALL
129
         is_syscall := '1';
130

    
131
      when "001101" =>   --BREAK s->wakeup=1;
132
         is_syscall := '1';
133

    
134
      --when "001111" =>   --SYNC  s->wakeup=1;
135

    
136
      when "010000" =>   --MFHI  r[rd]=s->hi;
137
         c_source := C_FROM_MULT;
138
         mult_function := MULT_READ_HI;
139

    
140
      when "010001" =>   --MTHI  s->hi=r[rs];
141
         mult_function := MULT_WRITE_HI;
142

    
143
      when "010010" =>   --MFLO  r[rd]=s->lo;
144
         c_source := C_FROM_MULT;
145
         mult_function := MULT_READ_LO;
146

    
147
      when "010011" =>   --MTLO  s->lo=r[rs];
148
         mult_function := MULT_WRITE_LO;
149

    
150
      when "011000" =>   --MULT  s->lo=r[rs]*r[rt]; s->hi=0;
151
         mult_function := MULT_SIGNED_MULT;
152

    
153
      when "011001" =>   --MULTU s->lo=r[rs]*r[rt]; s->hi=0;
154
         mult_function := MULT_MULT;
155

    
156
      when "011010" =>   --DIV   s->lo=r[rs]/r[rt]; s->hi=r[rs]%r[rt];
157
         mult_function := MULT_SIGNED_DIVIDE;
158

    
159
      when "011011" =>   --DIVU  s->lo=r[rs]/r[rt]; s->hi=r[rs]%r[rt];
160
         mult_function := MULT_DIVIDE;
161

    
162
      when "100000" =>   --ADD   r[rd]=r[rs]+r[rt];
163
         c_source := C_FROM_ALU;
164
         alu_function := ALU_ADD;
165

    
166
      when "100001" =>   --ADDU  r[rd]=r[rs]+r[rt];
167
         c_source := C_FROM_ALU;
168
         alu_function := ALU_ADD;
169

    
170
      when "100010" =>   --SUB   r[rd]=r[rs]-r[rt];
171
         c_source := C_FROM_ALU;
172
         alu_function := ALU_SUBTRACT;
173

    
174
      when "100011" =>   --SUBU  r[rd]=r[rs]-r[rt];
175
         c_source := C_FROM_ALU;
176
         alu_function := ALU_SUBTRACT;
177

    
178
      when "100100" =>   --AND   r[rd]=r[rs]&r[rt];
179
         c_source := C_FROM_ALU;
180
         alu_function := ALU_AND;
181

    
182
      when "100101" =>   --OR    r[rd]=r[rs]|r[rt];
183
         c_source := C_FROM_ALU;
184
         alu_function := ALU_OR;
185

    
186
      when "100110" =>   --XOR   r[rd]=r[rs]^r[rt];
187
         c_source := C_FROM_ALU;
188
         alu_function := ALU_XOR;
189

    
190
      when "100111" =>   --NOR   r[rd]=~(r[rs]|r[rt]);
191
         c_source := C_FROM_ALU;
192
         alu_function := ALU_NOR;
193

    
194
      when "101010" =>   --SLT   r[rd]=r[rs]<r[rt];
195
         c_source := C_FROM_ALU;
196
         alu_function := ALU_LESS_THAN_SIGNED;
197

    
198
      when "101011" =>   --SLTU  r[rd]=u[rs]<u[rt];
199
         c_source := C_FROM_ALU;
200
         alu_function := ALU_LESS_THAN;
201

    
202
      when "101101" =>   --DADDU r[rd]=r[rs]+u[rt];
203
         c_source := C_FROM_ALU;
204
         alu_function := ALU_ADD;
205

    
206
      --when "110001" =>   --TGEU
207
      --when "110010" =>   --TLT
208
      --when "110011" =>   --TLTU
209
      --when "110100" =>   --TEQ 
210
      --when "110110" =>   --TNE 
211
      when others =>
212
      end case;
213

    
214
   when "000001" =>   --REGIMM
215
      rt := "000000";
216
      rd := "011111";
217
      a_source := A_FROM_PC;
218
      b_source := B_FROM_IMMX4;
219
      alu_function := ALU_ADD;
220
      pc_source := FROM_BRANCH;
221
      branch_function := BRANCH_GTZ;
222
      --if(test) pc=pc+imm*4
223

    
224
      case rtx is
225
      when "10000" =>   --BLTZAL  r[31]=s->pc_next; branch=r[rs]<0;
226
         c_source := C_FROM_PC_PLUS4;
227
         branch_function := BRANCH_LTZ;
228

    
229
      when "00000" =>   --BLTZ    branch=r[rs]<0;
230
         branch_function := BRANCH_LTZ;
231

    
232
      when "10001" =>   --BGEZAL  r[31]=s->pc_next; branch=r[rs]>=0;
233
         c_source := C_FROM_PC_PLUS4;
234
         branch_function := BRANCH_GEZ;
235

    
236
      when "00001" =>   --BGEZ    branch=r[rs]>=0;
237
         branch_function := BRANCH_GEZ;
238

    
239
      --when "10010" =>   --BLTZALL r[31]=s->pc_next; lbranch=r[rs]<0;
240
      --when "00010" =>   --BLTZL   lbranch=r[rs]<0;
241
      --when "10011" =>   --BGEZALL r[31]=s->pc_next; lbranch=r[rs]>=0;
242
      --when "00011" =>   --BGEZL   lbranch=r[rs]>=0;
243

    
244
      when others =>
245
      end case;
246

    
247
   when "000011" =>   --JAL    r[31]=s->pc_next; s->pc_next=(s->pc&0xf0000000)|target;
248
      c_source := C_FROM_PC_PLUS4;
249
      rd := "011111";
250
      pc_source := FROM_OPCODE25_0;
251

    
252
   when "000010" =>   --J      s->pc_next=(s->pc&0xf0000000)|target; 
253
      pc_source := FROM_OPCODE25_0;
254

    
255
   when "000100" =>   --BEQ    branch=r[rs]==r[rt];
256
      a_source := A_FROM_PC;
257
      b_source := B_FROM_IMMX4;
258
      alu_function := ALU_ADD;
259
      pc_source := FROM_BRANCH;
260
      branch_function := BRANCH_EQ;
261

    
262
   when "000101" =>   --BNE    branch=r[rs]!=r[rt];
263
      a_source := A_FROM_PC;
264
      b_source := B_FROM_IMMX4;
265
      alu_function := ALU_ADD;
266
      pc_source := FROM_BRANCH;
267
      branch_function := BRANCH_NE;
268

    
269
   when "000110" =>   --BLEZ   branch=r[rs]<=0;
270
      a_source := A_FROM_PC;
271
      b_source := b_FROM_IMMX4;
272
      alu_function := ALU_ADD;
273
      pc_source := FROM_BRANCH;
274
      branch_function := BRANCH_LEZ;
275

    
276
   when "000111" =>   --BGTZ   branch=r[rs]>0;
277
      a_source := A_FROM_PC;
278
      b_source := B_FROM_IMMX4;
279
      alu_function := ALU_ADD;
280
      pc_source := FROM_BRANCH;
281
      branch_function := BRANCH_GTZ;
282

    
283
   when "001000" =>   --ADDI   r[rt]=r[rs]+(short)imm;
284
      b_source := B_FROM_SIGNED_IMM;
285
      c_source := C_FROM_ALU;
286
      rd := rt;
287
      alu_function := ALU_ADD;
288

    
289
   when "001001" =>   --ADDIU  u[rt]=u[rs]+(short)imm;
290
      b_source := B_FROM_SIGNED_IMM;
291
      c_source := C_FROM_ALU;
292
      rd := rt;
293
      alu_function := ALU_ADD;
294

    
295
   when "001010" =>   --SLTI   r[rt]=r[rs]<(short)imm;
296
      b_source := B_FROM_SIGNED_IMM;
297
      c_source := C_FROM_ALU;
298
      rd := rt;
299
      alu_function := ALU_LESS_THAN_SIGNED;
300

    
301
   when "001011" =>   --SLTIU  u[rt]=u[rs]<(unsigned long)(short)imm;
302
      b_source := B_FROM_SIGNED_IMM;
303
      c_source := C_FROM_ALU;
304
      rd := rt;
305
      alu_function := ALU_LESS_THAN;
306

    
307
   when "001100" =>   --ANDI   r[rt]=r[rs]&imm;
308
      b_source := B_FROM_IMM;
309
      c_source := C_FROM_ALU;
310
      rd := rt;
311
      alu_function := ALU_AND;
312

    
313
   when "001101" =>   --ORI    r[rt]=r[rs]|imm;
314
      b_source := B_FROM_IMM;
315
      c_source := C_FROM_ALU;
316
      rd := rt;
317
      alu_function := ALU_OR;
318

    
319
   when "001110" =>   --XORI   r[rt]=r[rs]^imm;
320
      b_source := B_FROM_IMM;
321
      c_source := C_FROM_ALU;
322
      rd := rt;
323
      alu_function := ALU_XOR;
324

    
325
   when "001111" =>   --LUI    r[rt]=(imm<<16);
326
      c_source := C_FROM_IMM_SHIFT16;
327
      rd := rt;
328

    
329
   when "010000" =>   --COP0
330
      alu_function := ALU_OR;
331
      c_source := C_FROM_ALU;
332
      if opcode(23) = '0' then  --move from CP0
333
         rs := '1' & opcode(15 downto 11);
334
         rt := "000000";
335
         rd := '0' & opcode(20 downto 16);
336
      else                      --move to CP0
337
         rs := "000000";
338
         rd(5) := '1';
339
         pc_source := FROM_BRANCH;   --delay possible interrupt
340
         branch_function := BRANCH_NO;
341
      end if;
342

    
343
   --when "010001" =>   --COP1
344
   --when "010010" =>   --COP2
345
   --when "010011" =>   --COP3
346
   --when "010100" =>   --BEQL   lbranch=r[rs]==r[rt];
347
   --when "010101" =>   --BNEL   lbranch=r[rs]!=r[rt];
348
   --when "010110" =>   --BLEZL  lbranch=r[rs]<=0;
349
   --when "010111" =>   --BGTZL  lbranch=r[rs]>0;
350

    
351
   when "100000" =>   --LB     r[rt]=*(signed char*)ptr;
352
      a_source := A_FROM_REG_SOURCE;
353
      b_source := B_FROM_SIGNED_IMM;
354
      alu_function := ALU_ADD;
355
      rd := rt;
356
      c_source := C_FROM_MEMORY;
357
      mem_source := MEM_READ8S;    --address=(short)imm+r[rs];
358

    
359
   when "100001" =>   --LH     r[rt]=*(signed short*)ptr;
360
      a_source := A_FROM_REG_SOURCE;
361
      b_source := B_FROM_SIGNED_IMM;
362
      alu_function := ALU_ADD;
363
      rd := rt;
364
      c_source := C_FROM_MEMORY;
365
      mem_source := MEM_READ16S;   --address=(short)imm+r[rs];
366

    
367
   when "100010" =>   --LWL    //Not Implemented
368
      a_source := A_FROM_REG_SOURCE;
369
      b_source := B_FROM_SIGNED_IMM;
370
      alu_function := ALU_ADD;
371
      rd := rt;
372
      c_source := C_FROM_MEMORY;
373
      mem_source := MEM_READ32;
374

    
375
   when "100011" =>   --LW     r[rt]=*(long*)ptr;
376
      a_source := A_FROM_REG_SOURCE;
377
      b_source := B_FROM_SIGNED_IMM;
378
      alu_function := ALU_ADD;
379
      rd := rt;
380
      c_source := C_FROM_MEMORY;
381
      mem_source := MEM_READ32;
382

    
383
   when "100100" =>   --LBU    r[rt]=*(unsigned char*)ptr;
384
      a_source := A_FROM_REG_SOURCE;
385
      b_source := B_FROM_SIGNED_IMM;
386
      alu_function := ALU_ADD;
387
      rd := rt;
388
      c_source := C_FROM_MEMORY;
389
      mem_source := MEM_READ8;    --address=(short)imm+r[rs];
390

    
391
   when "100101" =>   --LHU    r[rt]=*(unsigned short*)ptr;
392
      a_source := A_FROM_REG_SOURCE;
393
      b_source := B_FROM_SIGNED_IMM;
394
      alu_function := ALU_ADD;
395
      rd := rt;
396
      c_source := C_FROM_MEMORY;
397
      mem_source := MEM_READ16;    --address=(short)imm+r[rs];
398

    
399
   --when "100110" =>   --LWR    //Not Implemented
400

    
401
   when "101000" =>   --SB     *(char*)ptr=(char)r[rt];
402
      a_source := A_FROM_REG_SOURCE;
403
      b_source := B_FROM_SIGNED_IMM;
404
      alu_function := ALU_ADD;
405
      mem_source := MEM_WRITE8;   --address=(short)imm+r[rs];
406

    
407
   when "101001" =>   --SH     *(short*)ptr=(short)r[rt];
408
      a_source := A_FROM_REG_SOURCE;
409
      b_source := B_FROM_SIGNED_IMM;
410
      alu_function := ALU_ADD;
411
      mem_source := MEM_WRITE16;
412

    
413
   when "101010" =>   --SWL    //Not Implemented
414
      a_source := A_FROM_REG_SOURCE;
415
      b_source := B_FROM_SIGNED_IMM;
416
      alu_function := ALU_ADD;
417
      mem_source := MEM_WRITE32;  --address=(short)imm+r[rs];
418

    
419
   when "101011" =>   --SW     *(long*)ptr=r[rt];
420
      a_source := A_FROM_REG_SOURCE;
421
      b_source := B_FROM_SIGNED_IMM;
422
      alu_function := ALU_ADD;
423
      mem_source := MEM_WRITE32;  --address=(short)imm+r[rs];
424

    
425
   --when "101110" =>   --SWR    //Not Implemented
426
   --when "101111" =>   --CACHE
427
   --when "110000" =>   --LL     r[rt]=*(long*)ptr;
428
   --when "110001" =>   --LWC1 
429
   --when "110010" =>   --LWC2 
430
   --when "110011" =>   --LWC3 
431
   --when "110101" =>   --LDC1 
432
   --when "110110" =>   --LDC2 
433
   --when "110111" =>   --LDC3 
434
   --when "111000" =>   --SC     *(long*)ptr=r[rt]; r[rt]=1;
435
   --when "111001" =>   --SWC1 
436
   --when "111010" =>   --SWC2 
437
   --when "111011" =>   --SWC3 
438
   --when "111101" =>   --SDC1 
439
   --when "111110" =>   --SDC2 
440
   --when "111111" =>   --SDC3 
441
   when others =>
442
   end case;
443

    
444
   if c_source = C_FROM_NULL then
445
      rd := "000000";
446
   end if;
447

    
448
   if intr_signal = '1' or is_syscall = '1' then
449
      rs := "111111";  --interrupt vector
450
      rt := "000000";
451
      rd := "101110";  --save PC in EPC
452
      alu_function := ALU_OR;
453
      shift_function := SHIFT_NOTHING;
454
      mult_function := MULT_NOTHING;
455
      branch_function := BRANCH_YES;
456
      a_source := A_FROM_REG_SOURCE;
457
      b_source := B_FROM_REG_TARGET;
458
      c_source := C_FROM_PC;
459
      pc_source := FROM_LBRANCH;
460
      mem_source := MEM_FETCH;
461
      exception_out <= '1';
462
   else
463
      exception_out <= '0';
464
   end if;
465

    
466
   rs_index <= rs;
467
   rt_index <= rt;
468
   rd_index <= rd;
469
   imm_out <= imm;
470
   alu_func <= alu_function;
471
   shift_func <= shift_function;
472
   mult_func <= mult_function;
473
   branch_func <= branch_function;
474
   a_source_out <= a_source;
475
   b_source_out <= b_source;
476
   c_source_out <= c_source;
477
   pc_source_out <= pc_source;
478
   mem_source_out <= mem_source;
479

    
480
end process;
481

    
482
end; --logic
483

    
(8-8/16)