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 17

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 10 jsauermann
            when "000000" =>                            -- 0000 00xx xxxx xxxx
93 2 jsauermann
                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 15 jsauermann
                            Q_AMOD <= AMOD_SPdd;
102 2 jsauermann
                            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 10 jsauermann
            when "000011" =>                            -- 0000 11xx xxxx xxxx
165 2 jsauermann
                --
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 10 jsauermann
            when "000100" =>                            -- 0001 00xx xxxx xxxx
173 2 jsauermann
                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 10 jsauermann
            when "000111" =>                            -- 0001 11xx xxxx xxxx
189 2 jsauermann
                --
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 10 jsauermann
            when "001000" =>                            -- 0010 00xx xxxx xxxx
197 2 jsauermann
                --
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 10 jsauermann
            when "001001" =>                            -- 0010 01xx xxxx xxxx
205 2 jsauermann
                --
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 10 jsauermann
            when "001010" =>                            -- 0010 10xx xxxx xxxx
213 2 jsauermann
                --
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 10 jsauermann
            when "001011" =>                            -- 0010 11xx xxxx xxxx
221 2 jsauermann
                --
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 13 jsauermann
                if (I_OPC(9) = '0') then            -- LDD
294 14 jsauermann
                    Q_RSEL <= RS_DIN;
295 13 jsauermann
                    Q_RD_M <= I_T0 ;
296
                    Q_WE_D <= '0' & not I_T0;
297
                else                                -- STD
298
                    Q_WE_M <= '0' & I_OPC(9);
299
                end if;
300 2 jsauermann
 
301 10 jsauermann
            when "100100" =>                            -- 1001 00xx xxxx xxxx
302 2 jsauermann
                Q_IMM <= I_OPC(31 downto 16);   -- absolute address for LDS/STS
303
                if (I_OPC(9) = '0') then        -- LDD / POP
304
                    --
305
                    -- 1001 00-0d dddd 0000 - LDS
306
                    -- 1001 00-0d dddd 0001 - LD Rd, Z+
307
                    -- 1001 00-0d dddd 0010 - LD Rd, -Z
308
                    -- 1001 00-0d dddd 0100 - (ii)  LPM Rd, (Z)
309
                    -- 1001 00-0d dddd 0101 - (iii) LPM Rd, (Z+)
310
                    -- 1001 00-0d dddd 0110 - ELPM Z        --- not mega8
311
                    -- 1001 00-0d dddd 0111 - ELPM Z+       --- not mega8
312
                    -- 1001 00-0d dddd 1001 - LD Rd, Y+
313
                    -- 1001 00-0d dddd 1010 - LD Rd, -Y
314
                    -- 1001 00-0d dddd 1100 - LD Rd, X
315
                    -- 1001 00-0d dddd 1101 - LD Rd, X+
316
                    -- 1001 00-0d dddd 1110 - LD Rd, -X
317
                    -- 1001 00-0d dddd 1111 - POP Rd
318
                    --
319
                    Q_RSEL <= RS_DIN;
320
                    Q_RD_M <= I_T0;
321
                    Q_WE_D <= '0' & not I_T0;
322
                    Q_WE_XYZS <= not I_T0;
323
                    Q_PMS <= (not I_OPC(3)) and I_OPC(2) and (not I_OPC(1));
324
                    case I_OPC(3 downto 0) is
325
                        when "0000" => Q_AMOD <= AMOD_ABS;  Q_WE_XYZS <= '0';
326
                        when "0001" => Q_AMOD <= AMOD_Zi;
327
                        when "0100" => Q_AMOD <= AMOD_Z;    Q_WE_XYZS <= '0';
328
                        when "0101" => Q_AMOD <= AMOD_Zi;
329
                        when "1001" => Q_AMOD <= AMOD_Yi;
330
                        when "1010" => Q_AMOD <= AMOD_dY;
331
                        when "1100" => Q_AMOD <= AMOD_X;    Q_WE_XYZS <= '0';
332
                        when "1101" => Q_AMOD <= AMOD_Xi;
333
                        when "1110" => Q_AMOD <= AMOD_dX;
334 15 jsauermann
                        when "1111" => Q_AMOD <= AMOD_iSP;
335 2 jsauermann
                        when others =>                      Q_WE_XYZS <= '0';
336
                    end case;
