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

Subversion Repositories light8080

[/] [light8080/] [trunk/] [vhdl/] [soc/] [l80soc.vhdl] - Blame information for rev 80

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 70 ja_rd
--##############################################################################
2
-- l80soc : light8080 SOC
3
--##############################################################################
4
-- v1.0    (27 mar 2012) First release. Jose A. Ruiz.
5 80 ja_rd
-- v2.0    (16 apr 2012) Made interface a bit more useable, added comments.
6
-- 
7
-- This SoC is meant as an usage example for the light8080 core. The code shows
8
-- how to interface the core to internal BRAM and other modules.
9
-- This module is not meant to be used in real applications though it can be
10
-- used as the starting point for one.
11 70 ja_rd
--
12 80 ja_rd
-- Please see the comments below for usage instructions.
13
-- 
14 70 ja_rd
-- This file and all the light8080 project files are freeware (See COPYING.TXT)
15
--##############################################################################
16
 
17
library ieee;
18
use ieee.std_logic_1164.all;
19
use ieee.std_logic_arith.all;
20
use ieee.std_logic_unsigned.all;
21
use work.l80pkg.all;
22
 
23
 
24
--##############################################################################
25 80 ja_rd
-- Interface pins:
26
------------------
27
-- p1in :     Input port P1.
28
-- p2out :    Output port P2.
29
-- rxd :      UART RxD pin.
30
-- txd :      UART TxD pin.
31
-- extint :   External interrupt inputs, wired straight to the irq controller.
32
--            EXCEPT for the one used by the UART -- see generic UART_IRQ_LINE.
33
-- clk :      Master clock, rising edge active.
34
-- reset :    Synchronous reset, 1 cycle active to reset all SoC.
35 70 ja_rd
--
36 80 ja_rd
--------------------------------------------------------------------------------
37
-- Generics:
38
------------
39
-- OBJ_CODE (mandatory, no default value):  
40
-- Table that will be used to initialize internal BRAM, starting at address 0.
41
--
42
-- DEFAULT_RAM_SIZE (default = 0):
43
-- Internal RAM size. If set to zero, the RAM size will be determined from the 
44
-- size of OBJ_CODE as the smallest power of 2 larger than OBJ_CODE'length.
45
--
46
-- UART_IRQ_LINE (defaults to 4):
47
-- Index of the irq controller input the internal UART is wired to, or >3 to 
48
-- leave the UART unconnected to the IRQ controller.
49
-- The irq controller input used for the uart will be unconnected to the SoC
50
-- input port.
51
--
52
-- UART_HARDWIRED (defaults to true):
53
-- True when the UART baud rate is hardwired. the baud rate registers will be
54
-- 
55
-- BAUD_RATE (defaults to 19200):
56
-- UART default baud rate. When th UART is hardwired, the baud rate can't be
57
-- changed at run time. 
58
-- Note that you have to set generic z. This value is needed to compute the 
59
-- UART baud rate constants.
60
--
61
--------------------------------------------------------------------------------
62
-- I/O port map:
63
----------------
64
--
65
-- 080h..083h     UART registers.
66
-- 084h           P1 input port (read only, writes are ignored).
67
-- 086h           P2 output port (write only, reads undefined data).
68
-- 088h           IRQ enable register.
69
--
70
-- Please see the comments in the source of the relevant modules for a more
71
-- detailed explanation of their behavior.
72
--
73
-- All i/o  ports other than the above read as 00h.
74
--------------------------------------------------------------------------------
75
-- Notes:
76
---------
77
-- -# If you do not set a default memory size, you then have to take care to 
78
--    control the size of the object code table.
79
-- -# If you do set the default memory size, the code will not warn you if the
80
--    object code does not fit inside, it will silentl truncate it.
81
-- -# The internal memory block is mirrored over the entire address map. 
82
-- -# There is no write protection to any address range: you can overwrite the 
83
--    program. If you do that there's no way to recover it but reloading the 
84
--    FPGA, a reset will not do.
85 70 ja_rd
--##############################################################################
86
entity l80soc is
87
    generic (
88
      OBJ_CODE      : obj_code_t;       -- RAM initialization constant 
89 80 ja_rd
      DEFAULT_RAM_SIZE: integer := 0;   -- RAM size or 0 to stretch
90 70 ja_rd
      UART_IRQ_LINE : integer := 4;     -- [0..3] or >3 for none
91
      UART_HARDWIRED: boolean := true;  -- UART baud rate is hardwired
92
      BAUD_RATE     : integer := 19200; -- UART (default) baud rate
93
      CLOCK_FREQ    : integer := 50E6   -- Clock frequency in Hz
94
    );
95
    port (
96
      p1in :          in std_logic_vector(7 downto 0);
97
      p2out :         out std_logic_vector(7 downto 0);
98
 
99
      rxd :           in std_logic;
100
      txd :           out std_logic;
101
 
102
      extint :        in std_logic_vector(3 downto 0);
103
 
104
      clk :           in std_logic;
105
      reset :         in std_logic
106
    );
107
end l80soc;
108
 
