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

Subversion Repositories risc5x

[/] [risc5x/] [trunk/] [cpu.vhd] - Blame information for rev 5

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

Line No. Rev Author Line
1 2 mikej
--
2
-- Risc5x
3
-- www.OpenCores.Org - November 2001
4
--
5
--
6
-- This library is free software; you can distribute it and/or modify it
7
-- under the terms of the GNU Lesser General Public License as published
8
-- by the Free Software Foundation; either version 2.1 of the License, or
9
-- (at your option) any later version.
10
--
11
-- This library is distributed in the hope that it will be useful, but
12
-- WITHOUT ANY WARRANTY; without even the implied warranty of
13
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
-- See the GNU Lesser General Public License for more details.
15
--
16
-- A RISC CPU core.
17
--
18
-- (c) Mike Johnson 2001. All Rights Reserved.
19
-- mikej@opencores.org for support or any other issues.
20
--
21
-- Revision list
22
--
23
-- version 1.1 bug fix: Used wrong bank select bits in direct addressing mode
24
--                      INDF register returns 0 when indirectly read
25
--                      FSR bit 8 always set
26
-- version 1.0 initial opencores release
27
--
28
 
29
use work.pkg_risc5x.all;
30
use work.pkg_prims.all;
31
library ieee;
32
  use ieee.std_logic_1164.all;
33
  use ieee.std_logic_arith.all;
34
  use ieee.std_logic_unsigned.all;
35
 
36
entity CPU is
37
  port (
38
    PADDR           : out std_logic_vector(10 downto 0);
39
    PDATA           : in  std_logic_vector(11 downto 0);
40
 
41
    PORTA_IN        : in    std_logic_vector(7 downto 0);
42
    PORTA_OUT       : out   std_logic_vector(7 downto 0);
43
    PORTA_OE_L      : out   std_logic_vector(7 downto 0);
44
 
45
    PORTB_IN        : in    std_logic_vector(7 downto 0);
46
    PORTB_OUT       : out   std_logic_vector(7 downto 0);
47
    PORTB_OE_L      : out   std_logic_vector(7 downto 0);
48
 
49
    PORTC_IN        : in    std_logic_vector(7 downto 0);
50
    PORTC_OUT       : out   std_logic_vector(7 downto 0);
51
    PORTC_OE_L      : out   std_logic_vector(7 downto 0);
52
 
53
    DEBUG_W         : out std_logic_vector(7 downto 0);
54
    DEBUG_PC        : out std_logic_vector(10 downto 0);
55
    DEBUG_INST      : out std_logic_vector(11 downto 0);
56
    DEBUG_STATUS    : out std_logic_vector(7 downto 0);
57
 
58
    RESET           : in  std_logic;
59
    CLK             : in  std_logic
60
    );
61
end;
62
 
63
architecture RTL of CPU is
64
 
65
-- component definitions
66
 
67
component IDEC is
68
  port (
69
    INST                : in  std_logic_vector(11 downto 0);
70
 
71
    ALU_ASEL            : out std_logic_vector(1 downto 0);
72
    ALU_BSEL            : out std_logic_vector(1 downto 0);
73
    ALU_ADDSUB          : out std_logic_vector(1 downto 0);
74
    ALU_BIT             : out std_logic_vector(1 downto 0);
75
    ALU_SEL             : out std_logic_vector(1 downto 0);
76
 
77
    WWE_OP              : out std_logic;
78
    FWE_OP              : out std_logic;
79
 
80
    ZWE                 : out std_logic;
81
    DCWE                : out std_logic;
82
    CWE                 : out std_logic;
83
    BDPOL               : out std_logic;
84
    OPTION              : out std_logic;
85
    TRIS                : out std_logic
86
    );
87
end component;
88
 
89
component ALU is
90
  port (
91
    ADDSUB          : in  std_logic_vector(1 downto 0);
92
    BIT             : in  std_logic_vector(1 downto 0);
93
    SEL             : in  std_logic_vector(1 downto 0);
94
 
95
    A               : in  std_logic_vector(7 downto 0);
96
    B               : in  std_logic_vector(7 downto 0);
97
    Y               : out std_logic_vector(7 downto 0);
98
    CIN             : in  std_logic;
99
    COUT            : out std_logic;
100
    DCOUT           : out std_logic;
101
    ZOUT            : out std_logic
102
    );
