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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [VHDL/] [o8_cpu.vhd] - Blame information for rev 151

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

Line No. Rev Author Line
1 151 jshamlet
-- Copyright (c)2006, Jeremy Seth Henry
2
-- All rights reserved.
3
--
4
-- Redistribution and use in source and binary forms, with or without
5
-- modification, are permitted provided that the following conditions are met:
6
--     * Redistributions of source code must retain the above copyright
7
--       notice, this list of conditions and the following disclaimer.
8
--     * Redistributions in binary form must reproduce the above copyright
9
--       notice, this list of conditions and the following disclaimer in the
10
--       documentation and/or other materials provided with the distribution,
11
--       where applicable (as part of a user interface, debugging port, etc.)
12
--
13
-- THIS SOFTWARE IS PROVIDED BY JEREMY SETH HENRY ``AS IS'' AND ANY
14
-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15
-- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16
-- DISCLAIMED. IN NO EVENT SHALL JEREMY SETH HENRY BE LIABLE FOR ANY
17
-- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18
-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19
-- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20
-- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22
-- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
 
24
-- VHDL Units :  Open8_CPU
25
-- Description:  VHDL model of the V8 uRISC 8-bit processor core
26
-- Notes      :  Generic definitions
27
--            :  Stack_Start_Address - determines the initial (reset) value of
28
--            :   the stack pointer. Also used for the RSP instruction if
29
--            :   Allow_Stack_Address_Move is 0.
30
--            :
31
--            :  Allow_Stack_Address_Move - When set to 1, allows the RSP to be
32
--            :   programmed via thet RSP instruction. If enabled, the contents
33
--            :   of R1:R0 are used to initialize the stack pointer.
34
--            :
35
--            :  ISR_Start_Addr - determines the location of the interrupt
36
--            :   service vector table. There are 8 service vectors, or 16
37
--            :   bytes, which must be allocated to either ROM or RAM.
38
--            :
39
--            :  Program_Start_Addr - Determines the initial value of the
40
--            :   program counter.
41
--            :
42
--            :  Default_Interrupt_Mask - Determines the intial value of the
43
--            :   interrupt mask. To remain true to the original core, which
44
--            :   had no interrupt mask, this should be set to x"FF". Otherwise
45
--            :   it can be initialized to any value.
46
--            :
47
--            :  Enable_CPU_Halt - determines whether the CPU_Halt pin is
48
--            :   connected or not. This signal is typically used to halt the
49
--            :   processor for a few cycles when accessing slower peripherals,
50
--            :   but may also be used to single step the processor. If this
51
--            :   feature isn't used, it can be disabled to increase Fmax.
52
--            :
53
--            :  The CPU_Halt signal can be used to access slower peripherals
54
--            :   by allowing the device to "pause" the CPU. This can be used,
55
--            :   for example, to write to a standard LCD panel, which requires
56
--            :   a 4MHz interface, by halting on writes. Alternately, devices
57
--            :   such as SDRAM controllers, can pause the processor until the
58
--            :   data is ready to be presented.
59
--            :
60
--            :  The Enable_Auto_Increment generic can be used to modify the
61
--            :   indexed instructions such that specifying an odd register
62
--            :   will use the next lower register pair, post-incrementing the
63
--            :   value in that pair. IOW, specifying STX R1 will instead
64
--            :   result in STX R0++, or R0 = {R1:R0}; {R1:R0} + 1
65
--            :
66
--            : Instructions USR and USR2 have been replaced with DBNZ, and MUL
67
--            :  respectively. DBNZ decrements the specified register, and will
68
--            :  branch if the result is non-zero (Zero flag is not set). MUL
69
--            :  places the result of R0 * Rn into R1:R0, and executes in two
70
--            :  cycles. (R1:R0 = R0 * Rn)
71
--            :
72
-- Revision History
73
-- Author          Date     Change
74
------------------ -------- ---------------------------------------------------
75
-- Seth Henry      07/19/06 Design Start
76
-- Seth Henry      01/18/11 Fixed BTT instruction to match V8
77
-- Seth Henry      06/14/11 Fixed STO instruction to avoid register corruption
78
--                          Fixed interrupt logic to avoid address corruption
79
--                            when interrupt coincides with branch instruction
80
 
81
library ieee;
82
  use ieee.std_logic_1164.all;
83
  use ieee.std_logic_unsigned.all;
84
  use ieee.std_logic_arith.all;
85
 
86
library work;
87
use work.Open8_pkg.all;
88
 
89
entity Open8_CPU is
90
  generic(
91
    Stack_Start_Addr         : ADDRESS_TYPE := x"007F"; -- Top of Stack
92
    Allow_Stack_Address_Move : boolean      := false;   -- Use Normal v8 RSP
93
    ISR_Start_Addr           : ADDRESS_TYPE := x"0080"; -- Bottom of ISR vec's
94
    Program_Start_Addr       : ADDRESS_TYPE := x"0090"; -- Initial PC location
95
    Default_Interrupt_Mask   : DATA_TYPE    := x"FF";   -- Enable all Ints
96
    Enable_CPU_Halt          : boolean      := false;   -- Disable HALT pin
97
    Enable_Auto_Increment    : boolean      := false;   -- Modify indexed instr
98
    Reset_Level              : std_logic    := '0' );   -- Active reset level
99
  port(
100
    Clock                    : in  std_logic;
101
    Reset                    : in  std_logic;
102
    CPU_Halt                 : in  std_logic := '0';
103
    Interrupts               : in  INTERRUPT_BUNDLE;
104
    --
105
    Address                  : out ADDRESS_TYPE;
106
    Rd_Data                  : in  DATA_TYPE;
107
    Rd_Enable                : out std_logic;
108
    Wr_Data                  : out DATA_TYPE;
109
    Wr_Enable                : out std_logic );
110
end entity;
111
 
112
architecture rtl of Open8_CPU is
113
  subtype OPCODE_TYPE  is std_logic_vector(4 downto 0);
114
  subtype SUBOP_TYPE   is std_logic_vector(2 downto 0);
115
 
116
  -- Most of the ALU instructions are the same as their Opcode equivalents with
117
  -- three exceptions (for IDLE, UPP2, and MUL2)
118
  constant ALU_INC           : OPCODE_TYPE := "00000"; -- x"00"
119
  constant ALU_ADC           : OPCODE_TYPE := "00001"; -- x"01"
120
  constant ALU_TX0           : OPCODE_TYPE := "00010"; -- x"02"
121
  constant ALU_OR            : OPCODE_TYPE := "00011"; -- x"03"
122
  constant ALU_AND           : OPCODE_TYPE := "00100"; -- x"04"
123
  constant ALU_XOR           : OPCODE_TYPE := "00101"; -- x"05"
124
  constant ALU_ROL           : OPCODE_TYPE := "00110"; -- x"06"
125
  constant ALU_ROR           : OPCODE_TYPE := "00111"; -- x"07"
126
  constant ALU_DEC           : OPCODE_TYPE := "01000"; -- x"08"
127
  constant ALU_SBC           : OPCODE_TYPE := "01001"; -- x"09"
128
  constant ALU_ADD           : OPCODE_TYPE := "01010"; -- x"0A"
129
  constant ALU_STP           : OPCODE_TYPE := "01011"; -- x"0B"
130
  constant ALU_BTT           : OPCODE_TYPE := "01100"; -- x"0C"
131
  constant ALU_CLP           : OPCODE_TYPE := "01101"; -- x"0D"
132
  constant ALU_T0X           : OPCODE_TYPE := "01110"; -- x"0E"
133
  constant ALU_CMP           : OPCODE_TYPE := "01111"; -- x"0F"
134
  constant ALU_POP           : OPCODE_TYPE := "10001"; -- x"11"
135
  constant ALU_MUL           : OPCODE_TYPE := "10110"; -- x"16"
136
  constant ALU_UPP           : OPCODE_TYPE := "11000"; -- x"18"
137
  constant ALU_LDI           : OPCODE_TYPE := "11100"; -- x"1C"
138
  constant ALU_LDX           : OPCODE_TYPE := "11110"; -- x"1E"
139
 
140
  constant ALU_IDLE          : OPCODE_TYPE := "10000"; -- x"10"
141
  constant ALU_UPP2          : OPCODE_TYPE := "10010"; -- x"12"
142
  constant ALU_RFLG          : OPCODE_TYPE := "10011"; -- x"13"
143
 
144
  constant FL_ZERO           : integer := 0;
145
  constant FL_CARRY          : integer := 1;
146
  constant FL_NEG            : integer := 2;
147
  constant FL_INT_EN         : integer := 3;
148
  constant FL_GP1            : integer := 4;
149
  constant FL_GP2            : integer := 5;
150
  constant FL_GP3            : integer := 6;
151
  constant FL_GP4            : integer := 7;
152
 
153
  type ALU_CTRL_TYPE is record
154
    Oper                     : OPCODE_TYPE;
155
    Reg                      : SUBOP_TYPE;
156
    Data                     : DATA_TYPE;
157
  end record;
158
 
159
  constant ACCUM             : SUBOP_TYPE := "000";
160
  constant INT_FLAG          : SUBOP_TYPE := "011";
161
 
162
  -- There are only 8 byte-wide registers - and the write register is always 0,
163
  --  so there is little point in making a RAM out of this
164
  type REGFILE_TYPE is array (0 to 7) of DATA_TYPE;
165
 
166
  subtype FLAG_TYPE is DATA_TYPE;
167
 
168
  type PC_MODES is ( PC_IDLE, PC_REV1, PC_REV2, PC_INCR, PC_LOAD );
