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

Subversion Repositories light52

[/] [light52/] [trunk/] [vhdl/] [light52_mcu.vhdl] - Blame information for rev 17

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 ja_rd
--------------------------------------------------------------------------------
2
-- light52_mcu.vhdl -- MCU/SoC built around light52 CPU.
3
--------------------------------------------------------------------------------
4
-- The MCU is a minimalistic SoC built around the light52 core mostly for
5
-- demonstration purposes. It has more or less the same features as a plain old
6
-- i8051: an UART, a timer and a bunch of i/o.
7
-- While it can be used as it stands, it is meant to be modified to suit each 
8
-- particular application of the core. Thus, no effort has been made to provide 
9
-- a variety of general purpose peripherals. You are supposed to supply them 
10
-- yourself.
11
-- 
12
--
13
-- A complete explanation of all the peripherals and their SFRs can be found in
14
-- the core datasheet.
15
--
16
--------------------------------------------------------------------------------
17
-- INTERFACE SIGNALS
18
--
19
-- clk :                Clock, active rising edge.
20
-- reset :              Synchronous reset, hold for at least 1 cycle.
21
--
22
-- rxd :                UART RxD input.
23
-- txd :                UART TxD output.
24
--
25
-- external_irq :       External interrupt request inputs. 
26
--                      Level active: Will trigger interrupt #0 as long as any 
27
--                      of them is high (if enabled).
28
--
29
-- p0_out :             Output GP port 0.
30
-- p1_out :             Output GP port 1.
31
-- p2_in :              Input GP port 2.
32
-- p3_out :             Input GP port 3.
33
--
34
--------------------------------------------------------------------------------
35
-- GENERICS:
36
--
37
-- CODE_ROM_SIZE 
38
--  Size in bytes of XCODE ROM block to be initialized with application object 
39
--  code. Must be 512 <= CODE_ROM_SIZE < 64K.
40
--
41
-- XDATA_RAM_SIZE               
42
-- Size of XDATA RAM. Can be zero. 
43
--
44
-- OBJ_CODE
45
--  Object code constant hardwired onto XCODE ROM block. This value is meant to 
46
--  come from a constant defined in an 'object code package', built from the 
47
--  project application object code. See the datasheet.
48
--
49
-- IMPLEMENT_BCD_INSTRUCTIONS
50
--  Whether or not to implement BCD instructions. 
51
--  When true, instructions DA and XCHD will work as in the original MCS51.
52
--  When false, those instructions will work as NOP, saving some logic.
53
--
54
-- SEQUENTIAL_MULTIPLIER
55
--  Sequential vs. combinational multiplier.
56
--  When true, a sequential implementation will be used for the multiplier, 
57
--  which will usually save a lot of logic or a dedicated multiplier.
58
--  When false, a combinational registered multiplier will be used.
59
--  (NOT IMPLEMENTED -- setting it to true will raise an assertion failure).
60
--
61
-- USE_BRAM_FOR_XRAM            
62
--  Use extra space in IRAM/uCode RAM as XRAM.
63
--  When true, extra logic will be generated so that the extra space in the 
64
--  RAM block used for IRAM/uCode can be used as XRAM.
65
--  This prevents RAM waste at some cost in area and clock rate.
66
--  When false, any extra space in the IRAM physical block will be wasted.
67
--
68
-- UART_HARDWIRED               
69
--  UART baud rate is hardwired to its default value, writes to the SBPL, SBPH 
70
--  SFR registers have no effect.
71
--
72
-- UART_BAUD_RATE               
73
--  Default UART baud rate. Must be <= (CLOCK_RATE/16).
74
--
75
-- CLOCK_RATE                   
76
--  Main clock frequency in Hz. Used in the computation of the periods of the 
77
--  UART and the timer.
78
--
79
-- TIMER0_COUNT_RATE 
80
--  Count rate of Timer0. Used to compute the value of the Timer0 prescaler.
81
--
82
--------------------------------------------------------------------------------
83
-- Copyright (C) 2012 Jose A. Ruiz
84
--                                                              
85
-- This source file may be used and distributed without         
86
-- restriction provided that this copyright statement is not    
87
-- removed from the file and that any derivative work contains  
88
-- the original copyright notice and the associated disclaimer. 
89
--                                                              
90
-- This source file is free software; you can redistribute it   
91
-- and/or modify it under the terms of the GNU Lesser General   
92
-- Public License as published by the Free Software Foundation; 
93
-- either version 2.1 of the License, or (at your option) any   
94
-- later version.                                               
95
--                                                              
96
-- This source is distributed in the hope that it will be       
97
-- useful, but WITHOUT ANY WARRANTY; without even the implied   
98
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      
99
-- PURPOSE.  See the GNU Lesser General Public License for more 
100
-- details.                                                     
101
--                                                              
102
-- You should have received a copy of the GNU Lesser General    
103
-- Public License along with this source; if not, download it   
104
-- from http://www.opencores.org/lgpl.shtml
105
--------------------------------------------------------------------------------
106
 
