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

Subversion Repositories cpu_lecture

[/] [cpu_lecture/] [trunk/] [src/] [opc_deco.vhd] - Blame information for rev 2

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

Line No. Rev Author Line
1 2 jsauermann
-------------------------------------------------------------------------------
2
-- 
3
-- Copyright (C) 2009, 2010 Dr. Juergen Sauermann
4
-- 
5
--  This code is free software: you can redistribute it and/or modify
6
--  it under the terms of the GNU General Public License as published by
7
--  the Free Software Foundation, either version 3 of the License, or
8
--  (at your option) any later version.
9
--
10
--  This code is distributed in the hope that it will be useful,
11
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
--  GNU General Public License for more details.
14
--
15
--  You should have received a copy of the GNU General Public License
16
--  along with this code (see the file named COPYING).
17
--  If not, see http://www.gnu.org/licenses/.
18
--
19
-------------------------------------------------------------------------------
20
-------------------------------------------------------------------------------
21
--
22
-- Module Name:    opc_deco - Behavioral 
23
-- Create Date:    16:05:16 10/29/2009 
24
-- Description:    the opcode decoder of a CPU.
25
--
26
-------------------------------------------------------------------------------
27
--
28
library IEEE;
29
use IEEE.STD_LOGIC_1164.ALL;
30
use IEEE.STD_LOGIC_ARITH.ALL;
31
use IEEE.STD_LOGIC_UNSIGNED.ALL;
32
 
33
use work.common.ALL;
34
 
35
entity opc_deco is
36
    port (  I_CLK       : in  std_logic;
37
 
38
            I_OPC       : in  std_logic_vector(31 downto 0);
39
            I_PC        : in  std_logic_vector(15 downto 0);
40
            I_T0        : in  std_logic;
41
 
42
            Q_ALU_OP    : out std_logic_vector( 4 downto 0);
43
            Q_AMOD      : out std_logic_vector( 5 downto 0);
44
            Q_BIT       : out std_logic_vector( 3 downto 0);
45
            Q_DDDDD     : out std_logic_vector( 4 downto 0);
46
            Q_IMM       : out std_logic_vector(15 downto 0);
47
            Q_JADR      : out std_logic_vector(15 downto 0);
48
            Q_OPC       : out std_logic_vector(15 downto 0);
49
            Q_PC        : out std_logic_vector(15 downto 0);
50
            Q_PC_OP     : out std_logic_vector( 2 downto 0);
51
            Q_PMS       : out std_logic;  -- program memory select
52
            Q_RD_M      : out std_logic;
53
            Q_RRRRR     : out std_logic_vector( 4 downto 0);
54
            Q_RSEL      : out std_logic_vector( 1 downto 0);
55
            Q_WE_01     : out std_logic;
56
            Q_WE_D      : out std_logic_vector( 1 downto 0);
57
            Q_WE_F      : out std_logic;
58
            Q_WE_M      : out std_logic_vector( 1 downto 0);
59
            Q_WE_XYZS   : out std_logic);
60
end opc_deco;
61
 
62
architecture Behavioral of opc_deco is
63
 
64
begin
65
 
66
    process(I_CLK)
67
    begin
68
    if (rising_edge(I_CLK)) then
69
        --
70
        -- set the most common settings as default.
71
        --
72
        Q_ALU_OP  <= ALU_D_MV_Q;
73
        Q_AMOD    <= AMOD_ABS;
74
        Q_BIT     <= I_OPC(10) & I_OPC(2 downto 0);
75
        Q_DDDDD   <= I_OPC(8 downto 4);
76
        Q_IMM     <= X"0000";
77
        Q_JADR    <= I_OPC(31 downto 16);
78
        Q_OPC     <= I_OPC(15 downto  0);
79
        Q_PC      <= I_PC;
80
        Q_PC_OP   <= PC_NEXT;
81
        Q_PMS     <= '0';
82
        Q_RD_M    <= '0';