169
 
170
  type PC_CTRL_TYPE is record
171
    Oper                     : PC_MODES;
172
    Offset                   : DATA_TYPE;
173
    Addr                     : ADDRESS_TYPE;
174
  end record;
175
 
176
  type SP_MODES is ( SP_IDLE, SP_RSET, SP_POP, SP_PUSH );
177
 
178
  type SP_CTRL_TYPE is record
179
    Oper                     : SP_MODES;
180
    Addr                     : ADDRESS_TYPE;
181
  end record;
182
 
183
  type INT_CTRL_TYPE is record
184
    Mask_Set                 : std_logic;
185
    Mask_Data                : DATA_TYPE;
186
    Soft_Ints                : INTERRUPT_BUNDLE;
187
    Incr_ISR                 : std_logic;
188
  end record;
189
 
190
  type AS_MODES is ( ADDR_PC, ADDR_SP, ADDR_IMM, ADDR_ISR);
191
 
192
  type ADDR_CTRL_TYPE is record
193
    Src                      : AS_MODES;
194
  end record;
195
 
196
  type DP_MODES is ( DATA_IDLE, DATA_REG, DATA_FLAG, DATA_PC );
197
 
198
  type DATA_CTRL_TYPE is record
199
    Src                      : DP_MODES;
200
    Reg                      : SUBOP_TYPE;
201
  end record;
202
 
203
  signal Halt                : std_logic;
204
  signal ALU_Ctrl            : ALU_CTRL_TYPE;
205
  signal ALU_Regs            : REGFILE_TYPE;
206
  signal ALU_Flags           : FLAG_TYPE;
207
  signal PC_Ctrl             : PC_CTRL_TYPE;
208
  signal SP_Ctrl             : SP_CTRL_TYPE;
209
  signal AS_Ctrl             : ADDR_CTRL_TYPE;
210
  signal DP_Ctrl             : DATA_CTRL_TYPE;
211
  signal INT_Ctrl            : INT_CTRL_TYPE;
212
  signal Int_Req, Int_Ack    : std_logic;
213
  signal Int_RTI             : std_logic;
214
  signal Int_Mask            : DATA_TYPE;
215
  signal PC                  : ADDRESS_TYPE;
216
  signal SP                  : ADDRESS_TYPE;
217
  signal ISR                 : ADDRESS_TYPE;
218
  signal IMM                 : ADDRESS_TYPE;
219
begin
220
 
221
Halt_Disabled_fn: if( not Enable_CPU_Halt )generate
222
  Halt                       <= '0';
223
end generate;
224
 
225
Halt_Enabled_fn: if( Enable_CPU_Halt )generate
226
  Halt                       <= CPU_Halt;
227
end generate;
228
 
229
-------------------------------------------------------------------------------
230
-- ALU (Arithmetic / Logic Unit
231
-- Notes:
232
-- 1) Infers a multiplier in Xilinx/Altera parts - should be checked in others
233
-------------------------------------------------------------------------------
234
 
235
Open8_ALU : block is
236
 
237
  -- Preinitialization is for simulation only - check actual reset conditions
238
  signal Regfile_D, Regfile  : REGFILE_TYPE := (others => (others => '0') );
239
  signal Flags_D, Flags      : FLAG_TYPE    := (others => '0');
240
  signal Mult                : ADDRESS_TYPE := (others => '0');
241
 
242
  signal Sum                 : std_logic_vector(8 downto 0) := (others => '0');
243
  signal Addend_A, Addend_B  : DATA_TYPE    := (others => '0');
244
  signal Carry               : std_logic    := '0';
245
 
246
begin
247
 
248
  ALU_Regs                   <= Regfile;
249
  ALU_Flags                  <= Flags;
250
 
251
  ALU_proc: process( ALU_Ctrl, Regfile, Flags, Mult, Sum )
252
    variable Index             : integer range 0 to 7 := 0;
253
    variable Temp              : std_logic_vector(8 downto 0);
254
  begin
255
    Regfile_D                <= Regfile;
256
    Flags_D                  <= Flags;
257
    Addend_A                 <= x"00";
258
    Addend_B                 <= x"00";
259
    Carry                    <= '0';
260
 
261
    Temp                     := (others => '0');
262
    Index                    := conv_integer(ALU_Ctrl.Reg);
263
 
264
    case ALU_Ctrl.Oper is
265
      when ALU_INC | ALU_UPP => -- Rn = Rn + 1 : Flags N,C,Z
266
        Addend_A             <= x"01";
267
        Addend_B             <= Regfile(Index);
268
        Flags_D(FL_CARRY)    <= Sum(8);
269
        Regfile_D(Index)     <= Sum(7 downto 0);
270
        -- ALU_INC and ALU_UPP are essentially the same, except that ALU_UPP
271
        --  doesn't set the N or Z flags. Note that the MSB can be used to
272
        --  distinguish between the two ALU modes.
273
        if( ALU_Ctrl.Oper(4) = '0' )then
274
          Flags_D(FL_ZERO)   <= '0';
275
          if( Sum(7 downto 0) = 0 )then
276
            Flags_D(FL_ZERO) <= '1';
277
          end if;
278
          Flags_D(FL_NEG)    <= Sum(7);
279
        end if;
280
 
281
      when ALU_UPP2 => -- Rn = Rn + C
282
        Addend_A             <= x"00";
283
        Addend_B             <= Regfile(Index);
284
        Carry                <= Flags(FL_CARRY);
285
        Flags_D(FL_CARRY)    <= Sum(8);
286
        Regfile_D(Index)     <= Sum(7 downto 0);
287
 
288
      when ALU_ADC => -- R0 = R0 + Rn + C : Flags N,C,Z
289
        Addend_A             <= Regfile(0);
290
        Addend_B             <= Regfile(Index);
291
        Carry                <= Flags(FL_CARRY);
292
        Flags_D(FL_ZERO)     <= '0';
293
        if( Sum(7 downto 0) = 0 )then
294
          Flags_D(FL_ZERO)   <= '1';
295
        end if;
296
        Flags_D(FL_CARRY)    <= Sum(8);
297
        Flags_D(FL_NEG)      <= Sum(7);
298
        Regfile_D(0)         <= Sum(7 downto 0);
299
 
300
      when ALU_TX0 => -- R0 = Rn : Flags N,Z
301
        Temp                 := "0" & Regfile(Index);
302
        Flags_D(FL_ZERO)     <= '0';
303
        if( Temp(7 downto 0) = 0 )then
304
          Flags_D(FL_ZERO)   <= '1';
305
        end if;
306
        Flags_D(FL_NEG)      <= Temp(7);
307
        Regfile_D(0)         <= Temp(7 downto 0);
308
 
309
      when ALU_OR  => -- R0 = R0 | Rn : Flags N,Z
310
        Temp(7 downto 0)     := Regfile(0) or Regfile(Index);
311
        Flags_D(FL_ZERO)     <= '0';
312
        if( Temp(7 downto 0) = 0 )then
313
          Flags_D(FL_ZERO)   <= '1';
314
        end if;
315
        Flags_D(FL_NEG)      <= Temp(7);
316
        Regfile_D(0)         <= Temp(7 downto 0);
317
 
318
      when ALU_AND => -- R0 = R0 & Rn : Flags N,Z
319
        Temp(7 downto 0)     := Regfile(0) and Regfile(Index);
320
        Flags_D(FL_ZERO)     <= '0';
321
        if( Temp(7 downto 0) = 0 )then
322
          Flags_D(FL_ZERO)   <= '1';
323
        end if;
324
        Flags_D(FL_NEG)      <= Temp(7);
325
        Regfile_D(0)         <= Temp(7 downto 0);
326
 
327
      when ALU_XOR => -- R0 = R0 ^ Rn : Flags N,Z
328
        Temp(7 downto 0)     := Regfile(0) xor Regfile(Index);
329
        Flags_D(FL_ZERO)     <= '0';
330
        if( Temp(7 downto 0) = 0 )then
331
          Flags_D(FL_ZERO)   <= '1';
332
        end if;
333
        Flags_D(FL_NEG)      <= Temp(7);
334
        Regfile_D(0)         <= Temp(7 downto 0);
335
 
336
      when ALU_ROL => -- Rn = Rn<<1,C : Flags N,C,Z
337
        Temp                 := Regfile(Index) & Flags(FL_CARRY);
338
        Flags_D(FL_ZERO)     <= '0';
339
        if( Temp(7 downto 0) = 0 )then
340
          Flags_D(FL_ZERO)   <= '1';
341
        end if;
342
        Flags_D(FL_CARRY)    <= Temp(8);
343
        Flags_D(FL_NEG)      <= Temp(7);
344
        Regfile_D(Index)     <= Temp(7 downto 0);
345
 
346
      when ALU_ROR => -- Rn = C,Rn>>1 : Flags N,C,Z
347
        Temp                 := Regfile(Index)(0) & Flags(FL_CARRY) &
348
                                Regfile(Index)(7 downto 1);
349
        Flags_D(FL_ZERO)     <= '0';
350
        if( Temp(7 downto 0) = 0 )then
351
          Flags_D(FL_ZERO)   <= '1';
352
        end if;
353
        Flags_D(FL_CARRY)    <= Temp(8);
354
        Flags_D(FL_NEG)      <= Temp(7);
355
        Regfile_D(Index)     <= Temp(7 downto 0);
356
 
357
      when ALU_DEC => -- Rn = Rn - 1 : Flags N,C,Z