107
library ieee;
108
use ieee.std_logic_1164.all;
109
use ieee.numeric_std.all;
110
 
111
use work.light52_pkg.all;
112
use work.obj_code_pkg.all;
113
 
114
 
115
entity light52_mcu is
116
    generic (
117
        -- External memory configuration -- These default values will be 
118
        -- overriden in the actual project instantiation.
119
        CODE_ROM_SIZE :         natural := 2*1024;
120
        XDATA_RAM_SIZE :        natural := 0;
121
        OBJ_CODE :              t_obj_code := default_object_code;
122
        -- CPU configuration (see CPU module).
123
        USE_BRAM_FOR_XRAM :     boolean := false;
124
        IMPLEMENT_BCD_INSTRUCTIONS : boolean := false;
125
        SEQUENTIAL_MULTIPLIER : boolean := false;
126
        -- Peripheral configuration (see peripheral modules).
127
        UART_HARDWIRED :        boolean := false;
128
        UART_BAUD_RATE :        natural := 19200;
129
        CLOCK_RATE :            natural := 50e6;
130
        -- Timer0 count period = 20 us by default (20e-6 = 1/50e3)
131
        TIMER0_COUNT_RATE :     natural := 50e3
132
    );
133
    port(
134
        clk             : in std_logic;
135
        reset           : in std_logic;
136
 
137
        rxd             : in std_logic;
138
        txd             : out std_logic;
139
 
140
        external_irq    : in std_logic_vector(7 downto 0);
141
 
142
        p0_out          : out std_logic_vector(7 downto 0);
143
        p1_out          : out std_logic_vector(7 downto 0);
144
        p2_in           : in std_logic_vector(7 downto 0);
145
        p3_in           : in std_logic_vector(7 downto 0)
146
    );
147
end entity light52_mcu;
148
 
149
 
150
architecture rtl of light52_mcu is
151
 
152
---- SFR addresses -------------------------------------------------------------
153
 
154
subtype t_mcu_sfr_addr is std_logic_vector(7 downto 0);
155
 
156
-- These include only the SFR addresses of the MCU peripherals; the CPU SFRs are
157
-- covered in the main package.
158
-- Note these addresses overlap those of the original 8051 but the SFRs 
159
-- themselves are NOT compatible!
160
constant SFR_ADDR_SCON      : t_mcu_sfr_addr := X"98";
161
constant SFR_ADDR_SBUF      : t_mcu_sfr_addr := X"99";
162
constant SFR_ADDR_SBPL      : t_mcu_sfr_addr := X"9a";
163
constant SFR_ADDR_SBPH      : t_mcu_sfr_addr := X"9b";
164
constant SFR_ADDR_P0        : t_mcu_sfr_addr := X"80";
165
constant SFR_ADDR_P1        : t_mcu_sfr_addr := X"90";
166
constant SFR_ADDR_P2        : t_mcu_sfr_addr := X"a0";
167
constant SFR_ADDR_P3        : t_mcu_sfr_addr := X"b0";
168
constant SFR_ADDR_TCON      : t_mcu_sfr_addr := X"88";
169
constant SFR_ADDR_TL        : t_mcu_sfr_addr := X"8c";
170
constant SFR_ADDR_TH        : t_mcu_sfr_addr := X"8d";
171
constant SFR_ADDR_TCL       : t_mcu_sfr_addr := X"8e";
172
constant SFR_ADDR_TCH       : t_mcu_sfr_addr := X"8f";
173
constant SFR_ADDR_EXTINT    : t_mcu_sfr_addr := X"c0";
174
 
175
constant P0_RESET_VALUE     : std_logic_vector(7 downto 0) := X"00";
176
constant P1_RESET_VALUE     : std_logic_vector(7 downto 0) := X"00";
177
 
178
 
179
----- XCODE interface ----------------------------------------------------------
180
 