103
end component;
104
 
105
component REGS is
106
  port (
107
    WE              : in  std_logic;
108
    RE              : in  std_logic;
109
    BANK            : in  std_logic_vector(1 downto 0);
110
    LOCATION        : in  std_logic_vector(4 downto 0);
111
    DIN             : in  std_logic_vector(7 downto 0);
112
    DOUT            : out std_logic_vector(7 downto 0);
113
    RESET           : in  std_logic;
114
    CLK             : in  std_logic
115
    );
116
end component;
117
 
118
-- type/constant definitions
119
  constant STATUS_RESET_VALUE : std_logic_vector(7 downto 0) := x"18";
120
  constant OPTION_RESET_VALUE : std_logic_vector(7 downto 0) := x"3F";
121
  constant INDF_ADDR     : std_logic_vector(2 downto 0) := "000";
122
  constant TMR0_ADDR     : std_logic_vector(2 downto 0) := "001";
123
  constant PCL_ADDR      : std_logic_vector(2 downto 0) := "010";
124
  constant STATUS_ADDR   : std_logic_vector(2 downto 0) := "011";
125
  constant FSR_ADDR      : std_logic_vector(2 downto 0) := "100";
126
  constant PORTA_ADDR    : std_logic_vector(2 downto 0) := "101";
127
  constant PORTB_ADDR    : std_logic_vector(2 downto 0) := "110";
128
  constant PORTC_ADDR    : std_logic_vector(2 downto 0) := "111";
129
 
130
-- signal definitions
131
  signal inst                           : std_logic_vector(11 downto 0);
132
 
133
  signal inst_k                         : std_logic_vector(7 downto 0);
134
  signal inst_fsel                      : std_logic_vector(4 downto 0);
135
  signal inst_d                         : std_logic;
136
  signal inst_b                         : std_logic_vector(2 downto 0);
137
 
138
  signal pc,next_pc                     : std_logic_vector(10 downto 0);
139
  signal pc_load_stack                  : std_logic_vector(10 downto 0);
140
  signal pc_write                       : std_logic_vector(10 downto 0);
141
  signal pc_call                        : std_logic_vector(10 downto 0);
142
  signal pc_goto                        : std_logic_vector(10 downto 0);
143
  signal pc_load                        : std_logic_vector(10 downto 0);
144
  signal pc_load_sel                    : std_logic_vector(1 downto 0);
145
  signal pc_inc                         : std_logic;
146
 
147
  signal stacklevel                     : std_logic_vector(1 downto 0);
148
  signal stack1,stack2                  : std_logic_vector(10 downto 0);
149
  signal w_reg,status,fsr,tmr0          : std_logic_vector(7 downto 0);
150
  signal prescaler,option               : std_logic_vector(7 downto 0);
151
  signal trisa,trisb,trisc              : std_logic_vector(7 downto 0);
152
 
153
  signal porta_dout                     : std_logic_vector(7 downto 0);
154
  signal portb_dout                     : std_logic_vector(7 downto 0);
155
  signal portc_dout                     : std_logic_vector(7 downto 0);
156
 
157
  signal porta_din                      : std_logic_vector(7 downto 0);
158
  signal portb_din                      : std_logic_vector(7 downto 0);
159
  signal portc_din                      : std_logic_vector(7 downto 0);
160
 
161
  signal dbus,sbus                      : std_logic_vector(7 downto 0);
162
  signal sbus_swap                      : std_logic_vector(7 downto 0);
163
  signal sbus_mux_out                   : std_logic_vector(7 downto 0);
164
 
165
  -- inst decode
166
  signal regfile_sel,special_sel        : std_logic;
167
  signal fileaddr_indirect              : std_logic;
168
  signal fileaddr_mux1                  : std_logic_vector(6 downto 0);
169
  signal fileaddr_mux0                  : std_logic_vector(6 downto 0);
170
 
171
  signal istris,isoption                : std_logic;
172
  signal fwe,wwe,zwe,dcwe,cwe           : std_logic;
173
  signal bdpol                          : std_logic;
174
  signal bd                             : std_logic_vector(7 downto 0);
175
  signal skip                           : std_logic;
176
 
177
  -- alu