358
        Addend_A             <= Regfile(Index);
359
        Addend_B             <= x"FF";
360
        Flags_D(FL_ZERO)     <= '0';
361
        if( Sum(7 downto 0) = 0 )then
362
          Flags_D(FL_ZERO)   <= '1';
363
        end if;
364
        Flags_D(FL_CARRY)    <= Sum(8);
365
        Flags_D(FL_NEG)      <= Sum(7);
366
        Regfile_D(Index)     <= Sum(7 downto 0);
367
 
368
      when ALU_SBC => -- Rn = R0 - Rn - C : Flags N,C,Z
369
        Addend_A             <= Regfile(0);
370
        Addend_B             <= not Regfile(Index);
371
        Carry                <= Flags(FL_CARRY);
372
        Flags_D(FL_ZERO)     <= '0';
373
        if( Sum(7 downto 0) = 0 )then
374
          Flags_D(FL_ZERO)   <= '1';
375
        end if;
376
        Flags_D(FL_CARRY)    <= Sum(8);
377
        Flags_D(FL_NEG)      <= Sum(7);
378
        Regfile_D(0)         <= Sum(7 downto 0);
379
 
380
      when ALU_ADD => -- R0 = R0 + Rn : Flags N,C,Z
381
        Addend_A             <= Regfile(0);
382
        Addend_B             <= Regfile(Index);
383
        Flags_D(FL_CARRY)    <= Sum(8);
384
        Regfile_D(0)         <= Sum(7 downto 0);
385
        Flags_D(FL_ZERO)     <= '0';
386
        if( Sum(7 downto 0) = 0 )then
387
          Flags_D(FL_ZERO)   <= '1';
388
        end if;
389
        Flags_D(FL_NEG)      <= Sum(7);
390
 
391
      when ALU_STP => -- Sets bit(n) in the Flags register
392
        Flags_D(Index)       <= '1';
393
 
394
      when ALU_BTT => -- Z = !R0(N), N = R0(7)
395
        Flags_D(FL_ZERO)     <= not Regfile(0)(Index);
396
        Flags_D(FL_NEG)      <= Regfile(0)(7);
397
--        Temp                 := "0" & Regfile(Index);
398
--        Flags_D(FL_ZERO)     <= '0';
399
--        if( Temp(7 downto 0) = 0 )then
400
--          Flags_D(FL_ZERO)   <= '1';
401
--        end if;
402
--        Flags_D(FL_NEG)      <= Temp(7);
403
 
404
      when ALU_CLP => -- Clears bit(n) in the Flags register
405
        Flags_D(Index)         <= '0';
406
 
407
      when ALU_T0X => -- Rn = R0 : Flags N,Z
408
        Temp                 := "0" & Regfile(0);
409
        Flags_D(FL_ZERO)     <= '0';
410
        if( Temp(7 downto 0) = 0 )then
411
          Flags_D(FL_ZERO)   <= '1';
412
        end if;
413
        Flags_D(FL_NEG)      <= Temp(7);
414
        Regfile_D(Index)     <= Temp(7 downto 0);
415
 
416
      when ALU_CMP => -- Sets Flags on R0 - Rn : Flags N,C,Z
417
        Addend_A             <= Regfile(0);
418
        Addend_B             <= not Regfile(Index);
419
        Carry                <= '1';
420
        Flags_D(FL_ZERO)     <= '0';
421
        if( Sum(7 downto 0) = 0 )then
422
          Flags_D(FL_ZERO)   <= '1';
423
        end if;
424
        Flags_D(FL_CARRY)    <= Sum(8);
425
        Flags_D(FL_NEG)      <= Sum(7);
426
 
427
      when ALU_MUL => -- Stage 1 of 2 {R1:R0} = R0 * Rn : Flags Z
428
        Regfile_D(0)         <= Mult(7 downto 0);
429
        Regfile_D(1)         <= Mult(15 downto 8);
430
        Flags_D(FL_ZERO)     <= '0';
431
        if( Mult = 0 )then
432
          Flags_D(FL_ZERO)   <= '1';
433
        end if;
434
 
435
      when ALU_LDI | ALU_POP => -- Rn <= Data : Flags N,Z
436
        -- The POP instruction doesn't alter the flags, so we need to check
437
        if( ALU_Ctrl.Oper = ALU_LDI )then
438
          Flags_D(FL_ZERO)   <= '0';
439
          if( ALU_Ctrl.Data = 0 )then
440
            Flags_D(FL_ZERO) <= '1';
441
          end if;
442
          Flags_D(FL_NEG)    <= ALU_Ctrl.Data(7);
443
        end if;
444
        Regfile_D(Index)     <= ALU_Ctrl.Data;
445
 
446
      when ALU_LDX => -- R0 <= Data : Flags N,Z
447
        Flags_D(FL_ZERO)     <= '0';
448
        if( ALU_Ctrl.Data = 0 )then
449
          Flags_D(FL_ZERO)   <= '1';
450
        end if;
451
        Flags_D(FL_NEG)      <= ALU_Ctrl.Data(7);
452
        Regfile_D(0)         <= ALU_Ctrl.Data;
453
 
454
      when ALU_RFLG =>
455
        Flags_D              <= ALU_Ctrl.Data;
456
 
457
      when others => null;
458
    end case;
459
  end process;
460
 
461
  -- 8-bit Adder with carry
462
  Sum                        <= ("0" & Addend_A) + ("0" & Addend_B) + Carry;
463
 
464
  -- We need to infer a hardware multipler, so we create a special clocked
465
  --  process with no reset or clock enable
466
  M_Reg: process( Clock )
467
  begin
468
    if( rising_edge(Clock) )then
469
      Mult                   <= Regfile(0) *
470
                                Regfile(conv_integer(ALU_Ctrl.Reg));
471
    end if;
472
  end process;
473
 
474
  S_Regs: process( Reset, Clock )
475
  begin
476
    if( Reset = Reset_Level )then
477
      for i in 0 to 7 loop
478
        Regfile(i)           <= (others => '0');
479
      end loop;
480
      Flags                  <= x"00";
481
    elsif( rising_edge(Clock) )then
482
      if( Halt = '0' )then
483
        Regfile              <= Regfile_D;
484
        Flags                <= Flags_D;
485
      end if;
486
    end if;
487
  end process;
488
 
489
end block;
490
 
491
-------------------------------------------------------------------------------
492
-- Program Counter
493
-------------------------------------------------------------------------------
494
 
495
Open8_PC : block is
496
  -- Preinitialization is for simulation only - check actual reset conditions
497
  signal PC_Q                : ADDRESS_TYPE := (others => '0');
498
  signal Rewind_1_2n         : std_logic    := '0';
499
begin
500
 
501
  PC                         <= PC_Q;
502
 
503
  -- This sets the carry input on the "rewind" adder. If the rewind command is
504
  --  PC_REV2, then we clear the carry. Otherwise, we leave it high.
505
  Rewind_PC_Calc: process( PC_Ctrl )
506
  begin
507
    Rewind_1_2n              <= '1';
508
    if( PC_Ctrl.Oper = PC_REV2 )then
509
      Rewind_1_2n            <= '0';
510
    end if;
511
  end process;
512
 
513
  Program_Counter: process( Reset, Clock, PC_Ctrl )
514
    variable PC_Offset_SX    : ADDRESS_TYPE := x"0000";
515
  begin
516
    PC_Offset_SX(15 downto 8):= (others => PC_Ctrl.Offset(7));
517
    PC_Offset_SX(7 downto 0) := PC_Ctrl.Offset;
518
    if( Reset = Reset_Level )then
519
      PC_Q                   <= Program_Start_Addr;
520
    elsif( rising_edge(Clock) )then
521
      if( Halt = '0' )then
522
        case PC_Ctrl.Oper is
523
          when PC_IDLE =>
524
            null;
525
          when PC_REV1 | PC_REV2 =>
526
            PC_Q             <= PC_Q - 2 + Rewind_1_2n;
527
          when PC_INCR =>
528
            PC_Q             <= PC_Q + PC_Offset_SX - 2;
529
          when PC_LOAD =>
530
            PC_Q             <= PC_Ctrl.Addr;
531
        end case;
532
      end if;
533
    end if;
534
  end process;
535
 
536
end block;
537
 
538
-------------------------------------------------------------------------------
539
-- Stack Pointer
540
-------------------------------------------------------------------------------
541
 
542
Open8_SP : block is
543
  -- Preinitialization is for simulation only - check actual reset conditions
544
  signal SP_Q                : ADDRESS_TYPE := (others => '0');
545
begin
546
 
547
  SP                         <= SP_Q;
548
 
549
  Stack_Pointer: process( Reset, Clock )
550
  begin
551
    if( Reset = Reset_Level )then
552
      SP_Q                   <= Stack_Start_Addr;
553
    elsif( rising_edge(Clock) )then
554
      if( Halt = '0' )then
555
        case SP_Ctrl.Oper is
556
          when SP_IDLE => null;
557
          when SP_RSET => SP_Q <= SP_Ctrl.Addr;
558
          when SP_POP  => SP_Q <= SP_Q + 1;
559
          when SP_PUSH => SP_Q <= SP_Q - 1;
560
        end case;
561
      end if;
562
    end if;
563
  end process;
564
 
565
end block;
566
 
567
-------------------------------------------------------------------------------
568
-- Interrupt Controller
569
-------------------------------------------------------------------------------
570
 
571
Open8_INT : block is
572
 
573
  -- Preinitialization is for simulation only - check actual reset conditions