181
signal code_addr :          std_logic_vector(15 downto 0);
182
signal code_rd :            std_logic_vector(7 downto 0);
183
 
184
-- Code ROM must be initialized with the object code.
185
signal code_bram :          t_bram(0 to CODE_ROM_SIZE-1) :=
186
                            objcode_to_bram(OBJ_CODE, CODE_ROM_SIZE);
187
signal code_addr_slice :    std_logic_vector(log2(CODE_ROM_SIZE)-1 downto 0);
188
 
189
 
190
---- XDATA interface -----------------------------------------------------------
191
 
192
signal xdata_addr :         std_logic_vector(15 downto 0);
193
signal xdata_rd :           std_logic_vector(7 downto 0);
194
signal xdata_wr :           std_logic_vector(7 downto 0);
195
signal xdata_vma :          std_logic;
196
signal xdata_we :           std_logic;
197
 
198
signal xdata_ram :          t_bram(0 to XDATA_RAM_SIZE-1);
199
signal data_addr_slice :    std_logic_vector(log2(XDATA_RAM_SIZE)-1 downto 0);
200
 
201
---- SFR and peripheral module interface signals -------------------------------
202
 
203
signal sfr_addr :           std_logic_vector(7 downto 0);
204
signal sfr_rd :             std_logic_vector(7 downto 0);
205
signal sfr_wr :             std_logic_vector(7 downto 0);
206
signal sfr_vma :            std_logic;
207
signal sfr_we :             std_logic;
208
 
209
signal uart_re :            std_logic;
210
signal uart_ce :            std_logic;
211
signal uart_sfr_rd :        std_logic_vector(7 downto 0);
212
signal uart_irq :           std_logic;
213
 
214
signal timer_we :           std_logic;
215
signal timer_ce :           std_logic;
216
signal timer_sfr_rd :       std_logic_vector(7 downto 0);
217
signal timer_irq :          std_logic;
218
 
219
signal io_ce :              std_logic;
220
signal p0_reg :             std_logic_vector(7 downto 0);
221
signal p1_reg :             std_logic_vector(7 downto 0);
222
signal p2_reg :             std_logic_vector(7 downto 0);
223
signal p3_reg :             std_logic_vector(7 downto 0);
224
 
225
signal ext_irq_ce :         std_logic;
226
signal external_irq_reg :   std_logic_vector(7 downto 0);
227
signal ext_irq :            std_logic;
228
 
229
signal irq_source :         std_logic_vector(4 downto 0);
230
 
231
 
232
begin
233
 
234
---- CPU entity instantiation --------------------------------------------------
235
 
236
    cpu: entity work.light52_cpu
237
    generic map (
238
        USE_BRAM_FOR_XRAM => USE_BRAM_FOR_XRAM,
239
        IMPLEMENT_BCD_INSTRUCTIONS => IMPLEMENT_BCD_INSTRUCTIONS,
240
        SEQUENTIAL_MULTIPLIER => SEQUENTIAL_MULTIPLIER
241
    )
242
    port map (
243
        clk         => clk,
244
        reset       => reset,
245
 
246
        code_addr   => code_addr,
247
        code_rd     => code_rd,
248
 
249
        irq_source  => irq_source,
250
 
251
        xdata_addr  => xdata_addr,
252
        xdata_rd    => xdata_rd,
253
        xdata_wr    => xdata_wr,
254
        xdata_vma   => xdata_vma,
255
        xdata_we    => xdata_we,
256
 
257
 
258
        sfr_addr    => sfr_addr,
259
        sfr_rd      => sfr_rd,
260
        sfr_wr      => sfr_wr,
261
        sfr_vma     => sfr_vma,
262
        sfr_we      => sfr_we
263
    );
264
 
265 17 ja_rd
    -- Connect peripheral IRQ inputs to the CPU.
266
    irq_source <= uart_irq & "00" & timer_irq & ext_irq;
267 2 ja_rd
 
268
---- SFR input mux -------------------------------------------------------------
269
 
270
    -- You have to modify simplified addressing if you add new peripherals.
271
    -- WARNING:
272
    -- If we use constant slices for decoding instead of bit vector literals,
273
    -- Xilinx ISE 9.2i will complain that 'sfr_rd is not assigned' and will 
274
    -- optimize away the SFR input mux.
275
    -- The only way I've found to fix this is to use literals, though it 
276
    -- defeats the purpose of using constants in the first place...