178
  signal alu_asel,alu_bsel              : std_logic_vector(1 downto 0) := (others => '0');
179
  signal alu_addsub                     : std_logic_vector(1 downto 0) := (others => '0');
180
  signal alu_bit                        : std_logic_vector(1 downto 0) := (others => '0');
181
  signal alu_sel                        : std_logic_vector(1 downto 0) := (others => '0');
182
 
183
  signal alu_z,alu_dcout,alu_cout       : std_logic := '0';
184
  signal alu_a,alu_b                    : std_logic_vector(7 downto 0) := (others => '0');
185
  signal alu_out                        : std_logic_vector(7 downto 0);
186
 
187
  signal regfile_we,regfile_re          : std_logic;
188
  signal regfile_in,regfile_out         : std_logic_vector(7 downto 0);
189
  signal fileaddr                       : std_logic_vector(6 downto 0);
190
 
191
begin -- architecture
192
 
193
  u_idec : IDEC
194
    port map (
195
      INST                => inst,
196
 
197
      ALU_ASEL            => alu_asel,
198
      ALU_BSEL            => alu_bsel,
199
      ALU_ADDSUB          => alu_addsub,
200
      ALU_BIT             => alu_bit,
201
      ALU_SEL             => alu_sel,
202
 
203
      WWE_OP              => wwe,
204
      FWE_OP              => fwe,
205
 
206
      ZWE                 => zwe,
207
      DCWE                => dcwe,
208
      CWE                 => cwe,
209
      BDPOL               => bdpol,
210
      OPTION              => isoption,
211
      TRIS                => istris
212
      );
213
 
214
  u_alu : ALU
215
    port map (
216
      ADDSUB          => alu_addsub,
217
      BIT             => alu_bit,
218
      SEL             => alu_sel,
219
 
220
      A               => alu_a,
221
      B               => alu_b,
222
      Y               => alu_out,
223
      CIN             => status(0),
224
      COUT            => alu_cout,
225
      DCOUT           => alu_dcout,
226
      ZOUT            => alu_z
227
      );
228
 
229
  u_regs : REGS
230
    port map (
231
      WE              => regfile_we,
232
      RE              => regfile_re,
233
      BANK            => fileaddr(6 downto 5),
234
      LOCATION        => fileaddr(4 downto 0),
235
      DIN             => regfile_in,
236
      DOUT            => regfile_out,
237
      RESET           => RESET,
238
      CLK             => CLK
239
      );
240
 
241
  DEBUG_W <= w_reg;
242
  DEBUG_PC <= pc(10 downto 0);
243
  DEBUG_INST <= inst;
244
  DEBUG_STATUS <= status;
245
 
246
  -- *********** REGISTER FILE Addressing ****************
247
  p_addr_dec_comb : process(inst_fsel,fsr)
248
  begin
249
    if (inst_fsel = ("00" & INDF_ADDR)) then
250
      fileaddr_indirect <= '1';
251
    else
252
      fileaddr_indirect <= '0';
253
    end if;
254
 
255
    fileaddr_mux1 <= fsr(6 downto 0);
256
    fileaddr_mux0 <= (fsr(6 downto 5) & inst_fsel);
257
  end process;
258
 
259
  fileaddr_mux : MUX2
260
    generic map (
261
      WIDTH         => 7,
262
      SLICE         => 1,
263
      OP_REG        => FALSE
264
      )
265
    port map (
266
      DIN1          => fileaddr_mux1,
267
      DIN0          => fileaddr_mux0,
268
 
269
      SEL           => fileaddr_indirect,
270
      ENA           => '0', -- not used
271
      CLK           => '0', -- not used
272
 
273
      DOUT          => fileaddr
274
      );
275
 
276
  p_regfile_we_comb : process(regfile_sel,fwe,alu_asel,alu_bsel)
277
  begin
278
    regfile_we <= regfile_sel and fwe;
279
    regfile_re <= '1'; -- not used
280
  end process;
281
 
282
  p_fileaddr_dec_comb : process(fileaddr,isoption,istris)
283
  begin
284
    regfile_sel <= '1'; -- everything else;
285
    special_sel <= '0';
286
    if (fileaddr(4 downto 3) = "00") and (isoption = '0') and (istris = '0') then
287
      special_sel <= '1';  -- lower 8 addresses in ALL BANKS 1 lut