109
--##############################################################################
110
--
111
--##############################################################################
112
 
113
architecture hardwired of l80soc is
114
 
115 80 ja_rd
-- Helper functions ------------------------------------------------------------
116
 
117
 
118
-- soc_ram_size: compute size of internal RAM 
119
-- If default_size is /= 0, the size is the default. If it is zero, then the
120
-- size the smallest power of 2 larger than obj_code_size.
121
function soc_ram_size(default_size, obj_code_size: integer) return integer is
122
begin
123
  if default_size=0 then
124
    -- Default is zero: use a RAM as big as necessary for the obj code table
125
    -- rounding to the neares power of 2.
126
    return 2**log2(obj_code_size);
127
  else
128
    -- Default is not zero: use the default and do NOT check to see if the 
129
    -- object code fits.
130
    return default_size;
131
  end if;
132
end function soc_ram_size;
133
 
134
-- Custom types ----------------------------------------------------------------
135
 
136 70 ja_rd
subtype t_byte is std_logic_vector(7 downto 0);
137
 
138
-- CPU signals -----------------------------------------------------------------
139
 
140
signal cpu_vma :      std_logic;
141
signal cpu_rd :       std_logic;
142
signal cpu_wr :       std_logic;
143
signal cpu_io :       std_logic;
144
signal cpu_fetch :    std_logic;
145
signal cpu_addr :     std_logic_vector(15 downto 0);
146
signal cpu_data_i :   std_logic_vector(7 downto 0);
147
signal cpu_data_o :   std_logic_vector(7 downto 0);
148
signal cpu_intr :     std_logic;
149
signal cpu_inte :     std_logic;
150
signal cpu_inta :     std_logic;
151
signal cpu_halt :     std_logic;
152
 
153
 
154
-- Aux CPU signals -------------------------------------------------------------
155
 
156
-- io_wr: asserted in IO write cycles
157
signal io_wr :        std_logic;
158
-- io_rd: asserted in IO read cycles
159
signal io_rd :        std_logic;
160
-- io_addr: IO port address, lowest 8 bits of address bus
161
signal io_addr :      std_logic_vector(7 downto 0);
162
-- io_rd_data: data coming from IO ports (io input mux)
163
signal io_rd_data :   std_logic_vector(7 downto 0);
164
-- cpu_io_reg: registered cpu_io, used to control mux after cpu_io deasserts
165
signal cpu_io_reg :   std_logic;
166
 
167
-- UART ------------------------------------------------------------------------
168
 
169
signal uart_ce :      std_logic;
170
signal uart_data_rd : std_logic_vector(7 downto 0);
171
signal uart_irq :     std_logic;
172
 
173
 
174
-- RAM -------------------------------------------------------------------------
175
 