83
        Q_RRRRR   <= I_OPC(9) & I_OPC(3 downto 0);
84
        Q_RSEL    <= RS_REG;
85
        Q_WE_D    <= "00";
86
        Q_WE_01   <= '0';
87
        Q_WE_F    <= '0';
88
        Q_WE_M    <= "00";
89
        Q_WE_XYZS <= '0';
90
 
91
        case I_OPC(15 downto 10) is
92
            when "000000" =>
93
                case I_OPC(9 downto 8) is
94
                    when "00" =>
95
                        --
96
                        -- 0000 0000 0000 0000 - NOP
97
                        -- 0000 0000 001v vvvv - INTERRUPT
98
                        --
99
                        if (I_OPC(5)) = '1' then   -- interrupt
100
                            Q_ALU_OP <= ALU_INTR;
101
                            Q_AMOD <= AMOD_ddSP;
102
                            Q_JADR <= "0000000000" & I_OPC(4 downto 0) & "0";
103
                            Q_PC_OP <= PC_LD_I;
104
                            Q_WE_F <= '1';
105
                            Q_WE_M <= "11";
106
                        end if;
107
 
108
                    when "01" =>
109
                        --
110
                        -- 0000 0001 dddd rrrr - MOVW
111
                        --
112
                        Q_DDDDD <= I_OPC(7 downto 4) & "0";
113
                        Q_RRRRR <= I_OPC(3 downto 0) & "0";
114
                        Q_ALU_OP <= ALU_MV_16;
115
                        Q_WE_D <= "11";
116
 
117
                    when "10" =>
118
                        --
119
                        -- 0000 0010 dddd rrrr - MULS
120
                        --
121
                        Q_DDDDD <= "1" & I_OPC(7 downto 4);
122
                        Q_RRRRR <= "1" & I_OPC(3 downto 0);
123
                        Q_ALU_OP <= ALU_MULT;
124
                        Q_IMM(7 downto 5) <= MULT_SS;
125
                        Q_WE_01 <= '1';
126
                        Q_WE_F <= '1';
127
 
128
                    when others =>
129
                        --
130
                        -- 0000 0011 0ddd 0rrr - _MULSU  SU "010"
131
                        -- 0000 0011 0ddd 1rrr - FMUL    UU "100"
132
                        -- 0000 0011 1ddd 0rrr - FMULS   SS "111"
133
                        -- 0000 0011 1ddd 1rrr - FMULSU  SU "110"
134
                        --
135
                        Q_DDDDD(4 downto 3) <= "10";    -- regs 16 to 23
136
                        Q_RRRRR(4 downto 3) <= "10";    -- regs 16 to 23
137
                        Q_ALU_OP <= ALU_MULT;
138
                        if I_OPC(7) = '0' then
139
                            if I_OPC(3) = '0' then
140
                                Q_IMM(7 downto 5) <= MULT_SU;
141
                            else
142
                                Q_IMM(7 downto 5) <= MULT_FUU;
143
                            end if;
144
                        else
145
                            if I_OPC(3) = '0' then
146
                                Q_IMM(7 downto 5) <= MULT_FSS;
147
                            else
148
                                Q_IMM(7 downto 5) <= MULT_FSU;
149
                            end if;
150
                        end if;
151
                        Q_WE_01 <= '1';
152
                        Q_WE_F <= '1';
153
                end case;
154
 
155
            when "000001" | "000010" =>
156
                --
157
                -- 0000 01rd dddd rrrr - CPC = SBC without Q_WE_D
158
                -- 0000 10rd dddd rrrr - SBC
159
                --
160
                Q_ALU_OP <= ALU_SBC;
161
                Q_WE_D <= '0' & I_OPC(11);  -- write Rd if SBC.
162
                Q_WE_F <= '1';
163
 
164
            when "000011" =>
165
                --
166
                -- 0000 11rd dddd rrrr - ADD
167
                --
168
                Q_ALU_OP <= ALU_ADD;
169
                Q_WE_D <= "01";