574
  constant INT_VECTOR_0      : ADDRESS_TYPE := ISR_Start_Addr;
575
  constant INT_VECTOR_1      : ADDRESS_TYPE := ISR_Start_Addr+2;
576
  constant INT_VECTOR_2      : ADDRESS_TYPE := ISR_Start_Addr+4;
577
  constant INT_VECTOR_3      : ADDRESS_TYPE := ISR_Start_Addr+6;
578
  constant INT_VECTOR_4      : ADDRESS_TYPE := ISR_Start_Addr+8;
579
  constant INT_VECTOR_5      : ADDRESS_TYPE := ISR_Start_Addr+10;
580
  constant INT_VECTOR_6      : ADDRESS_TYPE := ISR_Start_Addr+12;
581
  constant INT_VECTOR_7      : ADDRESS_TYPE := ISR_Start_Addr+14;
582
 
583
  signal i_Ints              : INTERRUPT_BUNDLE             := (others => '0');
584
  signal Pending_D           : INTERRUPT_BUNDLE             := (others => '0');
585
  signal Pending             : INTERRUPT_BUNDLE             := (others => '0');
586
  signal Wait_for_FSM        : std_logic := '0';
587
  signal Mask                : std_logic_vector(6 downto 0) := (others => '0');
588
  signal ISR_D, ISR_Q        : ADDRESS_TYPE                 := (others => '0');
589
 
590
  type INT_HIST is array (0 to 8) of integer range 0 to 7;
591
  signal History             : INT_HIST                     := (others => 0);
592
  signal Int_Trig            : std_logic                    := '0';
593
  signal Hist_Level          : integer range 0 to 7         := 0;
594
  signal Hist_Ptr            : integer range 0 to 8         := 0;
595
 
596
begin
597
  Int_Mask                   <= Mask & '1';
598
  ISR                        <= ISR_Q;
599
 
600
  Int_Mask_proc: process( Mask, Interrupts, INT_Ctrl )
601
    variable S_Mask          : std_logic_vector(7 downto 0);
602
  begin
603
    S_Mask                   := Mask & '1';
604
    for i in 0 to 7 loop
605
      i_Ints(i)              <= (Interrupts(i) or INT_Ctrl.Soft_Ints(i))
606
                                and S_Mask(i);
607
    end loop;
608
  end process;
609
 
610
  Int_Ctrl_proc: process( i_Ints, Pending, Wait_for_FSM, ISR_Q, INT_Ctrl,
611
                          History, Hist_Ptr )
612
  begin
613
    ISR_D                    <= ISR_Q;
614
    Pending_D                <= Pending;
615
    Int_Trig                 <= '0';
616
    Hist_Level               <= 0;
617
 
618
    -- Record any incoming interrupts to the pending buffer
619
    if( i_Ints > 0 )then
620
      Pending_D              <= i_Ints;
621
    end if;
622
 
623
    -- Incr_ISR allows the CPU Core to advance the vector address to pop the
624
    --  lower half of the address.
625
    if( INT_Ctrl.Incr_ISR = '1' )then
626
      ISR_D                  <= ISR_Q + 1;
627
    end if;
628
 
629
    -- Only mess with interrupt signals while the CPU core is not currently
630
    --  working with the ISR address (ie, not loading a new service vector)
631
    if( Wait_for_FSM = '0' and Pending > 0 )then
632
      if( Pending(0) = '1' and (Hist_Ptr = 0 or History(Hist_Ptr) > 0) )then
633
        ISR_D                <= INT_VECTOR_0;
634
        Pending_D(0)         <= '0';
635
        Hist_Level           <= 0;
636
        Int_Trig             <= '1';
637
      elsif( Pending(1) = '1' and (Hist_Ptr = 0 or History(Hist_Ptr) > 1) )then
638
        ISR_D                <= INT_VECTOR_1;
639
        Pending_D(1)         <= '0';
640
        Hist_Level           <= 1;
641
        Int_Trig             <= '1';
642
      elsif( Pending(2) = '1' and (Hist_Ptr = 0 or History(Hist_Ptr) > 2) )then
643
        ISR_D                <= INT_VECTOR_2;
644
        Pending_D(2)         <= '0';
645
        Hist_Level           <= 2;
646
        Int_Trig             <= '1';
647
      elsif( Pending(3) = '1' and (Hist_Ptr = 0 or History(Hist_Ptr) > 3) )then
648
        ISR_D                <= INT_VECTOR_3;
649
        Pending_D(3)         <= '0';
650
        Hist_Level           <= 3;
651
        Int_Trig             <= '1';
652
      elsif( Pending(4) = '1' and (Hist_Ptr = 0 or History(Hist_Ptr) > 4) )then
653
        ISR_D                <= INT_VECTOR_4;
654
        Pending_D(4)         <= '0';
655
        Hist_Level           <= 4;
656
        Int_Trig             <= '1';
657
      elsif( Pending(5) = '1' and (Hist_Ptr = 0 or History(Hist_Ptr) > 5) )then
658
        ISR_D                <= INT_VECTOR_5;
659
        Pending_D(5)         <= '0';
660
        Hist_Level           <= 5;
661
        Int_Trig             <= '1';
662
      elsif( Pending(6) = '1' and (Hist_Ptr = 0 or History(Hist_Ptr) > 6) )then
663
        ISR_D                <= INT_VECTOR_6;
664
        Pending_D(6)         <= '0';
665
        Hist_Level           <= 6;
666
        Int_Trig             <= '1';
667
      elsif( Pending(7) = '1' and (Hist_Ptr = 0 or History(Hist_Ptr) > 7) )then
668
        ISR_D                <= INT_VECTOR_7;
669
        Pending_D(7)         <= '0';
670
        Hist_Level           <= 7;
671
        Int_Trig             <= '1';
672
      end if;
673
    end if;
674
  end process;
675
 
676
  S_Regs: process( Reset, Clock )
677
  begin
678
    if( Reset = Reset_Level )then
679
      Int_Req                <= '0';
680
      Pending                <= x"00";
681
      Wait_for_FSM           <= '0';
682
      Mask                   <= Default_Interrupt_Mask(7 downto 1);
683
      ISR_Q                  <= INT_VECTOR_0;
684
      for i in 0 to 8 loop
685
        History(i)           <= 0;
686
      end loop;
687
      Hist_Ptr               <= 0;
688
    elsif( rising_edge(Clock) )then
689
      if( Halt = '0' )then
690
        Int_Req              <= Wait_for_FSM and (not Int_Ack);
691
        Pending              <= Pending_D;
692
        -- Reset the Wait_for_FSM flag on Int_Ack
693
        if( Int_Ack = '1' )then
694
          Wait_for_FSM       <= '0';
695
        -- Set the Wait_for_FSM flag on Int_Trig
696
        elsif( Int_Trig = '1' )then
697
          Wait_for_FSM       <= '1';
698
        end if;
699
         if( INT_Ctrl.Mask_Set = '1' )then
700
          Mask               <= INT_Ctrl.Mask_Data(7 downto 1);
701
          end if;
702
          ISR_Q                <= ISR_D;
703
          if( Int_Trig = '1' )then
704
            History(Hist_Ptr+1) <= Hist_Level;
705
            Hist_Ptr           <= Hist_Ptr + 1;
706
          elsif( Int_RTI = '1' and Hist_Ptr > 0 )then
707
            Hist_Ptr           <= Hist_Ptr - 1;
708
          end if;
709
      end if;
710
    end if;
711
  end process;
712
 
713
end block;
714
 
715
-------------------------------------------------------------------------------
716
-- State Logic / Instruction Decoding & Execution
717
-------------------------------------------------------------------------------
718
 
719
Open8_FSM : block is
720
 
721
  -- These are all the primary instructions/op-codes (upper 5-bits)
722
  constant OP_INC            : OPCODE_TYPE := "00000";
723
  constant OP_ADC            : OPCODE_TYPE := "00001";
724
  constant OP_TX0            : OPCODE_TYPE := "00010";
725
  constant OP_OR             : OPCODE_TYPE := "00011";
726
  constant OP_AND            : OPCODE_TYPE := "00100";
727
  constant OP_XOR            : OPCODE_TYPE := "00101";
728
  constant OP_ROL            : OPCODE_TYPE := "00110";
729
  constant OP_ROR            : OPCODE_TYPE := "00111";
730
  constant OP_DEC            : OPCODE_TYPE := "01000";
731
  constant OP_SBC            : OPCODE_TYPE := "01001";
732
  constant OP_ADD            : OPCODE_TYPE := "01010";
733
  constant OP_STP            : OPCODE_TYPE := "01011";
734
  constant OP_BTT            : OPCODE_TYPE := "01100";
735
  constant OP_CLP            : OPCODE_TYPE := "01101";
736
  constant OP_T0X            : OPCODE_TYPE := "01110";
737
  constant OP_CMP            : OPCODE_TYPE := "01111";
738
  constant OP_PSH            : OPCODE_TYPE := "10000";
739
  constant OP_POP            : OPCODE_TYPE := "10001";
740
  constant OP_BR0            : OPCODE_TYPE := "10010";
741
  constant OP_BR1            : OPCODE_TYPE := "10011";
742
  constant OP_DBNZ           : OPCODE_TYPE := "10100"; -- USR
743
  constant OP_INT            : OPCODE_TYPE := "10101";
744
  constant OP_MUL            : OPCODE_TYPE := "10110"; -- USR2
745
  constant OP_STK            : OPCODE_TYPE := "10111";
746
  constant OP_UPP            : OPCODE_TYPE := "11000";
