Root/plasma/logic/control.vhd

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---------------------------------------------------------------------
23library ieee;
24use ieee.std_logic_1164.all;
25use work.mlite_pack.all;
26
27entity 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);
44end; --entity control
45
46architecture logic of control is
47begin
48
49control_proc: process(opcode, intr_signal)
50   variable op, func : std_logic_vector(5 downto 0);
51   variable rs, rt, rd : std_logic_vector(5 downto 0);
52   variable rtx : std_logic_vector(4 downto 0);
53   variable imm : std_logic_vector(15 downto 0);
54   variable alu_function : alu_function_type;
55   variable shift_function : shift_function_type;
56   variable mult_function : mult_function_type;
57   variable a_source : a_source_type;
58   variable b_source : b_source_type;
59   variable c_source : c_source_type;
60   variable pc_source : pc_source_type;
61   variable branch_function: branch_function_type;
62   variable mem_source : mem_source_type;
63   variable is_syscall : std_logic;
64begin
65   alu_function := ALU_NOTHING;
66   shift_function := SHIFT_NOTHING;
67   mult_function := MULT_NOTHING;
68   a_source := A_FROM_REG_SOURCE;
69   b_source := B_FROM_REG_TARGET;
70   c_source := C_FROM_NULL;
71   pc_source := FROM_INC4;
72   branch_function := BRANCH_EQ;
73   mem_source := MEM_FETCH;
74   op := opcode(31 downto 26);
75   rs := '0' & opcode(25 downto 21);
76   rt := '0' & opcode(20 downto 16);
77   rtx := opcode(20 downto 16);
78   rd := '0' & opcode(15 downto 11);
79   func := opcode(5 downto 0);
80   imm := opcode(15 downto 0);
81   is_syscall := '0';
82
83   case op is
84   when "000000" => --SPECIAL
85      case func is
86      when "000000" => --SLL r[rd]=r[rt]<<re;
87         a_source := A_FROM_IMM10_6;
88         c_source := C_FROM_SHIFT;
89         shift_function := SHIFT_LEFT_UNSIGNED;
90
91      when "000010" => --SRL r[rd]=u[rt]>>re;
92         a_source := A_FROM_IMM10_6;
93         c_source := C_FROM_shift;
94         shift_function := SHIFT_RIGHT_UNSIGNED;
95
96      when "000011" => --SRA r[rd]=r[rt]>>re;
97         a_source := A_FROM_IMM10_6;
98         c_source := C_FROM_SHIFT;
99         shift_function := SHIFT_RIGHT_SIGNED;
100
101      when "000100" => --SLLV r[rd]=r[rt]<<r[rs];
102         c_source := C_FROM_SHIFT;
103         shift_function := SHIFT_LEFT_UNSIGNED;
104
105      when "000110" => --SRLV r[rd]=u[rt]>>r[rs];
106         c_source := C_FROM_SHIFT;
107         shift_function := SHIFT_RIGHT_UNSIGNED;
108
109      when "000111" => --SRAV r[rd]=r[rt]>>r[rs];
110         c_source := C_FROM_SHIFT;
111         shift_function := SHIFT_RIGHT_SIGNED;
112
113      when "001000" => --JR s->pc_next=r[rs];
114         pc_source := FROM_BRANCH;
115         alu_function := ALU_ADD;
116         branch_function := BRANCH_YES;
117
118      when "001001" => --JALR r[rd]=s->pc_next; s->pc_next=r[rs];
119         c_source := C_FROM_PC_PLUS4;
120         pc_source := FROM_BRANCH;
121         alu_function := ALU_ADD;
122         branch_function := BRANCH_YES;
123
124      --when "001010" => --MOVZ if(!r[rt]) r[rd]=r[rs]; /*IV*/
125      --when "001011" => --MOVN if(r[rt]) r[rd]=r[rs]; /*IV*/
126
127      when "001100" => --SYSCALL
128         is_syscall := '1';
129
130      when "001101" => --BREAK s->wakeup=1;
131         is_syscall := '1';
132
133      --when "001111" => --SYNC s->wakeup=1;
134
135      when "010000" => --MFHI r[rd]=s->hi;
136         c_source := C_FROM_MULT;
137         mult_function := MULT_READ_HI;
138
139      when "010001" => --MTHI s->hi=r[rs];
140         mult_function := MULT_WRITE_HI;
141
142      when "010010" => --MFLO r[rd]=s->lo;
143         c_source := C_FROM_MULT;
144         mult_function := MULT_READ_LO;
145
146      when "010011" => --MTLO s->lo=r[rs];
147         mult_function := MULT_WRITE_LO;
148
149      when "011000" => --MULT s->lo=r[rs]*r[rt]; s->hi=0;
150         mult_function := MULT_SIGNED_MULT;
151
152      when "011001" => --MULTU s->lo=r[rs]*r[rt]; s->hi=0;
153         mult_function := MULT_MULT;
154
155      when "011010" => --DIV s->lo=r[rs]/r[rt]; s->hi=r[rs]%r[rt];
156         mult_function := MULT_SIGNED_DIVIDE;
157
158      when "011011" => --DIVU s->lo=r[rs]/r[rt]; s->hi=r[rs]%r[rt];
159         mult_function := MULT_DIVIDE;
160
161      when "100000" => --ADD r[rd]=r[rs]+r[rt];
162         c_source := C_FROM_ALU;
163         alu_function := ALU_ADD;
164
165      when "100001" => --ADDU r[rd]=r[rs]+r[rt];
166         c_source := C_FROM_ALU;
167         alu_function := ALU_ADD;
168
169      when "100010" => --SUB r[rd]=r[rs]-r[rt];
170         c_source := C_FROM_ALU;
171         alu_function := ALU_SUBTRACT;
172
173      when "100011" => --SUBU r[rd]=r[rs]-r[rt];
174         c_source := C_FROM_ALU;
175         alu_function := ALU_SUBTRACT;
176
177      when "100100" => --AND r[rd]=r[rs]&r[rt];
178         c_source := C_FROM_ALU;
179         alu_function := ALU_AND;
180
181      when "100101" => --OR r[rd]=r[rs]|r[rt];
182         c_source := C_FROM_ALU;
183         alu_function := ALU_OR;
184
185      when "100110" => --XOR r[rd]=r[rs]^r[rt];
186         c_source := C_FROM_ALU;
187         alu_function := ALU_XOR;
188
189      when "100111" => --NOR r[rd]=~(r[rs]|r[rt]);
190         c_source := C_FROM_ALU;
191         alu_function := ALU_NOR;
192
193      when "101010" => --SLT r[rd]=r[rs]<r[rt];
194         c_source := C_FROM_ALU;
195         alu_function := ALU_LESS_THAN_SIGNED;
196
197      when "101011" => --SLTU r[rd]=u[rs]<u[rt];
198         c_source := C_FROM_ALU;
199         alu_function := ALU_LESS_THAN;
200
201      when "101101" => --DADDU r[rd]=r[rs]+u[rt];
202         c_source := C_FROM_ALU;
203         alu_function := ALU_ADD;
204
205      --when "110001" => --TGEU
206      --when "110010" => --TLT
207      --when "110011" => --TLTU
208      --when "110100" => --TEQ
209      --when "110110" => --TNE
210      when others =>
211      end case;
212
213   when "000001" => --REGIMM
214      rt := "000000";
215      rd := "011111";
216      a_source := A_FROM_PC;
217      b_source := B_FROM_IMMX4;
218      alu_function := ALU_ADD;
219      pc_source := FROM_BRANCH;
220      branch_function := BRANCH_GTZ;
221      --if(test) pc=pc+imm*4
222
223      case rtx is
224      when "10000" => --BLTZAL r[31]=s->pc_next; branch=r[rs]<0;
225         c_source := C_FROM_PC_PLUS4;
226         branch_function := BRANCH_LTZ;
227
228      when "00000" => --BLTZ branch=r[rs]<0;
229         branch_function := BRANCH_LTZ;
230
231      when "10001" => --BGEZAL r[31]=s->pc_next; branch=r[rs]>=0;
232         c_source := C_FROM_PC_PLUS4;
233         branch_function := BRANCH_GEZ;
234
235      when "00001" => --BGEZ branch=r[rs]>=0;
236         branch_function := BRANCH_GEZ;
237
238      --when "10010" => --BLTZALL r[31]=s->pc_next; lbranch=r[rs]<0;
239      --when "00010" => --BLTZL lbranch=r[rs]<0;
240      --when "10011" => --BGEZALL r[31]=s->pc_next; lbranch=r[rs]>=0;
241      --when "00011" => --BGEZL lbranch=r[rs]>=0;
242
243      when others =>
244      end case;
245
246   when "000011" => --JAL r[31]=s->pc_next; s->pc_next=(s->pc&0xf0000000)|target;
247      c_source := C_FROM_PC_PLUS4;
248      rd := "011111";
249      pc_source := FROM_OPCODE25_0;
250
251   when "000010" => --J s->pc_next=(s->pc&0xf0000000)|target;
252      pc_source := FROM_OPCODE25_0;
253
254   when "000100" => --BEQ branch=r[rs]==r[rt];
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_EQ;
260
261   when "000101" => --BNE branch=r[rs]!=r[rt];
262      a_source := A_FROM_PC;
263      b_source := B_FROM_IMMX4;
264      alu_function := ALU_ADD;
265      pc_source := FROM_BRANCH;
266      branch_function := BRANCH_NE;
267
268   when "000110" => --BLEZ branch=r[rs]<=0;
269      a_source := A_FROM_PC;
270      b_source := b_FROM_IMMX4;
271      alu_function := ALU_ADD;
272      pc_source := FROM_BRANCH;
273      branch_function := BRANCH_LEZ;
274
275   when "000111" => --BGTZ branch=r[rs]>0;
276      a_source := A_FROM_PC;
277      b_source := B_FROM_IMMX4;
278      alu_function := ALU_ADD;
279      pc_source := FROM_BRANCH;
280      branch_function := BRANCH_GTZ;
281
282   when "001000" => --ADDI r[rt]=r[rs]+(short)imm;
283      b_source := B_FROM_SIGNED_IMM;
284      c_source := C_FROM_ALU;
285      rd := rt;
286      alu_function := ALU_ADD;
287
288   when "001001" => --ADDIU u[rt]=u[rs]+(short)imm;
289      b_source := B_FROM_SIGNED_IMM;
290      c_source := C_FROM_ALU;
291      rd := rt;
292      alu_function := ALU_ADD;
293
294   when "001010" => --SLTI r[rt]=r[rs]<(short)imm;
295      b_source := B_FROM_SIGNED_IMM;
296      c_source := C_FROM_ALU;
297      rd := rt;
298      alu_function := ALU_LESS_THAN_SIGNED;
299
300   when "001011" => --SLTIU u[rt]=u[rs]<(unsigned long)(short)imm;
301      b_source := B_FROM_SIGNED_IMM;
302      c_source := C_FROM_ALU;
303      rd := rt;
304      alu_function := ALU_LESS_THAN;
305
306   when "001100" => --ANDI r[rt]=r[rs]&imm;
307      b_source := B_FROM_IMM;
308      c_source := C_FROM_ALU;
309      rd := rt;
310      alu_function := ALU_AND;
311
312   when "001101" => --ORI r[rt]=r[rs]|imm;
313      b_source := B_FROM_IMM;
314      c_source := C_FROM_ALU;
315      rd := rt;
316      alu_function := ALU_OR;
317
318   when "001110" => --XORI r[rt]=r[rs]^imm;
319      b_source := B_FROM_IMM;
320      c_source := C_FROM_ALU;
321      rd := rt;
322      alu_function := ALU_XOR;
323
324   when "001111" => --LUI r[rt]=(imm<<16);
325      c_source := C_FROM_IMM_SHIFT16;
326      rd := rt;
327
328   when "010000" => --COP0
329      alu_function := ALU_OR;
330      c_source := C_FROM_ALU;
331      if opcode(23) = '0' then --move from CP0
332         rs := '1' & opcode(15 downto 11);
333         rt := "000000";
334         rd := '0' & opcode(20 downto 16);
335      else --move to CP0
336         rs := "000000";
337         rd(5) := '1';
338         pc_source := FROM_BRANCH; --delay possible interrupt
339         branch_function := BRANCH_NO;
340      end if;
341
342   --when "010001" => --COP1
343   --when "010010" => --COP2
344   --when "010011" => --COP3
345   --when "010100" => --BEQL lbranch=r[rs]==r[rt];
346   --when "010101" => --BNEL lbranch=r[rs]!=r[rt];
347   --when "010110" => --BLEZL lbranch=r[rs]<=0;
348   --when "010111" => --BGTZL lbranch=r[rs]>0;
349
350   when "100000" => --LB r[rt]=*(signed char*)ptr;
351      a_source := A_FROM_REG_SOURCE;
352      b_source := B_FROM_SIGNED_IMM;
353      alu_function := ALU_ADD;
354      rd := rt;
355      c_source := C_FROM_MEMORY;
356      mem_source := MEM_READ8S; --address=(short)imm+r[rs];
357
358   when "100001" => --LH r[rt]=*(signed short*)ptr;
359      a_source := A_FROM_REG_SOURCE;
360      b_source := B_FROM_SIGNED_IMM;
361      alu_function := ALU_ADD;
362      rd := rt;
363      c_source := C_FROM_MEMORY;
364      mem_source := MEM_READ16S; --address=(short)imm+r[rs];
365
366   when "100010" => --LWL //Not Implemented
367      a_source := A_FROM_REG_SOURCE;
368      b_source := B_FROM_SIGNED_IMM;
369      alu_function := ALU_ADD;
370      rd := rt;
371      c_source := C_FROM_MEMORY;
372      mem_source := MEM_READ32;
373
374   when "100011" => --LW r[rt]=*(long*)ptr;
375      a_source := A_FROM_REG_SOURCE;
376      b_source := B_FROM_SIGNED_IMM;
377      alu_function := ALU_ADD;
378      rd := rt;
379      c_source := C_FROM_MEMORY;
380      mem_source := MEM_READ32;
381
382   when "100100" => --LBU r[rt]=*(unsigned char*)ptr;
383      a_source := A_FROM_REG_SOURCE;
384      b_source := B_FROM_SIGNED_IMM;
385      alu_function := ALU_ADD;
386      rd := rt;
387      c_source := C_FROM_MEMORY;
388      mem_source := MEM_READ8; --address=(short)imm+r[rs];
389
390   when "100101" => --LHU r[rt]=*(unsigned short*)ptr;
391      a_source := A_FROM_REG_SOURCE;
392      b_source := B_FROM_SIGNED_IMM;
393      alu_function := ALU_ADD;
394      rd := rt;
395      c_source := C_FROM_MEMORY;
396      mem_source := MEM_READ16; --address=(short)imm+r[rs];
397
398   --when "100110" => --LWR //Not Implemented
399
400   when "101000" => --SB *(char*)ptr=(char)r[rt];
401      a_source := A_FROM_REG_SOURCE;
402      b_source := B_FROM_SIGNED_IMM;
403      alu_function := ALU_ADD;
404      mem_source := MEM_WRITE8; --address=(short)imm+r[rs];
405
406   when "101001" => --SH *(short*)ptr=(short)r[rt];
407      a_source := A_FROM_REG_SOURCE;
408      b_source := B_FROM_SIGNED_IMM;
409      alu_function := ALU_ADD;
410      mem_source := MEM_WRITE16;
411
412   when "101010" => --SWL //Not Implemented
413      a_source := A_FROM_REG_SOURCE;
414      b_source := B_FROM_SIGNED_IMM;
415      alu_function := ALU_ADD;
416      mem_source := MEM_WRITE32; --address=(short)imm+r[rs];
417
418   when "101011" => --SW *(long*)ptr=r[rt];
419      a_source := A_FROM_REG_SOURCE;
420      b_source := B_FROM_SIGNED_IMM;
421      alu_function := ALU_ADD;
422      mem_source := MEM_WRITE32; --address=(short)imm+r[rs];
423
424   --when "101110" => --SWR //Not Implemented
425   --when "101111" => --CACHE
426   --when "110000" => --LL r[rt]=*(long*)ptr;
427   --when "110001" => --LWC1
428   --when "110010" => --LWC2
429   --when "110011" => --LWC3
430   --when "110101" => --LDC1
431   --when "110110" => --LDC2
432   --when "110111" => --LDC3
433   --when "111000" => --SC *(long*)ptr=r[rt]; r[rt]=1;
434   --when "111001" => --SWC1
435   --when "111010" => --SWC2
436   --when "111011" => --SWC3
437   --when "111101" => --SDC1
438   --when "111110" => --SDC2
439   --when "111111" => --SDC3
440   when others =>
441   end case;
442
443   if c_source = C_FROM_NULL then
444      rd := "000000";
445   end if;
446
447   if intr_signal = '1' or is_syscall = '1' then
448      rs := "111111"; --interrupt vector
449      rt := "000000";
450      rd := "101110"; --save PC in EPC
451      alu_function := ALU_OR;
452      shift_function := SHIFT_NOTHING;
453      mult_function := MULT_NOTHING;
454      branch_function := BRANCH_YES;
455      a_source := A_FROM_REG_SOURCE;
456      b_source := B_FROM_REG_TARGET;
457      c_source := C_FROM_PC;
458      pc_source := FROM_LBRANCH;
459      mem_source := MEM_FETCH;
460      exception_out <= '1';
461   else
462      exception_out <= '0';
463   end if;
464
465   rs_index <= rs;
466   rt_index <= rt;
467   rd_index <= rd;
468   imm_out <= imm;
469   alu_func <= alu_function;
470   shift_func <= shift_function;
471   mult_func <= mult_function;
472   branch_func <= branch_function;
473   a_source_out <= a_source;
474   b_source_out <= b_source;
475   c_source_out <= c_source;
476   pc_source_out <= pc_source;
477   mem_source_out <= mem_source;
478
479end process;
480
481end; --logic
482
483

Archive Download this file

Branches:
master



interactive