170
                Q_WE_F <= '1';
171
 
172
            when "000100" => -- CPSE
173
                Q_ALU_OP <= ALU_SUB;
174
                Q_RD_M <= I_T0;
175
                if (I_T0 = '0') then        -- second cycle.
176
                    Q_PC_OP <= PC_SKIP_Z;
177
                end if;
178
 
179
            when "000101" | "000110" =>
180
                --
181
                -- 0001 01rd dddd rrrr - CP = SUB without Q_WE_D
182
                -- 0000 10rd dddd rrrr - SUB
183
                --
184
                Q_ALU_OP <= ALU_SUB;
185
                Q_WE_D <= '0' & I_OPC(11);  -- write Rd if SUB.
186
                Q_WE_F <= '1';
187
 
188
            when "000111" =>
189
                --
190
                -- 0001 11rd dddd rrrr - ADC
191
                --
192
                Q_ALU_OP <= ALU_ADC;
193
                Q_WE_D <= "01";
194
                Q_WE_F <= '1';
195
 
196
            when "001000" =>
197
                --
198
                -- 0010 00rd dddd rrrr - AND
199
                --
200
                Q_ALU_OP <= ALU_AND;
201
                Q_WE_D <= "01";
202
                Q_WE_F <= '1';
203
 
204
            when "001001" =>
205
                --
206
                -- 0010 01rd dddd rrrr - EOR
207
                --
208
                Q_ALU_OP <= ALU_EOR;
209
                Q_WE_D <= "01";
210
                Q_WE_F <= '1';
211
 
212
            when "001010" => -- OR
213
                --
214
                -- 0010 10rd dddd rrrr - OR
215
                --
216
                Q_ALU_OP <= ALU_OR;
217
                Q_WE_D <= "01";
218
                Q_WE_F <= '1';
219
 
220
            when "001011" =>
221
                --
222
                -- 0010 11rd dddd rrrr - MOV
223
                --
224
                Q_ALU_OP <= ALU_R_MV_Q;
225
                Q_WE_D <= "01";
226
 
227
            when "001100" | "001101" | "001110" | "001111"
228
               | "010100" | "010101" | "010110" | "010111" =>
229
                --
230
                -- 0011 KKKK dddd KKKK - CPI
231
                -- 0101 KKKK dddd KKKK - SUBI
232
                --
233
                Q_ALU_OP <= ALU_SUB;
234
                Q_IMM(7 downto 0) <= I_OPC(11 downto 8) & I_OPC(3 downto 0);
235
                Q_RSEL <= RS_IMM;
236
                Q_DDDDD(4) <= '1';    -- Rd = 16...31
237
                Q_WE_D <= '0' & I_OPC(14);
238
                Q_WE_F <= '1';
239
 
240
            when "010000" | "010001" | "010010" | "010011" =>
241
                --
242
                -- 0100 KKKK dddd KKKK - SBCI
243
                --
244
                Q_ALU_OP <= ALU_SBC;
245
                Q_IMM(7 downto 0) <= I_OPC(11 downto 8) & I_OPC(3 downto 0);
246
                Q_RSEL <= RS_IMM;
247
                Q_DDDDD(4) <= '1';    -- Rd = 16...31
248
                Q_WE_D <= "01";
249
                Q_WE_F <= '1';
250
 
251
            when "011000" | "011001" | "011010" | "011011" =>
252
                --
253
                -- 0110 KKKK dddd KKKK - ORI
254
                --
255
                Q_ALU_OP <= ALU_OR;
256
                Q_IMM(7 downto 0) <= I_OPC(11 downto 8) & I_OPC(3 downto 0);
257
                Q_RSEL <= RS_IMM;
258
                Q_DDDDD(4) <= '1';    -- Rd = 16...31
259
                Q_WE_D <= "01";
260
                Q_WE_F <= '1';
261
 
262
            when "011100" | "011101" | "011110" | "011111" =>
263
                --