288
    end if;
289
  end process;
290
 
291
  sbus_muxa : MUX8
292
    generic map (
293
      WIDTH         => 8,
294
      OP_REG        => FALSE
295
      )
296
    port map (
297
      DIN7          => portc_din,
298
      DIN6          => portb_din,
299
      DIN5          => porta_din,
300
      DIN4          => fsr,
301
      DIN3          => status,
302
      DIN2          => pc(7 downto 0),
303
      DIN1          => tmr0,
304
      DIN0          => x"00", -- INDF returns 0
305
 
306
      SEL           => inst_fsel(2 downto 0),
307
      ENA           => '0',
308
      CLK           => '0',
309
 
310
      DOUT          => sbus_mux_out
311
      );
312
 
313
  sbus_muxb : MUX2
314
    generic map (
315
      WIDTH         => 8,
316
      SLICE         => 1,
317
      OP_REG        => FALSE
318
      )
319
    port map (
320
      DIN1          => sbus_mux_out,
321
      DIN0          => regfile_out,
322
 
323
      SEL           => special_sel,
324
      ENA           => '0',
325
      CLK           => '0',
326
 
327
      DOUT          => sbus
328
      );
329
 
330
  p_dbus_comb : process(alu_out)
331
  begin
332
    dbus <= alu_out;
333
    regfile_in <= alu_out;
334
  end process;
335
 
336
  p_paddr_comb : process(next_pc)
337
  begin
338
     PADDR <= next_pc(10 downto 0);
339
  end process;
340
 
341
  p_inst_assign_comb : process(inst)
342
  begin
343
    inst_k    <= inst(7 downto 0);
344
    inst_fsel <= inst(4 downto 0);
345
    inst_d    <= inst(5);
346
    inst_b    <= inst(7 downto 5);
347
  end process;
348
 
349
  p_bdec_assign_comb : process(inst_b,bdpol)
350
  variable bdec : std_logic_vector(7 downto 0);
351
  begin
352
    -- 1 lut
353
    bdec := "00000001";
354
    case inst_b is
355
      when "000" => bdec := "00000001";
356
      when "001" => bdec := "00000010";
357
      when "010" => bdec := "00000100";
358
      when "011" => bdec := "00001000";
359
      when "100" => bdec := "00010000";
360
      when "101" => bdec := "00100000";
361
      when "110" => bdec := "01000000";
362
      when "111" => bdec := "10000000";
363
      when others => null;
364
    end case;
365
    if (bdpol = '1') then
366
      bd <= not bdec;
367
    else
368
      bd <=     bdec;
369
    end if;
370
  end process;
371
 
372
  p_inst : process(CLK,RESET)
373
  begin
374
    if (RESET = '1') then
375
      inst <= x"000";
376
    elsif CLK'event and (CLK = '1') then
377
      if (skip = '1')  then
378
        inst <= x"000"; -- force NOP
379
      else
380
        inst <= PDATA;
381
      end if;
382
    end if;
383
  end process;
384
 
385
  p_skip_comb : process(inst,alu_z,fwe,special_sel,fileaddr)
386
  begin
387
    -- SKIP signal.
388
    -- We want to insert the NOP instruction for the following conditions:
389
    --    we have modified PCL
390
    --    GOTO,CALL and RETLW instructions
391
    --    BTFSS instruction when aluz is HI
392
    --    BTFSC instruction when aluz is LO
393
   skip <= '0';
394
 
395
    if (fwe = '1') and (special_sel = '1') and (fileaddr(2 downto 0) = PCL_ADDR) then skip <= '1'; end if;
396
    if (inst(11 downto 10) = "10") then skip <= '1'; end if;
397
    if (inst(11 downto  8) = "0110") and (alu_z = '1') then skip <= '1'; end if; -- BTFSC
398
    if (inst(11 downto  8) = "0111") and (alu_z = '0') then skip <= '1'; end if; -- BTFSS
399
    if (inst(11 downto  6) = "001011") and (alu_z = '1') then skip <= '1'; end if; -- DECFSZ
400
    if (inst(11 downto  6) = "001111") and (alu_z = '1') then skip <= '1'; end if; -- INCFSZ
401
  end process;
402
 
403
  sbus_swap <= sbus(3 downto 0) & sbus(7 downto 4);