277
    with sfr_addr(7 downto 3) select sfr_rd <=
278
        uart_sfr_rd     when "10011",       -- SFR_ADDR_SCON(7 downto 3)
279
        timer_sfr_rd    when "10001",       -- SFR_ADDR_TCON(7 downto 3)
280
        p0_reg          when "10000",       -- SFR_ADDR_P0(7 downto 3)
281
        p1_reg          when "10010",       -- SFR_ADDR_P1(7 downto 3)
282
        p2_reg          when "10100",       -- SFR_ADDR_P2(7 downto 3)
283
        p3_reg          when others;
284
 
285
 
286
---- XCODE memory block --------------------------------------------------------
287
 
288
    -- Make sure the XCODE size is within bounds.
289
    assert 512 <= CODE_ROM_SIZE and CODE_ROM_SIZE <= 65536
290
    report "Invalid value for CODE_ROM_SIZE (<512 or >64KB)."
291
    severity failure;
292
 
293
 
294
    code_addr_slice <= code_addr(code_addr_slice'high downto 0);
295
 
296
    code_ram_block:
297
    process(clk)
298
    begin
299
        if clk'event and clk='1' then
300
            code_rd <= code_bram(to_integer(unsigned(code_addr_slice)));
301
        end if;
302
    end process code_ram_block;
303
 
304
---- XDATA memory block --------------------------------------------------------
305
 
306
    -- Make sure the XDATA size is within bounds.
307
    assert XDATA_RAM_SIZE <= 65536
308
    report "Invalid value for XDATA_RAM_SIZE (>64KB)."
309
    severity failure;
310
 
311
    -- If the XDATA memory is implemented, infer a synchronous RAM block.
312
    -- This block will be mirrored all over the 64K space, as usual.
313
    xdata_implemented:
314
    if XDATA_RAM_SIZE > 0 generate
315
 
316
    data_addr_slice <= xdata_addr(data_addr_slice'high downto 0);
317
 
318
    xdata_ram_block:
319
    process(clk)
320
    begin
321
        if clk'event and clk='1' then
322
            if xdata_we='1' then
323
                xdata_ram(to_integer(unsigned(data_addr_slice))) <= xdata_wr;
324
            end if;
325
            xdata_rd <= xdata_ram(to_integer(unsigned(data_addr_slice)));
326
        end if;
327
    end process xdata_ram_block;
328
 
329
    end generate xdata_implemented;
330
 
331
    -- If the XDATA memory is not implemented, ground the data input.
332
    xdata_unimplemented:
333
    if XDATA_RAM_SIZE = 0 generate
334
 
335
        xdata_rd <= (others => '0');
336
 
337
    end generate xdata_unimplemented;
338
 
339
 
340
 
341
---- UART ----------------------------------------------------------------------
342
 
343
    uart : entity work.light52_uart
344
    generic map (
345
        HARDWIRED => UART_HARDWIRED,
346
        CLOCK_FREQ => CLOCK_RATE,
347
        BAUD_RATE => UART_BAUD_RATE
348
    )
349
    port map (
350
        rxd_i   => rxd,
351
        txd_o   => txd,
352
 
353
        irq_o   => uart_irq,
354
 
355
        data_i  => sfr_wr,
356
        data_o  => uart_sfr_rd,
357
 
358
        addr_i  => sfr_addr(1 downto 0),
359
        wr_i    => sfr_we,
360
        rd_i    => uart_re,
361
        ce_i    => uart_ce,
362
 
363
        clk_i   => clk,
364
        reset_i => reset
365
    );
366
 
367
    -- Make sure the simplifications we'll do in the address decoding are valid.
368
    assert SFR_ADDR_SCON=X"98" and SFR_ADDR_SBUF=X"99" and
369
           SFR_ADDR_SBPL=X"9a" and SFR_ADDR_SBPH=X"9b"
370
    report "MCU SFR address decoding assumes standard UART register addresses "&
371
           "but addresses configured in light52_mcu are not standard."
372
    severity failure;
373
 
374
    uart_ce <= '1' when sfr_addr(7 downto 3)=SFR_ADDR_SCON(7 downto 3) else '0';
375
    uart_re <= sfr_vma and not sfr_we;
376
 
377
 
378
---- Timer ---------------------------------------------------------------------
379
 
380
    -- This is a basic 16-bit timer set up as a 20-microsecond-period counter
381
    timer: entity work.light52_timer
382
    generic map (
383
        PRESCALER_VALUE => CLOCK_RATE / TIMER0_COUNT_RATE
384
    )
385
    port map (
386
        irq_o   => timer_irq,
387
 
388
        data_i  => sfr_wr,
389
        data_o  => timer_sfr_rd,
390
 
391
        addr_i  => sfr_addr(2 downto 0),
392
        wr_i    => timer_we,
393
        ce_i    => timer_ce,
394
 
395
        clk_i   => clk,
396
        reset_i => reset
397
    );
398
 
399
    timer_ce <= '1' when sfr_addr(7 downto 3)=SFR_ADDR_TCON(7 downto 3) and
400
                sfr_vma='1'
401
                else '0';
402
    timer_we <= sfr_we;
403
 
404
    -- Make sure the simplifications we do in the address decoding are valid.
405
    assert SFR_ADDR_TCON=X"88" and SFR_ADDR_TL=X"8c"
406
    report "MCU SFR simplified address decoding makes assumptions that conflict "&
407
           "with the SFR addresses configured in light52_mcu."
408
    severity failure;
409
 
410
 
411
---- Input/Output ports --------------------------------------------------------
412
-- FIXME this should be encapsulated in a separate module
413
 
414
    -- Make sure the simplifications we'll do in the address decoding are valid.
415
    assert SFR_ADDR_P0=X"80" and SFR_ADDR_P1=X"90" and
416
           SFR_ADDR_P2=X"a0" and SFR_ADDR_P3=X"b0"
417
    report "MCU SFR address decoding assumes I/O port addresses are standard "&
418
           "but addresses configured in light52_pkg are not."
419
    severity failure;
420
 
421
    io_ce <= '1' when sfr_addr(7 downto 6)=SFR_ADDR_P0(7 downto 6) and
422
                      sfr_addr(3 downto 0)="0000" and
423
                      sfr_vma='1'
424
                      else '0';
425
 
426
    output_ports:
427
    process(clk)
428
    begin
429
        if clk'event and clk='1' then
430
            if reset='1' then
431
                p0_reg <= P0_RESET_VALUE;
432
                p1_reg <= P1_RESET_VALUE;
433
            else
434
                if io_ce='1' and sfr_we='1' then
435
                    if sfr_addr(5 downto 4)=SFR_ADDR_P0(5 downto 4) then
436
                        p0_reg <= sfr_wr;
437
                    end if;
438
                    if sfr_addr(5 downto 4)=SFR_ADDR_P1(5 downto 4) then
439
                        p1_reg <= sfr_wr;
440
                    end if;
441
                end if;
442
            end if;
443
        end if;
444
    end process output_ports;
445
 
446
    -- Note that for output ports the CPU will ALWAYS read the output register and
447
    -- not the actual pin status -- like read-modify-write instructions in the
448
    -- original MCS51.
449
    p0_out <= p0_reg;
450
    p1_out <= p1_reg;
451
 
452
    -- NOTE: input ports are registered but NOT protected against metastability.
453
    -- Add a second layer of registers if your application needs the protection.
454
    input_ports:
455
    process(clk)
456
    begin
457
        if clk'event and clk='1' then
458
            p2_reg <= p2_in;
459
            p3_reg <= p3_in;
460
        end if;
461
    end process input_ports;
462
 
463
 
464
---- External interrupt block --------------------------------------------------
465
-- FIXME this should be encapsulated in a separate module
466
 
467
    ext_irq_ce <= '1' when sfr_addr(7 downto 6)=SFR_ADDR_EXTINT(7 downto 6) and
468
                      sfr_addr(3 downto 0)="0000" and
469
                      sfr_vma='1'
470
                      else '0';
471
 
472
    external_interrupt_register:
473
    process(clk)
474
    begin
475
        if clk'event and clk='1' then
476
            if reset='1' then
477
                external_irq_reg <= (others => '0');
478
            else
479
                if ext_irq_ce='1' and sfr_we='1' then
480
                    -- All bits in this register are w1c
481
                    external_irq_reg <= external_irq_reg and (not sfr_wr);
482
                else
483
                    external_irq_reg <= external_irq or external_irq_reg;
484
                end if;
485
            end if;
486
        end if;
487
    end process external_interrupt_register;
488
 
489
    ext_irq <= '1' when external_irq_reg/=X"00" else '0';
490
 
491
end architecture rtl;

powered by: WebSVN 2.1.0

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