337
                else                        -- STD / PUSH
338
                    --
339
                    -- 1001 00-1r rrrr 0000 - STS
340
                    -- 1001 00-1r rrrr 0001 - ST Z+. Rr
341
                    -- 1001 00-1r rrrr 0010 - ST -Z. Rr
342
                    -- 1001 00-1r rrrr 1000 - ST Y. Rr
343
                    -- 1001 00-1r rrrr 1001 - ST Y+. Rr
344
                    -- 1001 00-1r rrrr 1010 - ST -Y. Rr
345
                    -- 1001 00-1r rrrr 1100 - ST X. Rr
346
                    -- 1001 00-1r rrrr 1101 - ST X+. Rr
347
                    -- 1001 00-1r rrrr 1110 - ST -X. Rr
348
                    -- 1001 00-1r rrrr 1111 - PUSH Rr
349
                    --
350
                    Q_ALU_OP <= ALU_D_MV_Q;
351
                    Q_WE_M <= "01";
352
                    Q_WE_XYZS <= '1';
353
                    case I_OPC(3 downto 0) is
354
                        when "0000" => Q_AMOD <= AMOD_ABS;  Q_WE_XYZS <= '0';
355
                        when "0001" => Q_AMOD <= AMOD_Zi;
356
                        when "0010" => Q_AMOD <= AMOD_dZ;
357
                        when "1001" => Q_AMOD <= AMOD_Yi;
358
                        when "1010" => Q_AMOD <= AMOD_dY;
359
                        when "1100" => Q_AMOD <= AMOD_X;    Q_WE_XYZS <= '0';
360
                        when "1101" => Q_AMOD <= AMOD_Xi;
361
                        when "1110" => Q_AMOD <= AMOD_dX;
362 15 jsauermann
                        when "1111" => Q_AMOD <= AMOD_SPd;
363 2 jsauermann
                        when others =>
364
                    end case;
365
                end if;
366
 
367 10 jsauermann
            when "100101" =>                            -- 1001 01xx xxxx xxxx
368
                if (I_OPC(9) = '0') then                -- 1001 010
369
                    if (I_OPC(3) = '0') then            -- 1001 010x xxxx 0xxx
370 2 jsauermann
                        --
371
                        --  1001 010d dddd 0000 - COM
372
                        --  1001 010d dddd 0001 - NEG
373
                        --  1001 010d dddd 0010 - SWAP
374
                        --  1001 010d dddd 0011 - INC
375
                        --  1001 010d dddd 0101 - ASR
376
                        --  1001 010d dddd 0110 - LSR
377
                        --  1001 010d dddd 0111 - ROR
378
                        --
379
                        case I_OPC(2 downto 0) is
380
                            when "000"  => Q_ALU_OP <= ALU_COM;
381
                            when "001"  => Q_ALU_OP <= ALU_NEG;
382
                            when "010"  => Q_ALU_OP <= ALU_SWAP;
383
                            when "011"  => Q_ALU_OP <= ALU_INC;
384
                            when "101"  => Q_ALU_OP <= ALU_ASR;
385
                            when "110"  => Q_ALU_OP <= ALU_LSR;
386
                            when "111"  => Q_ALU_OP <= ALU_ROR;
387
                            when others =>
388
                        end case;
389
                        Q_WE_D <= "01";
390
                        Q_WE_F <= '1';
391 10 jsauermann
                    else                                -- 1001 010x xxxx 1xxx
392 2 jsauermann
                        case I_OPC(2 downto 0) is
393 10 jsauermann
                            when "000"  =>              -- 1001 010x xxxx 1000
394
                                if I_OPC(8) = '0' then  -- 1001 0100 xxxx 1000
395 2 jsauermann
                                    --
396
                                    --  1001 0100 0sss 1000 - BSET
397
                                    --  1001 0100 1sss 1000 - BCLR
398
                                    --
399
                                    Q_BIT(3 downto 0) <= I_OPC(7 downto 4);
400
                                    Q_ALU_OP <= ALU_SREG;
401
                                    Q_WE_F <= '1';
402 10 jsauermann
                                else                    -- 1001 0101 xxxx 1000
403 2 jsauermann
                                    --
404
                                    --  1001 0101 0000 1000 - RET
405
                                    --  1001 0101 0001 1000 - RETI