404
 
405
  alua_mux : MUX4
406
    generic map (
407
      WIDTH         => 8,
408
      SLICE         => 1,
409
      OP_REG        => FALSE
410
      )
411
    port map (
412
      DIN3          => sbus_swap,
413
      DIN2          => inst_k,
414
      DIN1          => sbus,
415
      DIN0          => w_reg,
416
 
417
      SEL           => alu_asel,
418
      ENA           => '0',
419
      CLK           => '0',
420
 
421
      DOUT          => alu_a
422
      );
423
 
424
  alub_mux : MUX4
425
    generic map (
426
      WIDTH         => 8,
427
      SLICE         => 0,
428
      OP_REG        => FALSE
429
      )
430
    port map (
431
      DIN3          => x"01",
432
      DIN2          => bd,
433
      DIN1          => sbus,
434
      DIN0          => w_reg,
435
 
436
      SEL           => alu_bsel,
437
      ENA           => '0',
438
      CLK           => '0',
439
 
440
      DOUT          => alu_b
441
      );
442
 
443
  p_w_reg : process(CLK,RESET)
444
  begin
445
    if (RESET = '1') then
446
      w_reg <= x"00";
447
    elsif CLK'event and (CLK = '1') then
448
      if (wwe = '1')  then
449
        w_reg <= dbus;
450
      end if;
451
    end if;
452
  end process;
453
 
454
  p_tmr0 : process(CLK,RESET)
455
    variable mask : std_logic_vector(7 downto 0);
456
  begin
457
    if (RESET = '1') then
458
      tmr0 <= x"00";
459
    elsif CLK'event and (CLK = '1') then
460
      -- See if the timer register is actually being written to
461
      if (fwe = '1') and (special_sel = '1') and (fileaddr(2 downto 0) = TMR0_ADDR) then
462
        tmr0 <= dbus;
463
      else
464
        mask := "00000001";
465
        case option(2 downto 0) is
466
          when "000" => mask := "00000001";
467
          when "001" => mask := "00000011";
468
          when "010" => mask := "00000111";
469
          when "011" => mask := "00001111";
470
          when "100" => mask := "00011111";
471
          when "101" => mask := "00111111";
472
          when "110" => mask := "01111111";
473
          when "111" => mask := "11111111";
474
          when others => null;
475
        end case;
476
        if ((prescaler and mask) = "00000000") or (option(3) = '1') then
477
          tmr0 <= tmr0 + "1";
478
        end if;
479
      end if;
480
    end if;
481
  end process;
482
 
483
  p_prescaler : process(CLK,RESET)
484
  begin
485
    if (RESET = '1') then
486
      prescaler <= x"00";
487
    elsif CLK'event and (CLK = '1') then
488
      if not (option(5) = '1') then
489
        prescaler <= prescaler + "1";
490
      end if;
491
    end if;
492
  end process;
493
 
494
  p_status_reg : process(CLK,RESET)
495
    variable new_z,new_dc,new_c : std_logic;
496
  begin
497
    if (RESET = '1') then
498
      status <= STATUS_RESET_VALUE;
499
    elsif CLK'event and (CLK = '1') then
500
      -- See if the status register is actually being written to
501
      -- this is not accurate, bits 4 & 3 should be read only
502
      -- additionally, zwe,cwe and dcwe should override fwe
503
 
504
      if (fwe = '1') and (special_sel = '1') and (fileaddr(2 downto 0) = STATUS_ADDR) then
505
        status <= dbus;
506
      else
507
      -- For the carry and zero flags, each instruction has its own rule as
508
      -- to whether to update this flag or not.  The instruction decoder is
509
      -- providing us with an enable for C and Z.  Use this to decide whether
510
      -- to retain the existing value, or update with the new alu status output.
511
         if (zwe = '1') then new_z := alu_z; else new_z := status(2); end if;
512
         if (dcwe = '1') then new_dc := alu_dcout; else new_dc := status(1); end if;
513
         if (cwe = '1') then new_c := alu_cout; else new_c := status(0); end if;