747
  constant OP_STA            : OPCODE_TYPE := "11001";
748
  constant OP_STX            : OPCODE_TYPE := "11010";
749
  constant OP_STO            : OPCODE_TYPE := "11011";
750
  constant OP_LDI            : OPCODE_TYPE := "11100";
751
  constant OP_LDA            : OPCODE_TYPE := "11101";
752
  constant OP_LDX            : OPCODE_TYPE := "11110";
753
  constant OP_LDO            : OPCODE_TYPE := "11111";
754
 
755
  -- These are all specific sub-opcodes for OP_STK / 0xB8 (lower 3-bits)
756
  constant SOP_RSP           : SUBOP_TYPE := "000";
757
  constant SOP_RTS           : SUBOP_TYPE := "001";
758
  constant SOP_RTI           : SUBOP_TYPE := "010";
759
  constant SOP_BRK           : SUBOP_TYPE := "011";
760
  constant SOP_JMP           : SUBOP_TYPE := "100";
761
  constant SOP_SMSK          : SUBOP_TYPE := "101";
762
  constant SOP_GMSK          : SUBOP_TYPE := "110";
763
  constant SOP_JSR           : SUBOP_TYPE := "111";
764
 
765
  -- Preinitialization is for simulation only - check actual reset conditions
766
  type CPU_STATES is (
767
      -- Instruction fetch & Decode
768
    PIPE_FILL_0, PIPE_FILL_1, PIPE_FILL_2, INSTR_DECODE,
769
    -- Branching
770
    BRN_C1, DBNZ_C1, JMP_C1, JMP_C2,
771
    -- Loads
772
    LDA_C1, LDA_C2, LDA_C3, LDA_C4, LDI_C1, LDO_C1, LDX_C1, LDX_C2, LDX_C3,
773
    -- Stores
774
    STA_C1, STA_C2, STA_C3, STO_C1, STO_C2, STX_C1, STX_C2,
775
    -- 2-cycle math
776
    MUL_C1, UPP_C1,
777
    -- Stack
778
    PSH_C1, POP_C1, POP_C2, POP_C3, POP_C4,
779
    -- Subroutines & Interrupts
780
    WAIT_FOR_INT, ISR_C1, ISR_C2, ISR_C3, JSR_C1, JSR_C2,
781
    RTS_C1, RTS_C2, RTS_C3, RTS_C4, RTS_C5, RTI_C6,
782
    -- Debugging
783
    BRK_C1 );
784
 
785
  signal CPU_Next_State      : CPU_STATES := PIPE_FILL_0;
786
  signal CPU_State           : CPU_STATES := PIPE_FILL_0;
787
 
788
  type CACHE_MODES is (CACHE_IDLE, CACHE_INSTR, CACHE_OPER1, CACHE_OPER2,
789
                       CACHE_PREFETCH );
790
  signal Cache_Ctrl          : CACHE_MODES := CACHE_IDLE;
791
 
792
  signal Opcode              : OPCODE_TYPE := (others => '0');
793
  signal SubOp, SubOp_p1     : SUBOP_TYPE  := (others => '0');
794
  -- synthesis translate_off
795
  signal Instruction         : DATA_TYPE   := (others => '0');
796
  -- synthesis translate_on
797
  signal Prefetch            : DATA_TYPE   := (others => '0');
798
  signal Operand1, Operand2  : DATA_TYPE   := (others => '0');
799
 
800
  signal Instr_Prefetch      : std_logic   := '0';
801
 
802
  signal Ack_D, Ack_Q, Ack_Q1: std_logic   := '0';
803
  signal Int_RTI_D           : std_logic   := '0';
804
 
805
begin
806
 
807
  -- synthesis translate_off
808
  Instruction                <= Opcode & SubOp;
809
  -- synthesis translate_on
810
 
811
  State_Logic: process(CPU_State, ALU_Regs, ALU_Flags, Int_Mask, Opcode,
812
                       SubOp , SubOp_p1, Operand1, Operand2, Int_Req )
813
    variable Reg, Reg_1      : integer range 0 to 7 := 0;
814
    variable Offset_SX       : ADDRESS_TYPE;
815
  begin
816
    CPU_Next_State           <= CPU_State;
817
    Cache_Ctrl               <= CACHE_IDLE;
818
    --
819
    ALU_Ctrl.Oper            <= ALU_IDLE;
820
    ALU_Ctrl.Reg             <= ACCUM;
821
    ALU_Ctrl.Data            <= x"00";
822
    --
823
    PC_Ctrl.Oper             <= PC_IDLE;
824
 
825
    PC_Ctrl.Offset           <= x"03";
826
    PC_Ctrl.Addr             <= x"0000";
827
    --
828
    SP_Ctrl.Oper             <= SP_IDLE;
829
    --
830
    AS_Ctrl.Src              <= ADDR_PC;
831
    IMM                      <= x"0000";
832
    --
833
    DP_Ctrl.Src              <= DATA_IDLE;
834
    DP_Ctrl.Reg              <= ACCUM;
835
    --
836
    INT_Ctrl.Mask_Set        <= '0';
837
    INT_Ctrl.Soft_Ints       <= x"00";
838
    INT_Ctrl.Incr_ISR        <= '0';
839
    Ack_D                    <= '0';
840
    Int_RTI_D                <= '0';
841
 
842
    -- Assign the most common value of Reg and Reg1 outside the case structure
843
    --  to simplify things.
844
    Reg                      := conv_integer(SubOp);
845
    Reg_1                    := conv_integer(SubOp_p1);
846
    Offset_SX(15 downto 0)   := (others => Operand1(7));
847
    Offset_SX(7 downto 0)    := Operand1;
848
 
849
    case CPU_State is
850
-------------------------------------------------------------------------------
851
-- Initial Instruction fetch & decode
852
-------------------------------------------------------------------------------
853
      when PIPE_FILL_0 =>
854
        CPU_Next_State       <= PIPE_FILL_1;
855
        PC_Ctrl.Oper         <= PC_INCR;
856
 
857
      when PIPE_FILL_1 =>
858
        CPU_Next_State       <= PIPE_FILL_2;
859
        PC_Ctrl.Oper         <= PC_INCR;
860
 
861
      when PIPE_FILL_2 =>
862
        CPU_Next_State       <= INSTR_DECODE;
863
        Cache_Ctrl           <= CACHE_INSTR;
864
        PC_Ctrl.Oper         <= PC_INCR;
865
 
866
      when INSTR_DECODE =>
867
        CPU_Next_State       <= INSTR_DECODE;
868
        Cache_Ctrl           <= CACHE_INSTR;
869
 
870
        case Opcode is
871
          when OP_PSH =>
872
            CPU_Next_State   <= PSH_C1;
873
            Cache_Ctrl       <= CACHE_PREFETCH;
874
            PC_Ctrl.Oper     <= PC_REV1;
875
            DP_Ctrl.Src      <= DATA_REG;
876
            DP_Ctrl.Reg      <= SubOp;
877
 
878
          when OP_POP =>
879
            CPU_Next_State   <= POP_C1;
880
            Cache_Ctrl       <= CACHE_PREFETCH;
881
            PC_Ctrl.Oper     <= PC_REV2;
882
            SP_Ctrl.Oper     <= SP_POP;
883
 
884
          when OP_BR0 | OP_BR1 =>
885
            CPU_Next_State   <= BRN_C1;
886
            Cache_Ctrl       <= CACHE_OPER1;
887
            PC_Ctrl.Oper     <= PC_INCR;
888
 
889
          when OP_DBNZ =>
890
            CPU_Next_State   <= DBNZ_C1;
891
            Cache_Ctrl       <= CACHE_OPER1;
892
            PC_Ctrl.Oper     <= PC_INCR;
893
            ALU_Ctrl.Oper    <= ALU_DEC;
894
            ALU_Ctrl.Reg     <= SubOp;
895
 
896
          when OP_INT =>
897
            PC_Ctrl.Oper     <= PC_INCR;
898
            if( Int_Mask(Reg) = '1' )then
899
              CPU_Next_State <= WAIT_FOR_INT;
900
              INT_Ctrl.Soft_Ints(Reg) <= '1';
901
            end if;
902
 
903
          when OP_STK =>
904
            case SubOp is
905
              when SOP_RSP  =>
906
                PC_Ctrl.Oper <= PC_INCR;
907
                SP_Ctrl.Oper <= SP_RSET;
908
 
909
              when SOP_RTS | SOP_RTI =>
910
                CPU_Next_State <= RTS_C1;
911
                Cache_Ctrl   <= CACHE_IDLE;
912
                SP_Ctrl.Oper <= SP_POP;
913
 
914
              when SOP_BRK  =>
915
                CPU_Next_State <= BRK_C1;
916
                PC_Ctrl.Oper <= PC_REV2;
917
 
918
              when SOP_JMP  =>
919
                CPU_Next_State <= JMP_C1;
920
                Cache_Ctrl   <= CACHE_OPER1;
921
 
922
              when SOP_SMSK =>
923
                PC_Ctrl.Oper <= PC_INCR;
924
                INT_Ctrl.Mask_Set <= '1';
925
 
926
              when SOP_GMSK =>
927
                PC_Ctrl.Oper <= PC_INCR;
928
                ALU_Ctrl.Oper<= ALU_LDI;
929
                ALU_Ctrl.Reg <= ACCUM;
930
                ALU_Ctrl.Data<= Int_Mask;
931
 
932
              when SOP_JSR =>
933
                CPU_Next_State <= JSR_C1;