406
                                    --  1001 0101 1000 1000 - SLEEP
407
                                    --  1001 0101 1001 1000 - BREAK
408
                                    --  1001 0101 1100 1000 - LPM     [ R0,(Z) ]
409
                                    --  1001 0101 1101 1000 - ELPM   not mega8
410
                                    --  1001 0101 1110 1000 - SPM
411
                                    --  1001 0101 1111 1000 - SPM #2
412
                                    --  1001 0101 1010 1000 - WDR
413
                                    --
414
                                    case I_OPC(7 downto 4) is
415
                                        when "0000" =>  -- RET
416 15 jsauermann
                                            Q_AMOD <= AMOD_iiSP;
417 2 jsauermann
                                            if (I_T0 = '1') then
418
                                                Q_RD_M <= '1';
419
                                            else
420
                                                Q_PC_OP <= PC_LD_S;
421
                                                Q_WE_XYZS <= not I_T0;
422
                                            end if;
423
 
424
                                        when "0001" =>  -- RETI
425
                                            Q_ALU_OP <= ALU_INTR;
426
                                            Q_IMM(6) <= '1';
427 15 jsauermann
                                            Q_AMOD <= AMOD_iiSP;
428 2 jsauermann
                                            if (I_T0 = '1') then
429
                                                Q_RD_M <= '1';
430
                                            else
431
                                                Q_PC_OP <= PC_LD_S;
432
                                                Q_WE_XYZS <= not I_T0;
433
                                            end if;
434
 
435
                                        when "1000" =>  -- (i) LPM R0, (Z)
436
                                            Q_DDDDD <= "00000";
437
                                            Q_AMOD <= AMOD_Z;
438
                                            Q_PMS <= '1';
439
                                            Q_WE_D <= '0' & not I_T0;
440
 
441
                                        when "1110" =>  -- SPM
442
                                            Q_DDDDD <= "00000";
443
                                            Q_AMOD <= AMOD_Z;
444
                                            Q_PMS <= '1';
445
                                            Q_WE_M <= "01";
446
 
447
                                        when "1111" =>  -- SPM #2