514
         status <= (
515
              status(7) &                  -- BIT 7: Undefined.. (maybe use for debugging)
516
              status(6) &                  -- BIT 6: Program Page, HI bit
517
              status(5) &                  -- BIT 5: Program Page, LO bit
518
              status(4) &                  -- BIT 4: Time Out bit (not implemented at this time)
519
              status(3) &                  -- BIT 3: Power Down bit (not implemented at this time)
520
              new_z     &                  -- BIT 2: Z
521
              new_dc    &                  -- BIT 1: DC
522
              new_c);                      -- BIT 0: C
523
       end if;
524
    end if;
525
  end process;
526
 
527
  p_fsr_reg : process(CLK,RESET)
528
  begin
529
    if (RESET = '1') then
530
      fsr <= x"80";
531
    elsif CLK'event and (CLK = '1') then
532
      if (fwe = '1') and (special_sel = '1') and (fileaddr(2 downto 0) = FSR_ADDR) then
533
        fsr <= dbus;
534
      end if;
535
      fsr(7) <= '1'; --always set in real chip
536
    end if;
537
  end process;
538
 
539
  p_option_reg : process(CLK,RESET)
540
  begin
541
    if (RESET = '1') then
542
      option <= OPTION_RESET_VALUE;
543
    elsif CLK'event and (CLK = '1') then
544
      if (isoption = '1') then
545
        option <= dbus;
546
      end if;
547
    end if;
548
  end process;
549
 
550
  p_drive_ports_comb : process(porta_dout,trisa,portb_dout,trisb,portc_dout,trisc)
551
  begin
552
      PORTA_OE_L <= trisa;
553
      PORTB_OE_L <= trisb;
554
      PORTC_OE_L <= trisc;
555
 
556
      PORTA_OUT <= porta_dout;
557
      PORTB_OUT <= portb_dout;
558
      PORTC_OUT <= portc_dout;
559
 
560
  end process;
561
 
562
  port_in : process(CLK,RESET,PORTA_IN,PORTB_IN,PORTC_IN)
563
    begin
564
    -- the input registers don't exist in the real device,
565
    -- so if you read an output we have introduced a clock delay.
566
      if (RESET = '1') then
567
        porta_din <= (others => '0');
568
        portb_din <= (others => '0');
569
        portc_din <= (others => '0');
570
      elsif CLK'event and (CLK = '1') then -- comment this out for combinatorial ip
571
      --else                               -- or comment this for registered ip
572
        porta_din <= PORTA_IN;
573
        portb_din <= PORTB_IN;
574
        portc_din <= PORTC_IN;
575
      end if;
576
  end process;
577
 
578
  p_port_reg : process(CLK,RESET)
579
  begin
580
    if (RESET = '1') then
581
      trisa <= x"FF"; -- default tristate
582
      trisb <= x"FF"; -- default tristate
583
      trisc <= x"FF"; -- default tristate
584
      porta_dout <= x"00";
585
      portb_dout <= x"00";
586
      portc_dout <= x"00";
587
    elsif CLK'event and (CLK = '1') then
588
 
589
      if (fwe = '1') and (fileaddr(2 downto 0) = PORTA_ADDR) then
590
        if (istris = '0') and (special_sel = '1') then
591
          porta_dout <= dbus;
592
        elsif (istris = '1') then
593
          trisa <= dbus;
594
        end if;
595
      end if;
596
 
597
      if (fwe = '1') and (fileaddr(2 downto 0) = PORTB_ADDR) then
598
        if (istris = '0') and (special_sel = '1') then
599
          portb_dout <= dbus;
600
        elsif (istris = '1') then
601
          trisb <= dbus;
602
        end if;
603
      end if;
604
 
605
      if (fwe = '1') and (fileaddr(2 downto 0) = PORTC_ADDR) then
606
        if (istris = '0') and (special_sel = '1') then
607
          portc_dout <= dbus;
608
        elsif (istris = '1') then
609
          trisc <= dbus;
610
        end if;
611
      end if;
612
    end if;
613
  end process;
614
 
615
  -- ********** PC AND STACK *************************
616
 
617
  p_next_pc_comb : process(pc,inst,status,stacklevel,stack1,stack2,dbus,fileaddr,special_sel,fwe)
618
  begin
619
 
620
    pc_goto  <= ( status(6 downto 5) &       inst(8 downto 0));
621
    pc_call  <= ( status(6 downto 5) & '0' & inst(7 downto 0));