934
                Cache_Ctrl   <= CACHE_OPER1;
935
                DP_Ctrl.Src  <= DATA_PC;
936
                DP_Ctrl.Reg  <= ACCUM+1;
937
 
938
              when others => null;
939
            end case;
940
 
941
          when OP_MUL =>
942
            CPU_Next_State   <= MUL_C1;
943
            Cache_Ctrl       <= CACHE_PREFETCH;
944
 
945
            -- We need to back the PC up by 1, and allow it to refill. An
946
            --  unfortunate consequence of the pipelining. We can get away with
947
            --  only 1 extra clock by pre-fetching the next instruction, though
948
            PC_Ctrl.Oper     <= PC_REV1;
949
            -- Multiplication is automatic, but requires a single clock cycle.
950
            --  We need to specify the register for Rn (R1:R0 = R0 * Rn) now,
951
            --   but will issue the multiply command on the next clock to copy
952
            --   the results to the specified register.
953
            ALU_Ctrl.Oper    <= ALU_IDLE;
954
            ALU_Ctrl.Reg     <= SubOp; -- Rn
955
 
956
          when OP_UPP =>
957
            CPU_Next_State   <= UPP_C1;
958
            Cache_Ctrl       <= CACHE_PREFETCH;
959
            PC_Ctrl.Oper     <= PC_REV1;
960
            ALU_Ctrl.Oper    <= Opcode;
961
            ALU_Ctrl.Reg     <= SubOp;
962
 
963
          when OP_LDA =>
964
            CPU_Next_State   <= LDA_C1;
965
            Cache_Ctrl       <= CACHE_OPER1;
966
 
967
          when OP_LDI =>
968
            CPU_Next_State   <= LDI_C1;
969
            Cache_Ctrl       <= CACHE_OPER1;
970
            PC_Ctrl.Oper     <= PC_INCR;
971
 
972
          when OP_LDO =>
973
            CPU_Next_State   <= LDO_C1;
974
            Cache_Ctrl       <= CACHE_OPER1;
975
            PC_Ctrl.Oper     <= PC_REV2;
976
 
977
          when OP_LDX =>
978
            CPU_Next_State   <= LDX_C1;
979
            PC_Ctrl.Oper     <= PC_REV2;
980
            AS_Ctrl.Src      <= ADDR_IMM;
981
            -- If auto-increment is disabled, use the specified register pair,
982
            --  otherwise, for an odd:even pair, and issue the first half of
983
            --  a UPP instruction to the ALU
984
            if( not Enable_Auto_Increment )then
985
              IMM            <= ALU_Regs(Reg_1) & ALU_Regs(Reg);
986
            else
987
              Reg            := conv_integer(SubOp(2 downto 1) & '0');
988
              Reg_1          := conv_integer(SubOp(2 downto 1) & '1');
989
              IMM            <= ALU_Regs(Reg_1) & ALU_Regs(Reg);
990
              if( SubOp(0) = '1' )then
991
                ALU_Ctrl.Oper<= ALU_UPP;
992
                ALU_Ctrl.Reg <= SubOp(2 downto 1) & '0';
993
              end if;
994
            end if;
995
 
996
          when OP_STA =>
997
            CPU_Next_State   <= STA_C1;
998
            Cache_Ctrl       <= CACHE_OPER1;
999
 
1000
          when OP_STO =>
1001
            CPU_Next_State   <= STO_C1;
1002
            Cache_Ctrl       <= CACHE_OPER1;
1003
            PC_Ctrl.Oper     <= PC_REV2;
1004
            DP_Ctrl.Src      <= DATA_REG;
1005
            DP_Ctrl.Reg      <= ACCUM;
1006
 
1007
          when OP_STX =>
1008
            CPU_Next_State   <= STX_C1;
1009
            Cache_Ctrl       <= CACHE_PREFETCH;
1010
            PC_Ctrl.Oper     <= PC_REV2;
1011
            DP_Ctrl.Src      <= DATA_REG;
1012
            DP_Ctrl.Reg      <= ACCUM;
1013
 
1014
          when others =>
1015
            PC_Ctrl.Oper     <= PC_INCR;
1016
            ALU_Ctrl.Oper    <= Opcode;
1017
            ALU_Ctrl.Reg     <= SubOp;
1018
 
1019
        end case;
1020
 
1021
-------------------------------------------------------------------------------
1022
-- Program Control (BR0_C1, BR1_C1, DBNZ_C1, JMP )
1023
-------------------------------------------------------------------------------
1024
 
1025
      when BRN_C1 =>
1026
        CPU_Next_State       <= INSTR_DECODE;
1027
        Cache_Ctrl           <= CACHE_INSTR;
1028
        PC_Ctrl.Oper         <= PC_INCR;
1029
        if( ALU_Flags(Reg) = Opcode(0) )then
1030
          CPU_Next_State     <= PIPE_FILL_0;
1031
          Cache_Ctrl         <= CACHE_IDLE;
1032
          PC_Ctrl.Offset     <= Operand1;
1033
        end if;
1034
 
1035
      when DBNZ_C1 =>
1036
        CPU_Next_State       <= INSTR_DECODE;
1037
        Cache_Ctrl           <= CACHE_INSTR;
1038
        PC_Ctrl.Oper         <= PC_INCR;
1039
        if( ALU_Flags(FL_ZERO) = '0' )then
1040
          CPU_Next_State     <= PIPE_FILL_0;
1041
          Cache_Ctrl         <= CACHE_IDLE;
1042
          PC_Ctrl.Offset     <= Operand1;
1043
        end if;
1044
 
1045
      when JMP_C1 =>
1046
        CPU_Next_State       <= JMP_C2;
1047
        Cache_Ctrl           <= CACHE_OPER2;
1048
 
1049
      when JMP_C2 =>
1050
        CPU_Next_State       <= PIPE_FILL_0;
1051
        PC_Ctrl.Oper         <= PC_LOAD;
1052
        PC_Ctrl.Addr         <= Operand2 & Operand1;
1053
 
1054
-------------------------------------------------------------------------------
1055
-- Data Storage - Load from memory (LDA, LDI, LDO, LDX)
1056
-------------------------------------------------------------------------------
1057
 
1058
      when LDA_C1 =>
1059
        CPU_Next_State       <= LDA_C2;
1060
        Cache_Ctrl           <= CACHE_OPER2;
1061
 
1062
      when LDA_C2 =>
1063
        CPU_Next_State       <= LDA_C3;
1064
        AS_Ctrl.Src          <= ADDR_IMM;
1065
        IMM                  <= Operand2 & Operand1;
1066
 
1067
      when LDA_C3 =>
1068
        CPU_Next_State       <= LDA_C4;
1069
        PC_Ctrl.Oper         <= PC_INCR;
1070
 
1071
      when LDA_C4 =>
1072
        CPU_Next_State       <= LDI_C1;
1073
        Cache_Ctrl           <= CACHE_OPER1;
1074
        PC_Ctrl.Oper         <= PC_INCR;
1075
 
1076
      when LDI_C1 =>
1077
        CPU_Next_State       <= INSTR_DECODE;
1078
        Cache_Ctrl           <= CACHE_INSTR;
1079
        PC_Ctrl.Oper         <= PC_INCR;
1080
        ALU_Ctrl.Oper        <= ALU_LDI;
1081
        ALU_Ctrl.Reg         <= SubOp;
1082
        ALU_Ctrl.Data        <= Operand1;
1083
 
1084
      when LDO_C1 =>
1085
        CPU_Next_State       <= LDX_C1;
1086
        AS_Ctrl.Src          <= ADDR_IMM;
1087
        PC_Ctrl.Oper         <= PC_INCR;
1088
        if( Enable_Auto_Increment )then
1089
          Reg                := conv_integer(SubOp(2 downto 1) & '0');
1090
          Reg_1              := conv_integer(SubOp(2 downto 1) & '1');
1091
          IMM                <= (ALU_Regs(Reg_1) & ALU_Regs(Reg)) + Offset_SX;
1092
          if( SubOp(0) = '1' )then
1093
            ALU_Ctrl.Oper<= ALU_UPP;
1094
            ALU_Ctrl.Reg <= SubOp(2 downto 1) & '0';
1095
          end if;
1096
        else
1097
          IMM                <= (ALU_Regs(Reg_1) & ALU_Regs(Reg)) + Offset_SX;
1098
        end if;
1099
 
1100
      when LDX_C1 =>
1101
        CPU_Next_State       <= LDX_C2;
1102
        PC_Ctrl.Oper         <= PC_INCR;
1103
 
1104
      when LDX_C2 =>
1105
        CPU_Next_State       <= LDX_C3;
1106
        PC_Ctrl.Oper         <= PC_INCR;
1107
        Cache_Ctrl           <= CACHE_OPER1;
1108
 
1109
      when LDX_C3 =>
1110
        CPU_Next_State       <= INSTR_DECODE;
1111
        Cache_Ctrl           <= CACHE_INSTR;
1112
        PC_Ctrl.Oper         <= PC_INCR;
1113
        ALU_Ctrl.Oper        <= ALU_LDX;
1114
        ALU_Ctrl.Reg         <= ACCUM;
1115
        ALU_Ctrl.Data        <= Operand1;
1116
 
1117
-------------------------------------------------------------------------------
1118
-- Data Storage - Store to memory (STA, STO, STX)
1119
-------------------------------------------------------------------------------
1120
      when STA_C1 =>
1121
        CPU_Next_State       <= STA_C2;