448
                                            -- page write: not su[pported
449
 
450
                                        when others =>
451
                                    end case;
452
                                end if;
453
 
454 10 jsauermann
                            when "001" =>               -- 1001 010x xxxx 1001
455 2 jsauermann
                                --
456
                                --  1001 0100 0000 1001 IJMP
457
                                --  1001 0100 0001 1001 EIJMP   -- not mega8
458
                                --  1001 0101 0000 1001 ICALL
459
                                --  1001 0101 0001 1001 EICALL   -- not mega8
460
                                --
461
                                Q_PC_OP <= PC_LD_Z;
462
                                if (I_OPC(8) = '1') then        -- ICALL
463
                                    Q_ALU_OP <= ALU_PC_1;
464 15 jsauermann
                                    Q_AMOD <= AMOD_SPdd;
465 2 jsauermann
                                    Q_WE_M <= "11";
466
                                    Q_WE_XYZS <= '1';
467
                                end if;
468
 
469 10 jsauermann
                            when "010"  =>               -- 1001 010x xxxx 1010
470 2 jsauermann
                                --
471
                                --  1001 010d dddd 1010 - DEC
472
                                --
473
                                Q_ALU_OP <= ALU_DEC;
474
                                Q_WE_D <= "01";
475
                                Q_WE_F <= '1';
476
 
477 10 jsauermann
                            when "011"  =>               -- 1001 010x xxxx 1011
478 2 jsauermann
                                --
479
                                --  1001 0100 KKKK 1011 - DES   -- not mega8
480
                                --
481
 
482
                            when "100" | "101"  =>
483
                                --
484
                                --  1001 010k kkkk 110k - JMP (k = 0 for 16 bit)
485
                                --  kkkk kkkk kkkk kkkk
486
                                --
487
                                Q_PC_OP <= PC_LD_I;
488
 
489 10 jsauermann
                            when "110" | "111"  =>      -- 1001 010x xxxx 111x
490 2 jsauermann
                                --
491
                                --  1001 010k kkkk 111k - CALL (k = 0)
492
                                --  kkkk kkkk kkkk kkkk
493
                                --
494
                                Q_ALU_OP <= ALU_PC_2;
495 15 jsauermann
                                Q_AMOD <= AMOD_SPdd;
496 2 jsauermann
                                Q_PC_OP <= PC_LD_I;
497
                                Q_WE_M <= "11";     -- both PC bytes
498
                                Q_WE_XYZS <= '1';
499
 
500
                            when others =>
501
                        end case;
502
                    end if;
503 10 jsauermann
                else            -- 1001 011
504 2 jsauermann
                    --
505
                    --  1001 0110 KKdd KKKK - ADIW
506
                    --  1001 0111 KKdd KKKK - SBIW
507
                    --
508
                    if (I_OPC(8) = '0') then    Q_ALU_OP <= ALU_ADIW;
509
                    else                        Q_ALU_OP <= ALU_SBIW;
510
                    end if;
511
                    Q_IMM(5 downto 4) <= I_OPC(7 downto 6);
512
                    Q_IMM(3 downto 0) <= I_OPC(3 downto 0);
513
                    Q_RSEL <= RS_IMM;
514
                    Q_DDDDD <= "11" & I_OPC(5 downto 4) & "0";
515
 
516
                    Q_WE_D <= "11";
517
                    Q_WE_F <= '1';
518
                end if; -- I_OPC(9) = 0/1
519
 
520 10 jsauermann
            when "100110" =>                            -- 1001 10xx xxxx xxxx
521 2 jsauermann
                --
522
                --  1001 1000 AAAA Abbb - CBI
523
                --  1001 1001 AAAA Abbb - SBIC
524
                --  1001 1010 AAAA Abbb - SBI
525
                --  1001 1011 AAAA Abbb - SBIS
526
                --
527
                Q_ALU_OP <= ALU_BIT_CS;
528
                Q_AMOD <= AMOD_ABS;
529
                Q_BIT(3) <= I_OPC(9);   -- set/clear
530
 
531
                -- IMM = AAAAAA + 0x20
532
                --
533
                Q_IMM(4 downto 0) <= I_OPC(7 downto 3);
534
                Q_IMM(6 downto 5) <= "01";
535
 
536
                Q_RD_M <= I_T0;
537
                if ((I_OPC(8) = '0') ) then     -- CBI or SBI
538
                    Q_WE_M(0) <= '1';
539
                else                            -- SBIC or SBIS
540
                    if (I_T0 = '0') then        -- second cycle.
541
                        Q_PC_OP <= PC_SKIP_T;
542
                    end if;
543
                end if;
544
 
545 10 jsauermann
            when "100111" =>                            -- 1001 11xx xxxx xxxx
546 2 jsauermann
                --
547
                --  1001 11rd dddd rrrr - MUL
548
                --
549
                 Q_ALU_OP <= ALU_MULT;
550
                 Q_IMM(7 downto 5) <= "000"; --  -MUL UU;
551
                 Q_WE_01 <= '1';
552
                 Q_WE_F <= '1';
553
 
554 10 jsauermann
            when "101100" | "101101" =>                 -- 1011 0xxx xxxx xxxx
555 2 jsauermann
                --
556
                -- 1011 0AAd dddd AAAA - IN
557
                --
558
                Q_RSEL <= RS_DIN;
559
                Q_AMOD <= AMOD_ABS;
560
 
561
                -- IMM = AAAAAA
562
                --     + 010000 (0x20)
563
                Q_IMM(3 downto 0) <= I_OPC(3 downto 0);
564
                Q_IMM(4) <= I_OPC(9);
565
                Q_IMM(6 downto 5) <= "01" + ('0' & I_OPC(10 downto 10));
566
 
567 16 jsauermann
                Q_RD_M <= '1';
568 2 jsauermann
                Q_WE_D <= "01";
569
 
570 10 jsauermann
            when "101110" | "101111" =>                 -- 1011 1xxx xxxx xxxx
571 2 jsauermann
                --
572
                -- 1011 1AAr rrrr AAAA - OUT
573
                --
574
                Q_ALU_OP <= ALU_D_MV_Q;
575
                Q_AMOD <= AMOD_ABS;
576
 
577
                -- IMM = AAAAAA
578
                --     + 010000 (0x20)
579
                --
580
                Q_IMM(3 downto 0) <= I_OPC(3 downto 0);
581
                Q_IMM(4) <= I_OPC(9);
582
                Q_IMM(6 downto 5) <= "01" + ('0' & I_OPC(10 downto 10));
583
                Q_WE_M <= "01";
584
 
585
            when "110000" | "110001" | "110010" | "110011" =>
586
                --
587
                -- 1100 kkkk kkkk kkkk - RJMP
588
                --
589
                Q_JADR <= I_PC + (I_OPC(11) & I_OPC(11) & I_OPC(11) & I_OPC(11)
590
                                & I_OPC(11 downto 0)) + X"0001";
591
                Q_PC_OP <= PC_LD_I;
592
 
593
            when "110100" | "110101" | "110110" | "110111" =>
594
                --
595
                -- 1101 kkkk kkkk kkkk - RCALL
596
                --
597
                Q_JADR <= I_PC + (I_OPC(11) & I_OPC(11) & I_OPC(11) & I_OPC(11)
598
                                & I_OPC(11 downto 0)) + X"0001";
599
                Q_ALU_OP <= ALU_PC_1;
600 15 jsauermann
                Q_AMOD <= AMOD_SPdd;
601 2 jsauermann
                Q_PC_OP <= PC_LD_I;
602
                Q_WE_M <= "11";     -- both PC bytes
603
                Q_WE_XYZS <= '1';
604
 
605
            when "111000" | "111001" | "111010" | "111011" => -- LDI
606
                --
607
                -- 1110 KKKK dddd KKKK - LDI Rd, K
608
                --
609
                Q_ALU_OP <= ALU_R_MV_Q;
610
                Q_RSEL <= RS_IMM;
611
                Q_DDDDD <= '1' & I_OPC(7 downto 4);     -- 16..31
612
                Q_IMM(7 downto 0) <= I_OPC(11 downto 8) & I_OPC(3 downto 0);
613
                Q_WE_D <= "01";
614
 
615 10 jsauermann
            when "111100" | "111101" =>                 -- 1111 0xxx xxxx xxxx
616 2 jsauermann
                --
617
                -- 1111 00kk kkkk kbbb - BRBS
618
                -- 1111 01kk kkkk kbbb - BRBC
619
                --       v
620
                -- bbb: status register bit
621
                -- v: value (set/cleared) of status register bit
622
                --
623
                Q_JADR <= I_PC + (I_OPC(9) & I_OPC(9) & I_OPC(9) & I_OPC(9)
624
                                & I_OPC(9) & I_OPC(9) & I_OPC(9) & I_OPC(9)
625
                                & I_OPC(9) & I_OPC(9 downto 3)) + X"0001";
626
                Q_PC_OP <= PC_BCC;
627
 
628 10 jsauermann
            when "111110" =>                            -- 1111 10xx xxxx xxxx
629 2 jsauermann
                --
630
                -- 1111 100d dddd 0bbb - BLD
631
                -- 1111 101d dddd 0bbb - BST
632
                --
633
                if I_OPC(9) = '0' then  -- BLD: T flag to register
634
                    Q_ALU_OP <= ALU_BLD;
635
                    Q_WE_D <= "01";
636
                else                    -- BST: register to T flag
637
                    Q_AMOD <= AMOD_ABS;
638
                    Q_BIT(3) <= I_OPC(10);
639
                    Q_IMM(4 downto 0) <= I_OPC(8 downto 4);
640
                    Q_ALU_OP <= ALU_BIT_CS;
641
                    Q_WE_F <= '1';
642
                end if;
643
 
644 10 jsauermann
            when "111111" =>                            -- 1111 11xx xxxx xxxx
645 2 jsauermann
                --
646
                -- 1111 110r rrrr 0bbb - SBRC
647
                -- 1111 111r rrrr 0bbb - SBRS
648
                --
649
                -- like SBIC, but and general purpose regs instead of I/O regs.
650
                --
651
                Q_ALU_OP <= ALU_BIT_CS;
652
                Q_AMOD <= AMOD_ABS;
653
                Q_BIT(3) <= I_OPC(9);   -- set/clear bit
654
                Q_IMM(4 downto 0) <= I_OPC(8 downto 4);
655
                if (I_T0 = '0') then
656
                    Q_PC_OP <= PC_SKIP_T;
657
                end if;
658
 
659
            when others =>
660
        end case;
661
    end if;
662
    end process;
663
 
664
end Behavioral;
665
 

powered by: WebSVN 2.1.0

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