264
                -- 0111 KKKK dddd KKKK - ANDI
265
                --
266
                Q_ALU_OP <= ALU_AND;
267
                Q_IMM(7 downto 0) <= I_OPC(11 downto 8) & I_OPC(3 downto 0);
268
                Q_RSEL <= RS_IMM;
269
                Q_DDDDD(4) <= '1';    -- Rd = 16...31
270
                Q_WE_D <= "01";
271
                Q_WE_F <= '1';
272
 
273
            when "100000" | "100001" | "100010" | "100011"
274
               | "101000" | "101001" | "101010" | "101011" =>
275
                --
276
                -- LDD (Y + q) == LD (y) if q == 0
277
                --
278
                -- 10q0 qq0d dddd 1qqq  LDD (Y + q)
279
                -- 10q0 qq0d dddd 0qqq  LDD (Z + q)
280
                -- 10q0 qq1d dddd 1qqq  SDD (Y + q)
281
                -- 10q0 qq1d dddd 0qqq  SDD (Z + q)
282
                --        L/      Z/
283
                --        S       Y
284
                --
285
                Q_IMM(5) <= I_OPC(13);
286
                Q_IMM(4 downto 3) <= I_OPC(11 downto 10);
287
                Q_IMM(2 downto 0) <= I_OPC( 2 downto  0);
288
 
289
                if (I_OPC(3) = '0') then    Q_AMOD <= AMOD_Zq;
290
                else                        Q_AMOD <= AMOD_Yq;
291
                end if;
292
 
293
                Q_RD_M <= not I_OPC(9);             -- '1'  if LDD
294
                Q_WE_M <= '0' & I_OPC(9);           -- "01" if STD
295
 
296
            when "100100" =>
297
                Q_IMM <= I_OPC(31 downto 16);   -- absolute address for LDS/STS
298
                if (I_OPC(9) = '0') then        -- LDD / POP
299
                    --
300
                    -- 1001 00-0d dddd 0000 - LDS
301
                    -- 1001 00-0d dddd 0001 - LD Rd, Z+
302
                    -- 1001 00-0d dddd 0010 - LD Rd, -Z
303
                    -- 1001 00-0d dddd 0100 - (ii)  LPM Rd, (Z)
304
                    -- 1001 00-0d dddd 0101 - (iii) LPM Rd, (Z+)
305
                    -- 1001 00-0d dddd 0110 - ELPM Z        --- not mega8
306
                    -- 1001 00-0d dddd 0111 - ELPM Z+       --- not mega8
307
                    -- 1001 00-0d dddd 1001 - LD Rd, Y+
308
                    -- 1001 00-0d dddd 1010 - LD Rd, -Y
309
                    -- 1001 00-0d dddd 1100 - LD Rd, X
310
                    -- 1001 00-0d dddd 1101 - LD Rd, X+
311
                    -- 1001 00-0d dddd 1110 - LD Rd, -X
312
                    -- 1001 00-0d dddd 1111 - POP Rd
313
                    --
314
                    Q_RSEL <= RS_DIN;
315
                    Q_RD_M <= I_T0;
316
                    Q_WE_D <= '0' & not I_T0;
317
                    Q_WE_XYZS <= not I_T0;
318
                    Q_PMS <= (not I_OPC(3)) and I_OPC(2) and (not I_OPC(1));
319
                    case I_OPC(3 downto 0) is
320
                        when "0000" => Q_AMOD <= AMOD_ABS;  Q_WE_XYZS <= '0';
321
                        when "0001" => Q_AMOD <= AMOD_Zi;
322
                        when "0100" => Q_AMOD <= AMOD_Z;    Q_WE_XYZS <= '0';
323
                        when "0101" => Q_AMOD <= AMOD_Zi;
324
                        when "1001" => Q_AMOD <= AMOD_Yi;
325
                        when "1010" => Q_AMOD <= AMOD_dY;
326
                        when "1100" => Q_AMOD <= AMOD_X;    Q_WE_XYZS <= '0';