1122
        Cache_Ctrl           <= CACHE_OPER2;
1123
        DP_Ctrl.Src          <= DATA_REG;
1124
        DP_Ctrl.Reg          <= SubOp;
1125
 
1126
      when STA_C2 =>
1127
        CPU_Next_State       <= STA_C3;
1128
        AS_Ctrl.Src          <= ADDR_IMM;
1129
        IMM                  <= Operand2 & Operand1;
1130
        PC_Ctrl.Oper         <= PC_INCR;
1131
 
1132
      when STA_C3 =>
1133
        CPU_Next_State       <= PIPE_FILL_2;
1134
        Cache_Ctrl           <= CACHE_PREFETCH;
1135
        PC_Ctrl.Oper         <= PC_INCR;
1136
 
1137
      when STO_C1 =>
1138
        Cache_Ctrl           <= CACHE_PREFETCH;
1139
        PC_Ctrl.Oper         <= PC_INCR;
1140
        AS_Ctrl.Src          <= ADDR_IMM;
1141
        -- If auto-increment is disabled, just load the registers normally
1142
        if( not Enable_Auto_Increment )then
1143
          CPU_Next_State     <= PIPE_FILL_1;
1144
          IMM                <= (ALU_Regs(Reg_1) & ALU_Regs(Reg)) + Offset_SX;
1145
        -- Otherwise, enforce the even register rule, and check the LSB to see
1146
        --  if we should perform the auto-increment on the register pair
1147
        else
1148
          CPU_Next_State     <= PIPE_FILL_0;
1149
          Reg                := conv_integer(SubOp(2 downto 1) & '0');
1150
          Reg_1              := conv_integer(SubOp(2 downto 1) & '1');
1151
          IMM                <= (ALU_Regs(Reg_1) & ALU_Regs(Reg)) + Offset_SX;
1152
          if( SubOp(0) = '1' )then
1153
            CPU_Next_State   <= STO_C2;
1154
            ALU_Ctrl.Oper    <= ALU_UPP;
1155
            ALU_Ctrl.Reg     <= SubOp(2 downto 1) & '0';
1156
          end if;
1157
        end if;
1158
 
1159
      when STO_C2 =>
1160
        CPU_Next_State       <= PIPE_FILL_1;
1161
        PC_Ctrl.Oper         <= PC_INCR;
1162
        ALU_Ctrl.Oper        <= ALU_UPP2;
1163
        ALU_Ctrl.Reg         <= SubOp(2 downto 1) & '1';
1164
 
1165
      when STX_C1 =>
1166
        PC_Ctrl.Oper         <= PC_INCR;
1167
        AS_Ctrl.Src          <= ADDR_IMM;
1168
        -- If auto-increment is disabled, just load the registers normally
1169
        if( not Enable_Auto_Increment )then
1170
          CPU_Next_State     <= PIPE_FILL_1;
1171
          IMM                <= (ALU_Regs(Reg_1) & ALU_Regs(Reg));
1172
        -- Otherwise, enforce the even register rule, and check the LSB to see
1173
        --  if we should perform the auto-increment on the register pair
1174
        else
1175
          CPU_Next_State     <= PIPE_FILL_1;
1176
          Reg                := conv_integer(SubOp(2 downto 1) & '0');
1177
          Reg_1              := conv_integer(SubOp(2 downto 1) & '1');
1178
          IMM                <= (ALU_Regs(Reg_1) & ALU_Regs(Reg));
1179
          if( SubOp(0) = '1' )then
1180
            CPU_Next_State   <= STX_C2;
1181
            ALU_Ctrl.Oper    <= ALU_UPP;
1182
            ALU_Ctrl.Reg     <= SubOp(2 downto 1) & '0';
1183
          end if;
1184
        end if;
1185
 
1186
      when STX_C2 =>
1187
        CPU_Next_State       <= PIPE_FILL_2;
1188
        PC_Ctrl.Oper         <= PC_INCR;
1189
        ALU_Ctrl.Oper        <= ALU_UPP2;
1190
        ALU_Ctrl.Reg         <= SubOp(2 downto 1) & '1';
1191
 
1192
-------------------------------------------------------------------------------
1193
-- Multi-Cycle Math Operations (UPP, MUL)
1194
-------------------------------------------------------------------------------
1195
      -- Because we have to backup the pipeline by 1 to refetch the 2nd
1196
      --  instruction/first operand, we have to return through PF2
1197
 
1198
      when MUL_C1 =>
1199
        CPU_Next_State       <= PIPE_FILL_2;
1200
        PC_Ctrl.Oper         <= PC_INCR;
1201
        ALU_Ctrl.Oper        <= ALU_MUL;
1202
 
1203
      when UPP_C1 =>
1204
        CPU_Next_State       <= PIPE_FILL_2;
1205
        PC_Ctrl.Oper         <= PC_INCR;
1206
        ALU_Ctrl.Oper        <= ALU_UPP2;
1207
        ALU_Ctrl.Reg         <= SubOp_p1;
1208
 
1209
-------------------------------------------------------------------------------
1210
-- Basic Stack Manipulation (PSH, POP, RSP)
1211
-------------------------------------------------------------------------------
1212
      when PSH_C1 =>
1213
        CPU_Next_State       <= PIPE_FILL_1;
1214
        AS_Ctrl.Src          <= ADDR_SP;
1215
        SP_Ctrl.Oper         <= SP_PUSH;
1216
 
1217
      when POP_C1 =>
1218
        CPU_Next_State       <= POP_C2;
1219
        AS_Ctrl.Src          <= ADDR_SP;
1220
 
1221
      when POP_C2 =>
1222
        CPU_Next_State       <= POP_C3;
1223
        PC_Ctrl.Oper         <= PC_INCR;
1224
 
1225
      when POP_C3 =>
1226
        CPU_Next_State       <= POP_C4;
1227
        Cache_Ctrl           <= CACHE_OPER1;
1228
        PC_Ctrl.Oper         <= PC_INCR;
1229
 
1230
      when POP_C4 =>
1231
        CPU_Next_State       <= INSTR_DECODE;
1232
        Cache_Ctrl           <= CACHE_INSTR;
1233
        PC_Ctrl.Oper         <= PC_INCR;
1234
        ALU_Ctrl.Oper        <= ALU_POP;
1235
        ALU_Ctrl.Reg         <= SubOp;
1236
        ALU_Ctrl.Data        <= Operand1;
1237
 
1238
-------------------------------------------------------------------------------
1239
-- Subroutines & Interrupts (RTS, JSR)
1240
-------------------------------------------------------------------------------
1241
      when WAIT_FOR_INT => -- For soft interrupts only, halt the PC
1242
        CPU_Next_State       <= WAIT_FOR_INT;
1243
 
1244
      when ISR_C1 =>
1245
        CPU_Next_State       <= ISR_C2;
1246
        AS_Ctrl.Src          <= ADDR_ISR;
1247
        INT_Ctrl.Incr_ISR    <= '1';
1248
--        PC_Ctrl.Oper         <= PC_INCR;
1249
        -- Rewind the PC by 3 to compensate for the pipeline registers
1250
--        PC_Ctrl.Offset       <= x"FF";
1251
 
1252
      when ISR_C2 =>
1253
        CPU_Next_State       <= ISR_C3;
1254
        AS_Ctrl.Src          <= ADDR_ISR;
1255
        DP_Ctrl.Src          <= DATA_FLAG;
1256
 
1257
      when ISR_C3 =>
1258
        CPU_Next_State       <= JSR_C1;
1259
        Cache_Ctrl           <= CACHE_OPER1;
1260
        AS_Ctrl.Src          <= ADDR_SP;
1261
        SP_Ctrl.Oper         <= SP_PUSH;
1262
        DP_Ctrl.Src          <= DATA_PC;
1263
        DP_Ctrl.Reg          <= ACCUM+1;
1264
        ALU_Ctrl.Oper        <= ALU_STP;
1265
        ALU_Ctrl.Reg         <= INT_FLAG;
1266
        Ack_D                <= '1';
1267
 
1268
      when JSR_C1 =>
1269
        CPU_Next_State       <= JSR_C2;
1270
        Cache_Ctrl           <= CACHE_OPER2;
1271
        AS_Ctrl.Src          <= ADDR_SP;
1272
        SP_Ctrl.Oper         <= SP_PUSH;
1273
        DP_Ctrl.Src          <= DATA_PC;
1274
        DP_Ctrl.Reg          <= ACCUM;
1275
 
1276
      when JSR_C2 =>
1277
        CPU_Next_State       <= PIPE_FILL_0;
1278
        AS_Ctrl.Src          <= ADDR_SP;
1279
        SP_Ctrl.Oper         <= SP_PUSH;
1280
        PC_Ctrl.Oper         <= PC_LOAD;
1281
        PC_Ctrl.Addr         <= Operand2 & Operand1;
1282
 
1283
      when RTS_C1 =>
1284
        CPU_Next_State       <= RTS_C2;
1285
        AS_Ctrl.Src          <= ADDR_SP;
1286
        SP_Ctrl.Oper         <= SP_POP;
1287
 
1288
      when RTS_C2 =>
1289
        CPU_Next_State       <= RTS_C3;
1290
        AS_Ctrl.Src          <= ADDR_SP;
1291
        -- if this is an RTI, then we need to POP the flags
1292
        if( SubOp = SOP_RTI )then
1293
          SP_Ctrl.Oper       <= SP_POP;
1294
        end if;
1295
 
1296
      when RTS_C3 =>
1297
        CPU_Next_State       <= RTS_C4;