622
    pc_write <= (pc(10) & '0' & pc(8) & dbus);          -- set bit 9 to zero
623
 
624
    pc_inc <= '1'; -- default
625
 
626
    pc_load_sel <= "00"; -- pc write
627
    if (fwe = '1') and (special_sel = '1') and (fileaddr(2 downto 0) = PCL_ADDR) then
628
      --pc_load_sel <= "00";  default
629
      pc_inc <= '0';  -- as we have modified next_pc, must skip next instruction
630
    end if;
631
 
632
    if (inst(11 downto 9) = "101")  then pc_load_sel <= "01"; pc_inc <= '0'; end if; -- goto
633
    if (inst(11 downto 8) = "1001") then pc_load_sel <= "10"; pc_inc <= '0'; end if; -- call
634
    if (inst(11 downto 8) = "1000") then pc_load_sel <= "11"; pc_inc <= '0'; end if; -- ret
635
 
636
  end process;
637
 
638
  pc_load_mux : MUX4
639
    generic map (
640
      WIDTH         => 11,
641
      SLICE         => 0,
642
      OP_REG        => FALSE
643
      )
644
    port map (
645
      DIN3          => pc_load_stack,
646
      DIN2          => pc_call,
647
      DIN1          => pc_goto,
648
      DIN0          => pc_write,
649
 
650
      SEL           => pc_load_sel,
651
      ENA           => '0',
652
      CLK           => '0',
653
 
654
      DOUT          => pc_load
655
      );
656
 
657
  pc_mux2_add_reg : MUX2_ADD_REG
658
    generic map (
659
      WIDTH         => 11
660
      )
661
    port map (
662
      ADD_VAL       => "00000000001",  -- pc = pc + 1
663
      LOAD_VAL      => pc_load, -- branch
664
 
665
      ADD           => pc_inc,
666
 
667
      PRESET        => RESET,
668
      ENA           => '1',
669
      CLK           => CLK,
670
 
671
      DOUT          => next_pc,
672
      REG_DOUT      => pc
673
      );
674
 
675
  p_stack_comb : process(stacklevel,stack1,stack2)
676
  begin
677
    pc_load_stack <= stack1; -- default
678
    case stacklevel is
679
      when "00" => pc_load_stack <= stack1;
680
      when "01" => pc_load_stack <= stack1;
681
      when "10" => pc_load_stack <= stack2;
682
      when "11" => pc_load_stack <= stack2;
683
      when others => null;
684
    end case;
685
  end process;
686
 
687
  p_stack_reg : process(CLK,RESET)
688
  begin
689
    if (RESET = '1') then
690
      stack1 <= (others => '0');
691
      stack2 <= (others => '0');
692
    elsif CLK'event and (CLK = '1') then
693
      if (inst(11 downto 8) = "1001") then
694
        case stacklevel is
695
          when "00" => stack1 <= pc(10 downto 0);
696
          when "01" => stack2 <= pc(10 downto 0);
697
          when "10" => assert false report "Too many CALLs !" severity failure;
698
          when "11" => assert false report "Too many CALLs !" severity failure;
699
          when others => null;
700
        end case;
701
      end if;
702
    end if;
703
  end process;
704
 
705
  p_stack_level : process(CLK,RESET)
706
  begin
707
    if (RESET = '1') then
708
      stacklevel <= "00";
709
    elsif CLK'event and (CLK = '1') then
710
      stacklevel <= stacklevel;
711
      if (inst(11 downto 8) = "1001") then
712
        case stacklevel is
713
          when "00" => stacklevel <="01"; -- 1st call
714
          when "01" => stacklevel <="10"; -- 2nd call
715
          when "10" => stacklevel <="10"; -- already 2, ignore
716
          when "11" => stacklevel <="00"; -- broke
717
          when others => null;
718
        end case;
719
      elsif (inst(11 downto 8) = "1000") then
720
        case stacklevel is
721
          when "00" => stacklevel <="00"; -- broke
722
          when "01" => stacklevel <="00"; -- go back to no call
723
          when "10" => stacklevel <="01"; -- go back to 1 call
724
          when "11" => stacklevel <="10"; -- broke
725
          when others => null;
726
        end case;
727
      end if;
728
    end if;
729
  end process;
730
end rtl;
731
 

powered by: WebSVN 2.1.0

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