327
                        when "1101" => Q_AMOD <= AMOD_Xi;
328
                        when "1110" => Q_AMOD <= AMOD_dX;
329
                        when "1111" => Q_AMOD <= AMOD_SPi;
330
                        when others =>                      Q_WE_XYZS <= '0';
331
                    end case;
332
                else                        -- STD / PUSH
333
                    --
334
                    -- 1001 00-1r rrrr 0000 - STS
335
                    -- 1001 00-1r rrrr 0001 - ST Z+. Rr
336
                    -- 1001 00-1r rrrr 0010 - ST -Z. Rr
337
                    -- 1001 00-1r rrrr 1000 - ST Y. Rr
338
                    -- 1001 00-1r rrrr 1001 - ST Y+. Rr
339
                    -- 1001 00-1r rrrr 1010 - ST -Y. Rr
340
                    -- 1001 00-1r rrrr 1100 - ST X. Rr
341
                    -- 1001 00-1r rrrr 1101 - ST X+. Rr
342
                    -- 1001 00-1r rrrr 1110 - ST -X. Rr
343
                    -- 1001 00-1r rrrr 1111 - PUSH Rr
344
                    --
345
                    Q_ALU_OP <= ALU_D_MV_Q;
346
                    Q_WE_M <= "01";
347
                    Q_WE_XYZS <= '1';
348
                    case I_OPC(3 downto 0) is
349
                        when "0000" => Q_AMOD <= AMOD_ABS;  Q_WE_XYZS <= '0';
350
                        when "0001" => Q_AMOD <= AMOD_Zi;
351
                        when "0010" => Q_AMOD <= AMOD_dZ;
352
                        when "1001" => Q_AMOD <= AMOD_Yi;
353
                        when "1010" => Q_AMOD <= AMOD_dY;
354
                        when "1100" => Q_AMOD <= AMOD_X;    Q_WE_XYZS <= '0';
355
                        when "1101" => Q_AMOD <= AMOD_Xi;
356
                        when "1110" => Q_AMOD <= AMOD_dX;
357
                        when "1111" => Q_AMOD <= AMOD_dSP;
358
                        when others =>
359
                    end case;
360
                end if;
361
 
362
            when "100101" =>
363
                if (I_OPC(9) = '0') then
364
                    if (I_OPC(3) = '0') then
365
                        --
366
                        --  1001 010d dddd 0000 - COM
367
                        --  1001 010d dddd 0001 - NEG
368
                        --  1001 010d dddd 0010 - SWAP
369
                        --  1001 010d dddd 0011 - INC
370
                        --  1001 010d dddd 0101 - ASR
371
                        --  1001 010d dddd 0110 - LSR
372
                        --  1001 010d dddd 0111 - ROR
373
                        --
374
                        case I_OPC(2 downto 0) is
375
                            when "000"  => Q_ALU_OP <= ALU_COM;
376
                            when "001"  => Q_ALU_OP <= ALU_NEG;
377
                            when "010"  => Q_ALU_OP <= ALU_SWAP;
378
                            when "011"  => Q_ALU_OP <= ALU_INC;
379
                            when "101"  => Q_ALU_OP <= ALU_ASR;
380
                            when "110"  => Q_ALU_OP <= ALU_LSR;
381
                            when "111"  => Q_ALU_OP <= ALU_ROR;
382
                            when others =>
383
                        end case;
384
                        Q_WE_D <= "01";
385
                        Q_WE_F <= '1';
386
                    else
387
                        case I_OPC(2 downto 0) is
388
                            when "000"  =>
389
                                if (I_OPC(8)) = '0' then
390
                                    --
391
                                    --  1001 0100 0sss 1000 - BSET
392
                                    --  1001 0100 1sss 1000 - BCLR
393
                                    --
394
                                    Q_BIT(3 downto 0) <= I_OPC(7 downto 4);
395
                                    Q_ALU_OP <= ALU_SREG;