1298
        Cache_Ctrl           <= CACHE_OPER1;
1299
        -- It doesn't really matter what is on the address bus for RTS, while
1300
        --  it does for RTI, so we make this the default
1301
        AS_Ctrl.Src          <= ADDR_SP;
1302
 
1303
      when RTS_C4 =>
1304
        CPU_Next_State       <= RTS_C5;
1305
        Cache_Ctrl           <= CACHE_OPER2;
1306
 
1307
      when RTS_C5 =>
1308
        CPU_Next_State       <= PIPE_FILL_0;
1309
        PC_Ctrl.Oper         <= PC_LOAD;
1310
        PC_Ctrl.Addr         <= Operand2 & Operand1;
1311
        if( SubOp = SOP_RTI )then
1312
          CPU_Next_State     <= RTI_C6;
1313
          Cache_Ctrl         <= CACHE_OPER1;
1314
        end if;
1315
 
1316
      when RTI_C6 =>
1317
        CPU_Next_State       <= PIPE_FILL_1;
1318
        PC_Ctrl.Oper         <= PC_INCR;
1319
        ALU_Ctrl.Oper        <= ALU_RFLG;
1320
        ALU_Ctrl.Data        <= Operand1;
1321
        PC_Ctrl.Oper         <= PC_INCR;
1322
        Int_RTI_D            <= '1';
1323
 
1324
-------------------------------------------------------------------------------
1325
-- Debugging (BRK) Performs a 5-clock NOP
1326
-------------------------------------------------------------------------------
1327
      when BRK_C1 =>
1328
        CPU_Next_State       <= PIPE_FILL_0;
1329
 
1330
      when others => null;
1331
    end case;
1332
 
1333
    -- Interrupt service routines can only begin during the decode and wait
1334
    --  states to avoid corruption due to incomplete instruction execution
1335
    if( Int_Req = '1' )then
1336
      if( CPU_State = INSTR_DECODE or CPU_State = WAIT_FOR_INT )then
1337
        CPU_Next_State       <= ISR_C1;
1338
        PC_Ctrl.Oper         <= PC_INCR;
1339
        -- Rewind the PC by 3 to compensate for the pipeline registers
1340
        PC_Ctrl.Offset       <= x"FF";
1341
      end if;
1342
    end if;
1343
 
1344
  end process;
1345
 
1346
  S_Regs: process( Reset, Clock )
1347
  begin
1348
    if( Reset = Reset_Level )then
1349
      CPU_State              <= PIPE_FILL_0;
1350
      Opcode                 <= OP_INC;
1351
      SubOp                  <= ACCUM;
1352
      SubOp_p1               <= ACCUM;
1353
      Operand1               <= x"00";
1354
      Operand2               <= x"00";
1355
      Instr_Prefetch         <= '0';
1356
      Prefetch               <= x"00";
1357
 
1358
      Ack_Q                  <= '0';
1359
      Ack_Q1                 <= '0';
1360
      Int_Ack                <= '0';
1361
      Int_RTI                <= '0';
1362
 
1363
    elsif( rising_edge(Clock) )then
1364
      if( Halt = '0' )then
1365
        CPU_State            <= CPU_Next_State;
1366
        case Cache_Ctrl is
1367
          when CACHE_INSTR =>
1368
            Opcode           <= Rd_Data(7 downto 3);
1369
            SubOp            <= Rd_Data(2 downto 0);
1370
            SubOp_p1         <= Rd_Data(2 downto 0) + 1;
1371
            if( Instr_Prefetch = '1' )then
1372
              Opcode         <= Prefetch(7 downto 3);
1373
              SubOp          <= Prefetch(2 downto 0);
1374
              SubOp_p1       <= Prefetch(2 downto 0) + 1;
1375
              Instr_Prefetch <= '0';
1376
            end if;
1377
          when CACHE_OPER1 =>
1378
            Operand1         <= Rd_Data;
1379
          when CACHE_OPER2 =>
1380
            Operand2         <= Rd_Data;
1381
          when CACHE_PREFETCH =>
1382
            Prefetch         <= Rd_Data;
1383
            Instr_Prefetch   <= '1';
1384
          when CACHE_IDLE =>
1385
            null;
1386
        end case;
1387
 
1388
        -- Interrupt signalling registers
1389
        Ack_Q                <= Ack_D;
1390
        Ack_Q1               <= Ack_Q;
1391
        Int_Ack              <= Ack_Q1;
1392
        Int_RTI              <= Int_RTI_D;
1393
      end if;
1394
    end if;
1395
  end process;
1396
 
1397
-------------------------------------------------------------------------------
1398
-- Fixed in-line statements for the interrupt mask, and stack pointer address
1399
-------------------------------------------------------------------------------
1400
 
1401
-- The interrupt control mask is always sourced out of R0
1402
  INT_Ctrl.Mask_Data         <= ALU_Regs(conv_integer(ACCUM));
1403
 
1404
-- The original RSP instruction simply reset the stack pointer to the preset
1405
--  address set at compile time. However, with little extra effort, we can
1406
--  modify the instruction to allow the stack pointer to be moved anywhere in
1407
--  the memory map. Since RSP can't have an sub-opcode, R1:R0 was chosen as
1408
--  a fixed source
1409
 
1410
Prog_Stack_Addr_Move_fn: if( Allow_Stack_Address_Move )generate
1411
  SP_Ctrl.Addr               <= ALU_Regs(1) & ALU_Regs(0);
1412
end generate;
1413
 
1414
Normal_Stack_Reset_fn: if( not Allow_Stack_Address_Move )generate
1415
  SP_Ctrl.Addr               <= Stack_Start_Addr;
1416
end generate;
1417
 
1418
end block;
1419
 
1420
-------------------------------------------------------------------------------
1421
-- Address Source Mux
1422
-------------------------------------------------------------------------------
1423
 
1424
Open8_AS : block is
1425
begin
1426
 
1427
  Address_Select: process( AS_Ctrl, PC, SP, IMM, ISR )
1428
    variable PC_Mux, SP_Mux  : ADDRESS_TYPE;
1429
    variable IMM_Mux, ISR_Mux: ADDRESS_TYPE;
1430
  begin
1431
    PC_Mux                   := (others => '0');
1432
    SP_Mux                   := (others => '0');
1433
    IMM_Mux                  := (others => '0');
1434
    ISR_Mux                  := (others => '0');
1435
 
1436
    case AS_Ctrl.Src is
1437
      when ADDR_PC =>
1438
        PC_Mux               := PC;
1439
      when ADDR_SP =>
1440
        SP_Mux               := SP;
1441
      when ADDR_IMM =>
1442
        IMM_Mux              := IMM;
1443
      when ADDR_ISR =>
1444
        ISR_Mux              := ISR;
1445
    end case;
1446
 
1447
    for i in 0 to 15 loop
1448
      Address(i)             <= PC_Mux(i) or SP_Mux(i) or IMM_Mux(i) or
1449
                                ISR_Mux(i);
1450
    end loop;
1451
  end process;
1452
 
1453
end block;
1454
 
1455
-------------------------------------------------------------------------------
1456
-- (Write) Data Path
1457
-------------------------------------------------------------------------------
1458
 
1459
Open8_DP : block is
1460
  signal Wr_Data_D           : DATA_TYPE := (others => '0');
1461
  signal Wr_Enable_D         : std_logic := '0';
1462
begin
1463
 
1464
  Data_Select: process( DP_Ctrl, ALU_Regs, ALU_Flags, PC )
1465
    variable Reg_Mux, PC_Mux : DATA_TYPE;
1466
    variable Flag_Mux        : DATA_TYPE;
1467
  begin
1468
    Reg_Mux                  := (others => '0');
1469
    Flag_Mux                 := (others => '0');
1470
    PC_Mux                   := (others => '0');
1471
    Wr_Enable_D              <= '0';
1472
 
1473
    case DP_Ctrl.Src is
1474
      when DATA_IDLE =>
1475
        null;
1476
      when DATA_REG =>
1477
        Reg_Mux              := ALU_Regs(conv_integer(DP_Ctrl.Reg));
1478
        Wr_Enable_D          <= '1';
1479
      when DATA_FLAG =>
1480
        Flag_Mux             := ALU_Flags;
1481
        Wr_Enable_D          <= '1';
1482
      when DATA_PC =>
1483
        Wr_Enable_D          <= '1';
1484
        if( DP_Ctrl.Reg = ACCUM )then
1485
          PC_Mux             := PC(7 downto 0);
1486
        else
1487
          PC_Mux             := PC(15 downto 8);
1488
        end if;
1489
    end case;
1490
 
1491
    for i in 0 to 7 loop
1492
      Wr_Data_D(i)           <= Reg_Mux(i) or Flag_Mux(i) or PC_Mux(i);
1493
    end loop;
1494
  end process;
1495
 
1496
  S_Regs: process( Reset, Clock )
1497
  begin
1498
    if( Reset = Reset_Level )then
1499
      Wr_Data                <= (others => '0');
1500
      Wr_Enable              <= '0';
1501
      Rd_Enable              <= '1';
1502
    elsif( rising_edge(Clock) )then
1503
      if( Halt = '0' )then
1504
        Wr_Data              <= Wr_Data_D;
1505
        Wr_Enable            <= Wr_Enable_D;
1506
        Rd_Enable            <= not Wr_Enable_D;
1507
      end if;
1508
    end if;
1509
  end process;
1510
 
1511
end block;
1512
 
1513
end rtl;

powered by: WebSVN 2.1.0

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