176 80 ja_rd
constant RAM_SIZE : integer := soc_ram_size(DEFAULT_RAM_SIZE,OBJ_CODE'length);
177
constant RAM_ADDR_SIZE : integer := log2(RAM_SIZE);
178 70 ja_rd
 
179
signal ram_rd_data :  std_logic_vector(7 downto 0);
180
signal ram_we :       std_logic;
181
 
182 80 ja_rd
signal ram :      ram_t(0 to RAM_SIZE-1) := objcode_to_bram(OBJ_CODE, RAM_SIZE);
183 70 ja_rd
signal ram_addr :     std_logic_vector(RAM_ADDR_SIZE-1 downto 0);
184
 
185
-- IRQ controller interface ----------------------------------------------------
186
 
187
signal irqcon_we :    std_logic;
188
signal irqcon_data_rd: std_logic_vector(7 downto 0);
189
signal irq :          std_logic_vector(3 downto 0);
190
 
191
 
192
-- IO ports addresses ----------------------------------------------------------
193
 
194
subtype io_addr_t is std_logic_vector(7 downto 0);
195
 
196
constant ADDR_UART_0 : io_addr_t  := X"80"; -- UART registers (80h..83h)
197
constant ADDR_UART_1 : io_addr_t  := X"81"; -- UART registers (80h..83h)
198
constant ADDR_UART_2 : io_addr_t  := X"82"; -- UART registers (80h..83h)
199
constant ADDR_UART_3 : io_addr_t  := X"83"; -- UART registers (80h..83h)
200
constant P1_DATA_REG : io_addr_t  := X"84"; -- port 1 data register 
201
constant P2_DATA_REG : io_addr_t  := X"86"; -- port 2 data register 
202
constant INTR_EN_REG : io_addr_t  := X"88"; -- interrupts enable register 
203
 
204 80 ja_rd
 
205 70 ja_rd
begin
206
 
207
 
208
  cpu: entity work.light8080
209
  port map (
210
    clk =>      clk,
211
    reset =>    reset,
212
    vma =>      cpu_vma,
213
    rd =>       cpu_rd,
214
    wr =>       cpu_wr,
215
    io =>       cpu_io,
216
    fetch =>    cpu_fetch,
217
    addr_out => cpu_addr,
218
    data_in =>  cpu_data_i,
219
    data_out => cpu_data_o,
220
 
221
    intr =>     cpu_intr,
222
    inte =>     cpu_inte,
223
    inta =>     cpu_inta,
224
    halt =>     cpu_halt
225
  );
226
 
227
  io_rd <= cpu_io and cpu_rd;
228
  io_wr <= '1' when cpu_io='1' and cpu_wr='1' else '0';
229
  io_addr <= cpu_addr(7 downto 0);
230
 
231
  -- Register some control signals that are needed to control multiplexors the
232
  -- cycle after the control signal asserts -- e.g. cpu_io.
233
  control_signal_registers:
234
  process(clk)
235
  begin
236
    if clk'event and clk='1' then
237
      cpu_io_reg <= cpu_io;
238
    end if;
239
  end process control_signal_registers;
240
 
241
  -- Input data mux -- remember, no 3-state buses within the FPGA --------------
242
  cpu_data_i <=
243
      irqcon_data_rd    when cpu_inta = '1' else
244
      io_rd_data        when cpu_io_reg = '1' else
245
      ram_rd_data;
246
 
247
 
248
  -- BRAM ----------------------------------------------------------------------
249
 
250
  ram_we <= '1' when cpu_io='0' and cpu_wr='1' else '0';
251
  ram_addr <= cpu_addr(RAM_ADDR_SIZE-1 downto 0);
252
 
253
  memory:
254
  process(clk)
255
  begin
256
    if clk'event and clk='1' then
257
      if ram_we = '1' then
258
        ram(conv_integer(ram_addr)) <= cpu_data_o;
259
      end if;
260
      ram_rd_data <= ram(conv_integer(ram_addr));
261
    end if;
262
  end process memory;
263
 
264
 
265
  -- Interrupt controller ------------------------------------------------------
266
  -- FIXME interrupts unused in this version
267
 
268
  irq_control: entity work.l80irq
269
  port map (
270
    clk =>          clk,
271
    reset =>        reset,
272
 
273
    irq_i =>        irq,
274
 
275
    data_i =>       cpu_data_o,
276
    data_o =>       irqcon_data_rd,
277
    addr_i =>       cpu_addr(0),
278
    data_we_i =>    irqcon_we,
279
 
280
    cpu_inta_i =>   cpu_inta,
281
    cpu_intr_o =>   cpu_intr,
282
    cpu_fetch_i =>  cpu_fetch
283
  );
284
 
285
  irq_line_connections:
286
  for i in 0 to 3 generate
287
  begin
288
    uart_irq_connection:
289
    if i = UART_IRQ_LINE generate
290
    begin
291
      irq(i) <= uart_irq;
292
    end generate;
293
    other_irq_connections:
294
    if i /= UART_IRQ_LINE generate
295
      irq(i) <= extint(i);
296
    end generate;
297
  end generate irq_line_connections;
298
 
299
  irqcon_we <= '1' when io_addr=INTR_EN_REG and io_wr='1' else '0';
300
 
301
  -- UART -- simple UART with hardwired baud rate ------------------------------
302
  -- NOTE: the serial port does NOT have interrupt capability (yet)
303
 
304
  uart : entity work.uart
305
  generic map (
306
    BAUD_RATE =>      BAUD_RATE,
307
    CLOCK_FREQ =>     CLOCK_FREQ
308
  )
309
  port map (
310
    clk_i =>          clk,
311
    reset_i =>        reset,
312
 
313
    irq_o =>          uart_irq,
314
    data_i =>         cpu_data_o,
315
    data_o =>         uart_data_rd,
316
    addr_i =>         cpu_addr(1 downto 0),
317
 
318
    ce_i =>           uart_ce,
319
    wr_i =>           io_wr,
320
    rd_i =>           io_rd,
321
 
322
    rxd_i =>          rxd,
323
    txd_o =>          txd
324
  );
325
 
326
  -- UART write enable
327
  uart_ce <= '1' when
328
        io_addr(7 downto 2) = ADDR_UART_0(7 downto 2)
329
        else '0';
330
 
331
  -- IO ports -- Simple IO ports with hardcoded direction ----------------------
332
  -- These are meant as an usage example mostly
333
 
334
  output_ports:
335
  process(clk)
336
  begin
337
    if clk'event and clk='1' then
338
      if reset = '1' then
339
        -- Reset values for all io ports
340
        p2out <= (others => '0');
341
      else
342
        if io_wr = '1' then
343
          if conv_integer(io_addr) = P2_DATA_REG then
344
            p2out <= cpu_data_o;
345
          end if;
346
        end if;
347
      end if;
348
    end if;
349
  end process output_ports;
350
 
351
  -- Input IO data multiplexor
352
  with io_addr select io_rd_data <=
353
    p1in            when P1_DATA_REG,
354
    uart_data_rd    when ADDR_UART_0,
355
    uart_data_rd    when ADDR_UART_1,
356
    uart_data_rd    when ADDR_UART_2,
357
    uart_data_rd    when ADDR_UART_3,
358
    irqcon_data_rd  when INTR_EN_REG,
359
    X"00"           when others;
360
 
361
 
362
end hardwired;
363
 

powered by: WebSVN 2.1.0

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