396
                                    Q_WE_F <= '1';
397
                                else
398
                                    --
399
                                    --  1001 0101 0000 1000 - RET
400
                                    --  1001 0101 0001 1000 - RETI
401
                                    --  1001 0101 1000 1000 - SLEEP
402
                                    --  1001 0101 1001 1000 - BREAK
403
                                    --  1001 0101 1100 1000 - LPM     [ R0,(Z) ]
404
                                    --  1001 0101 1101 1000 - ELPM   not mega8
405
                                    --  1001 0101 1110 1000 - SPM
406
                                    --  1001 0101 1111 1000 - SPM #2
407
                                    --  1001 0101 1010 1000 - WDR
408
                                    --
409
                                    case I_OPC(7 downto 4) is
410
                                        when "0000" =>  -- RET
411
                                            Q_AMOD <= AMOD_SPii;
412
                                            if (I_T0 = '1') then
413
                                                Q_RD_M <= '1';
414
                                            else
415
                                                Q_PC_OP <= PC_LD_S;
416
                                                Q_WE_XYZS <= not I_T0;
417
                                            end if;
418
 
419
                                        when "0001" =>  -- RETI
420
                                            Q_ALU_OP <= ALU_INTR;
421
                                            Q_IMM(6) <= '1';
422
                                            Q_AMOD <= AMOD_SPii;
423
                                            if (I_T0 = '1') then
424
                                                Q_RD_M <= '1';
425
                                            else
426
                                                Q_PC_OP <= PC_LD_S;
427
                                                Q_WE_XYZS <= not I_T0;
428
                                            end if;
429
 
430
                                        when "1000" =>  -- (i) LPM R0, (Z)
431
                                            Q_DDDDD <= "00000";
432
                                            Q_AMOD <= AMOD_Z;
433
                                            Q_PMS <= '1';
434
                                            Q_WE_D <= '0' & not I_T0;
435
 
436
                                        when "1110" =>  -- SPM
437
                                            Q_DDDDD <= "00000";
438
                                            Q_AMOD <= AMOD_Z;
439
                                            Q_PMS <= '1';
440
                                            Q_WE_M <= "01";
441
 
442
                                        when "1111" =>  -- SPM #2
443
                                            -- page write: not su[pported
444
 
445
                                        when others =>
446
                                    end case;
447
                                end if;
448
 
449
                            when "001"  =>
450
                                --
451
                                --  1001 0100 0000 1001 IJMP
452
                                --  1001 0100 0001 1001 EIJMP   -- not mega8
453
                                --  1001 0101 0000 1001 ICALL
454
                                --  1001 0101 0001 1001 EICALL   -- not mega8
455
                                --
456
                                Q_PC_OP <= PC_LD_Z;
457
                                if (I_OPC(8) = '1') then        -- ICALL
458
                                    Q_ALU_OP <= ALU_PC_1;
459
                                    Q_AMOD <= AMOD_ddSP;
460
                                    Q_WE_M <= "11";
461
                                    Q_WE_XYZS <= '1';
462
                                end if;
463
 
464
                            when "010"  =>
465
                                --
466
                                --  1001 010d dddd 1010 - DEC
467
                                --
468
                                Q_ALU_OP <= ALU_DEC;
469
                                Q_WE_D <= "01";
470
                                Q_WE_F <= '1';
471
 
472
                            when "011"  =>
473
                                --
474
                                --  1001 0100 KKKK 1011 - DES   -- not mega8
475
                                --
476
 
477
                            when "100" | "101"  =>
478
                                --
479
                                --  1001 010k kkkk 110k - JMP (k = 0 for 16 bit)
480
                                --  kkkk kkkk kkkk kkkk
481
                                --
482
                                Q_PC_OP <= PC_LD_I;
483
 
484
                            when "110" | "111"  =>
485
                                --
486
                                --  1001 010k kkkk 111k - CALL (k = 0)
487
                                --  kkkk kkkk kkkk kkkk
488
                                --
489
                                Q_ALU_OP <= ALU_PC_2;
490
                                Q_AMOD <= AMOD_ddSP;
491
                                Q_PC_OP <= PC_LD_I;
492
                                Q_WE_M <= "11";     -- both PC bytes
493
                                Q_WE_XYZS <= '1';
494
 
495
                            when others =>
496
                        end case;
497
                    end if;
498
                else
499
                    --
500
                    --  1001 0110 KKdd KKKK - ADIW
501
                    --  1001 0111 KKdd KKKK - SBIW
502
                    --
503
                    if (I_OPC(8) = '0') then    Q_ALU_OP <= ALU_ADIW;
504
                    else                        Q_ALU_OP <= ALU_SBIW;
505
                    end if;
506
                    Q_IMM(5 downto 4) <= I_OPC(7 downto 6);
507
                    Q_IMM(3 downto 0) <= I_OPC(3 downto 0);
508
                    Q_RSEL <= RS_IMM;
509
                    Q_DDDDD <= "11" & I_OPC(5 downto 4) & "0";
510
 
511
                    Q_WE_D <= "11";
512
                    Q_WE_F <= '1';
513
                end if; -- I_OPC(9) = 0/1
514
 
515
            when "100110" =>
516
                --
517
                --  1001 1000 AAAA Abbb - CBI
518
                --  1001 1001 AAAA Abbb - SBIC
519
                --  1001 1010 AAAA Abbb - SBI
520
                --  1001 1011 AAAA Abbb - SBIS
521
                --
522
                Q_ALU_OP <= ALU_BIT_CS;
523
                Q_AMOD <= AMOD_ABS;
524
                Q_BIT(3) <= I_OPC(9);   -- set/clear
525
 
526
                -- IMM = AAAAAA + 0x20
527
                --
528
                Q_IMM(4 downto 0) <= I_OPC(7 downto 3);
529
                Q_IMM(6 downto 5) <= "01";
530
 
531
                Q_RD_M <= I_T0;
532
                if ((I_OPC(8) = '0') ) then     -- CBI or SBI
533
                    Q_WE_M(0) <= '1';
534
                else                            -- SBIC or SBIS
535
                    if (I_T0 = '0') then        -- second cycle.
536
                        Q_PC_OP <= PC_SKIP_T;
537
                    end if;
538
                end if;
539
 
540
            when "100111" => -- MUL
541
                --
542
                --  1001 11rd dddd rrrr - MUL
543
                --
544
                 Q_ALU_OP <= ALU_MULT;
545
                 Q_IMM(7 downto 5) <= "000"; --  -MUL UU;
546
                 Q_WE_01 <= '1';
547
                 Q_WE_F <= '1';
548
 
549
            when "101100" | "101101" =>
550
                --
551
                -- 1011 0AAd dddd AAAA - IN
552
                --
553
                Q_RSEL <= RS_DIN;
554
                Q_AMOD <= AMOD_ABS;
555
 
556
                -- IMM = AAAAAA
557
                --     + 010000 (0x20)
558
                Q_IMM(3 downto 0) <= I_OPC(3 downto 0);
559
                Q_IMM(4) <= I_OPC(9);
560
                Q_IMM(6 downto 5) <= "01" + ('0' & I_OPC(10 downto 10));
561
 
562
                Q_WE_D <= "01";
563
 
564
            when "101110" | "101111" =>
565
                --
566
                -- 1011 1AAr rrrr AAAA - OUT
567
                --
568
                Q_ALU_OP <= ALU_D_MV_Q;
569
                Q_AMOD <= AMOD_ABS;
570
 
571
                -- IMM = AAAAAA
572
                --     + 010000 (0x20)
573
                --
574
                Q_IMM(3 downto 0) <= I_OPC(3 downto 0);
575
                Q_IMM(4) <= I_OPC(9);
576
                Q_IMM(6 downto 5) <= "01" + ('0' & I_OPC(10 downto 10));
577
                Q_WE_M <= "01";
578
 
579
            when "110000" | "110001" | "110010" | "110011" =>
580
                --
581
                -- 1100 kkkk kkkk kkkk - RJMP
582
                --
583
                Q_JADR <= I_PC + (I_OPC(11) & I_OPC(11) & I_OPC(11) & I_OPC(11)
584
                                & I_OPC(11 downto 0)) + X"0001";
585
                Q_PC_OP <= PC_LD_I;
586
 
587
            when "110100" | "110101" | "110110" | "110111" =>
588
                --
589
                -- 1101 kkkk kkkk kkkk - RCALL
590
                --
591
                Q_JADR <= I_PC + (I_OPC(11) & I_OPC(11) & I_OPC(11) & I_OPC(11)
592
                                & I_OPC(11 downto 0)) + X"0001";
593
                Q_ALU_OP <= ALU_PC_1;
594
                Q_AMOD <= AMOD_ddSP;
595
                Q_PC_OP <= PC_LD_I;
596
                Q_WE_M <= "11";     -- both PC bytes
597
                Q_WE_XYZS <= '1';
598
 
599
            when "111000" | "111001" | "111010" | "111011" => -- LDI
600
                --
601
                -- 1110 KKKK dddd KKKK - LDI Rd, K
602
                --
603
                Q_ALU_OP <= ALU_R_MV_Q;
604
                Q_RSEL <= RS_IMM;
605
                Q_DDDDD <= '1' & I_OPC(7 downto 4);     -- 16..31
606
                Q_IMM(7 downto 0) <= I_OPC(11 downto 8) & I_OPC(3 downto 0);
607
                Q_WE_D <= "01";
608
 
609
            when "111100" | "111101" =>
610
                --
611
                -- 1111 00kk kkkk kbbb - BRBS
612
                -- 1111 01kk kkkk kbbb - BRBC
613
                --       v
614
                -- bbb: status register bit
615
                -- v: value (set/cleared) of status register bit
616
                --
617
                Q_JADR <= I_PC + (I_OPC(9) & I_OPC(9) & I_OPC(9) & I_OPC(9)
618
                                & I_OPC(9) & I_OPC(9) & I_OPC(9) & I_OPC(9)
619
                                & I_OPC(9) & I_OPC(9 downto 3)) + X"0001";
620
                Q_PC_OP <= PC_BCC;
621
 
622
            when "111110" =>
623
                --
624
                -- 1111 100d dddd 0bbb - BLD
625
                -- 1111 101d dddd 0bbb - BST
626
                --
627
                if I_OPC(9) = '0' then  -- BLD: T flag to register
628
                    Q_ALU_OP <= ALU_BLD;
629
                    Q_WE_D <= "01";
630
                else                    -- BST: register to T flag
631
                    Q_AMOD <= AMOD_ABS;
632
                    Q_BIT(3) <= I_OPC(10);
633
                    Q_IMM(4 downto 0) <= I_OPC(8 downto 4);
634
                    Q_ALU_OP <= ALU_BIT_CS;
635
                    Q_WE_F <= '1';
636
                end if;
637
 
638
            when "111111" =>
639
                --
640
                -- 1111 110r rrrr 0bbb - SBRC
641
                -- 1111 111r rrrr 0bbb - SBRS
642
                --
643
                -- like SBIC, but and general purpose regs instead of I/O regs.
644
                --
645
                Q_ALU_OP <= ALU_BIT_CS;
646
                Q_AMOD <= AMOD_ABS;
647
                Q_BIT(3) <= I_OPC(9);   -- set/clear bit
648
                Q_IMM(4 downto 0) <= I_OPC(8 downto 4);
649
                if (I_T0 = '0') then
650
                    Q_PC_OP <= PC_SKIP_T;
651
                end if;
652
 
653
            when others =>
654
        end case;
655
    end if;
656
    end process;
657
 
658
end Behavioral;
659
 

powered by: WebSVN 2.1.0

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