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

Subversion Repositories mips_enhanced

[/] [mips_enhanced/] [trunk/] [grlib-gpl-1.0.19-b3188/] [lib/] [gleichmann/] [ahb2hpi/] [ahb2hpi2_ea.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 dimamali
-------------------------------------------------------------------------------
2
-- Title      : AHB2HPI bus bridge (bidirectional)
3
-- Project    : LEON3MINI
4
-------------------------------------------------------------------------------
5
-- $Id: ahb2hpi2.vhd,v 1.2 2006/12/08 10:22:18 tame Exp $
6
-------------------------------------------------------------------------------
7
-- Author     : Thomas Ameseder
8
-- Company    : Gleichmann Electronics
9
-- Created    : 2005-08-19
10
-- Standard   : VHDL'87
11
-------------------------------------------------------------------------------
12
-- Description:
13
--
14
-- This module implements an AHB slave that communicates with a
15
-- Host Peripheral Interface (HPI) device such as the CY7C67300 USB controller.
16
-- Supports Big Endian and Little Endian.
17
--
18
-- This is a modified version of the original AHB2HPI core with a bidirectional
19
-- data bus to be usable on-chip.
20
--
21
-- Restrictions: Do not use a data width other than 16 at the moment.
22
-------------------------------------------------------------------------------
23
-- Copyright (c) 2005 
24
-------------------------------------------------------------------------------
25
 
26
 
27
 
28
library ieee;
29
use ieee.std_logic_1164.all;
30
use ieee.std_logic_arith.all;
31
--use ieee.std_logic_unsigned.all;
32
library grlib;
33
use grlib.amba.all;
34
use grlib.stdlib.all;
35
use grlib.devices.all;
36
 
37
 
38
entity ahb2hpi2 is
39
  generic (
40
    counter_width : integer := 4;
41
    data_width    : integer := 16;
42
    address_width : integer := 2;
43
    hindex        : integer := 0;
44
    haddr         : integer := 0;
45
    hmask         : integer := 16#fff#;
46
    hirq          : integer := 5
47
    );
48
 
49
  port (
50
    -- AHB port
51
    HCLK    : in  std_ulogic;
52
    HRESETn : in  std_ulogic;
53
    ahbso   : out ahb_slv_out_type;
54
    ahbsi   : in  ahb_slv_in_type;
55
 
56
    -- HPI port
57
    ADDR  : out std_logic_vector(address_width-1 downto 0);
58
    WDATA : out std_logic_vector(data_width-1 downto 0);
59
    RDATA : in  std_logic_vector(data_width-1 downto 0);
60
    nCS   : out std_ulogic;
61
    nWR   : out std_ulogic;
62
    nRD   : out std_ulogic;
63
    INT   : in  std_ulogic;
64
 
65
    drive_bus : out std_ulogic;
66
 
67
    -- debug port
68
    dbg_equal : out std_ulogic
69
 
70
    );
71
end ahb2hpi2;
72
 
73
 
74
architecture rtl of ahb2hpi2 is
75
 
76
  constant CONFIGURATION_VERSION : integer := 0;
77
  constant VERSION               : integer := 1;
78
--  constant INTERRUPT_NUMBER      : integer := hirq;
79
  -- register file address is the base address plus the
80
  -- ahb memory space reserved for the device itself
81
  -- its size is 64 bytes as defined with 16#fff# for its
82
  -- mask below
83
  constant REGFILE_ADDRESS       : integer := 16#340#;
84
  -- big endian/little endian architecture selection
85
  constant BIG_ENDIAN            : boolean := true;
86
 
87
 
88
  constant hconfig : ahb_config_type := (
89
 
90
    (VENDOR_GLEICHMANN, GLEICHMANN_HPI,
91
     CONFIGURATION_VERSION, VERSION, hirq),
92
    4      => ahb_iobar(haddr, hmask),
93
    5      => ahb_iobar(REGFILE_ADDRESS, 16#fff#),
94
    others => (others => '0'));
95
 
96
  type reg_type is
97
    record
98
      hwrite           : std_ulogic;
99
      hready           : std_ulogic;
100
      hsel             : std_ulogic;
101
      addr             : std_logic_vector(address_width-1 downto 0);
102
      counter          : unsigned(counter_width-1 downto 0);
103
      Din              : std_logic_vector(data_width-1 downto 0);
104
      Dout             : std_logic_vector(data_width-1 downto 0);
105
      nWR, nRD, nCS    : std_ulogic;
106
      INT              : std_ulogic;
107
      ctrlreg          : std_logic_vector(data_width-1 downto 0);
108
      data_acquisition : std_ulogic;
109
      drive_bus : std_ulogic;
110
    end record;
111
 
112
 
113
  -- combinatorial, registered and
114
  -- double-registered signals
115
  signal c, r, rr : reg_type;
116
 
117
  -- signals for probing input and output data
118
  signal in_data_probe, out_data_probe : std_logic_vector(data_width-1 downto 0);
119
  signal equality_probe                : std_ulogic;
120
 
121
-- signal data_acquisition : std_ulogic;
122
 
123
  -- keep registers for debug purposes
124
  attribute syn_preserve                                                  : boolean;
125
  attribute syn_preserve of in_data_probe, out_data_probe, equality_probe : signal is true;
126
 
127
 
128
begin
129
 
130
  comb : process (INT, RDATA, HRESETn, ahbsi, r, rr)
131
    variable v            : reg_type;
132
    -- register fields
133
    variable tAtoCSlow    : unsigned(1 downto 0);  -- address to chip select (CS) low
134
    variable tCStoCTRLlow : unsigned(1 downto 0);  -- CS low to control (read/write) low
135
 
136
    variable tCTRLlowDvalid : unsigned(1 downto 0);  -- control (read) low to data valid
137
    variable tCTRLlow       : unsigned(1 downto 0);  -- control low to control high
138
 
139
    variable tCTRLhighCShigh : unsigned(1 downto 0);  -- control high to CS high
140
    variable tCShighREC      : unsigned(1 downto 0);  -- CS high to next CS recovery
141
 
142
    variable tCNT : unsigned(counter_width-1 downto 0);  -- timing counter
143
 
144
  begin
145
 
146
    -- assign values from the register in the beginning
147
    -- lateron, assign new values by looking at the new
148
    -- inputs from the bus
149
    v := r;
150
 
151
--    data_acquisition <= '0';
152
 
153
    if HRESETn = '0' then
154
      v.hwrite                := '0';
155
      v.hready                := '1';
156
      v.hsel                  := '0';
157
      v.addr                  := (others => '-');
158
      v.counter               := conv_unsigned(0, counter_width);
159
      v.Din                   := (others => '-');
160
      v.Dout                  := (others => '-');
161
      v.nWR                   := '1';
162
      v.nRD                   := '1';
163
      v.nCS                   := '1';
164
      v.INT                   := '0';
165
      -- bit 12 is reserved for the interrupt
166
      v.ctrlreg(15 downto 13) := (others => '0');
167
      v.ctrlreg(11 downto 0)  := (others => '0');
168
--      v.data_acquisition := '0';
169
          v.drive_bus := '1';
170
    end if;
171
 
172
    -- assert data_acquisition for not longer than one cycle
173
    v.data_acquisition := '0';
174
 
175
    -- bit 12 of control register holds registered interrupt
176
    v.ctrlreg(12) := INT;
177
    v.INT         := INT;
178
 
179
    -- assign register fields to signals
180
    tAtoCSlow    := (unsigned(r.ctrlreg(11 downto 10)));
181
    tCStoCTRLlow := (unsigned(r.ctrlreg(9 downto 8)));
182
 
183
    tCTRLlowDvalid := (unsigned(r.ctrlreg(7 downto 6)));
184
    tCTRLlow       := (unsigned(r.ctrlreg(5 downto 4)));
185
 
186
    tCTRLhighCShigh := (unsigned(r.ctrlreg(3 downto 2)));
187
    tCShighREC      := (unsigned(r.ctrlreg(1 downto 0)));
188
 
189
    tCNT := conv_unsigned(conv_unsigned(0, counter_width) + tAtoCSlow + tCStoCTRLlow + tCTRLlow + tCTRLhighCShigh + tCShighREC + '1', counter_width);
190
 
191
 
192
    -- is bus free to use?
193
    if ahbsi.hready = '1' then
194
      -- gets selected when HSEL signal for the right slave
195
      -- is asserted and the transfer type is SEQ or NONSEQ
196
      v.hsel := ahbsi.hsel(hindex) and ahbsi.htrans(1);
197
    else
198
      v.hsel := '0';
199
    end if;
200
 
201
    -- a valid cycle starts, so all relevant bus signals
202
    -- are registered and the timer is started
203
    if v.hsel = '1' and v.counter = conv_unsigned(0, counter_width) then
204
      v.hwrite  := ahbsi.hwrite and v.hsel;
205
      v.hready  := '0';
206
      v.counter := conv_unsigned(tCNT, counter_width);
207
      v.nWR     := '1';                 --not v.hwrite;
208
      v.nRD     := '1';                 --v.hwrite;
209
      v.nCS     := '1';
210
      if (conv_integer(ahbsi.haddr(19 downto 8)) = REGFILE_ADDRESS) then
211
        if ahbsi.haddr(7 downto 0) = X"00" then
212
          -- disable HPI signals, read/write register data
213
          -- and manage AHB handshake
214
          if v.hwrite = '1' then
215
            -- take data from AHB write data bus but skip interrupt bit
216
            if BIG_ENDIAN then
217
--              v.ctrlreg := ahbsi.hwdata(31 downto 31-data_width+1);
218
              v.ctrlreg(15 downto 13) := ahbsi.hwdata(31 downto 29);
219
              v.ctrlreg(11 downto 0)  := ahbsi.hwdata(27 downto 16);
220
            else
221
--              v.ctrlreg := ahbsi.hwdata(31-data_width downto 0);
222
              v.ctrlreg(15 downto 13) := ahbsi.hwdata(15 downto 13);
223
              v.ctrlreg(11 downto 0)  := ahbsi.hwdata(11 downto 0);
224
            end if;
225
          else
226
            v.Din := v.ctrlreg;
227
          end if;
228
        end if;
229
        -- go to last cycle which signals ahb ready
230
        v.counter := conv_unsigned(0, counter_width);  --(tCNT - tAtoCSlow - tCStoCTRLlow - tCTRLlow - tCTRLhighCShigh - tCShighREC);
231
      else
232
        -- the LSB of 16-bit AHB addresses is always zero,
233
        -- so the address is shifted in order to be able
234
        -- to access data with a short* in C
235
        v.addr := ahbsi.haddr(address_width downto 1);
236
--        v.size := ahbsi.hsize(1 downto 0);
237
 
238
 
239
 
240
      end if;
241
    end if;
242
 
243
        -- fetch input data according to the AMBA specification
244
        -- for big/little endian architectures
245
        -- only relevant for 16-bit accesses
246
        if v.counter = tCNT - 1 then
247
          if BIG_ENDIAN then
248
            v.Dout := ahbsi.hwdata(31 downto 31-data_width+1);
249
          else
250
            v.Dout := ahbsi.hwdata(31-data_width downto 0);
251
          end if;
252
        else
253
          if BIG_ENDIAN then
254
            v.Dout := r.Dout;
255
          else
256
            v.Dout := r.Dout;
257
      end if;
258
    end if;
259
 
260
    -- check if counter has just been re-initialized; if so,
261
    -- decrement it until it reaches zero and set control signals
262
    -- accordingly
263
    if v.counter > conv_unsigned(0, counter_width) then
264
      if v.counter = (tCNT - tAtoCSlow) then
265
        v.nCS := '0';
266
      end if;
267
      if v.counter = (tCNT - tAtoCSlow - tCStoCTRLlow) then
268
        v.nWR := not v.hwrite;
269
        v.nRD := v.hwrite;
270
      end if;
271
      if v.counter = (tCNT - tAtoCSlow - tCStoCTRLlow - tCTRLlowDvalid) then
272
        if v.nRD = '0' then
273
          v.Din              := RDATA;
274
          v.data_acquisition := '1';
275
--          in_data_probe <= DATA;
276
        end if;
277
      end if;
278
      if v.counter = (tCNT - tAtoCSlow - tCStoCTRLlow - tCTRLlow) then
279
        v.nWR := '1';
280
        v.nRD := '1';
281
      end if;
282
      if v.counter = (tCNT - tAtoCSlow - tCStoCTRLlow - tCTRLlow - tCTRLhighCShigh) then
283
        v.nCS := '1';
284
      end if;
285
      if v.counter = (tCNT - tAtoCSlow - tCStoCTRLlow - tCTRLlow
286
                      - tCTRLhighCShigh - tCShighREC) then
287
        v.hready := '1';
288
      end if;
289
      -- note: since the counter is queried and immediately
290
      -- decremented afterwards, the value in hardware
291
      -- is one lower than given in the if statement
292
      v.counter := v.counter - 1;
293
    else
294
      v.hready := '1';
295
    end if;
296
 
297
    -- three-state buffer: drive bus during a write cycle
298
    -- and hold data for one more clock cycle, then
299
    -- shut off from the bus
300
--    if ((r.nCS = '0' and r.nWR = '0') or (rr.nCS = '0' and r.nWR = '0') or
301
--        (r.nCS = '0' and rr.nWR = '0') or (rr.nCS = '0' and rr.nWR = '0')) then
302
--      WDATA <= r.Dout;
303
--      drive_bus <= '1';
304
--    else
305
      --WDATA <= (others => '-');
306
--      WDATA <= (others => 'Z');
307
--        drive_bus <= '0';
308
--    end if;
309
 
310
 
311
        if r.nCS='0' and r.nWR='0' then
312
                v.drive_bus := '1';
313
        elsif ((r.nCS='0' and rr.nCS='1') or ((r.Addr xor rr.Addr) /= "00")) then
314
                v.drive_bus := '0';
315
        end if;
316
 
317
    -- assign variable to a signal
318
    c <= v;
319
 
320
    -- HPI outputs
321
    ADDR <= r.addr;
322
    nCS  <= r.nCS;
323
    nWR  <= r.nWR;
324
    nRD  <= r.nRD;
325
 
326
    -- output data is assigned to the both the high and the
327
    -- low word of the 32-bit data bus
328
    ahbso.hrdata(31 downto 31-data_width+1) <= r.Din;
329
    ahbso.hrdata(31-data_width downto 0)    <= r.Din;  --(others => '-');
330
 
331
--    if v.addr(0) = '0' then
332
--      if BIG_ENDIAN then
333
--        ahbso.hrdata(31 downto 31-data_width+1) <= r.Din;
334
--        ahbso.hrdata(31-data_width downto 0) <= (others => '-');
335
--      else
336
--        ahbso.hrdata(31 downto 31-data_width+1) <= (others => '-');
337
--        ahbso.hrdata(31-data_width downto 0) <= r.Din;
338
--      end if;
339
--    else
340
--      if BIG_ENDIAN then
341
--        ahbso.hrdata(31 downto 31-data_width+1) <= (others => '-');
342
--        ahbso.hrdata(31-data_width downto 0) <= r.Din;
343
--      else
344
--        ahbso.hrdata(31 downto 31-data_width+1) <= r.Din;
345
--        ahbso.hrdata(31-data_width downto 0) <= (others => '-');
346
--      end if;
347
--    end if;
348
 
349
    ahbso.hready <= r.hready;
350
 
351
--    ahbso.hirq <= (hirq => r.ctrlreg(12), others => '0');  -- propagate registered interrupt
352
    ahbso.hirq       <= (others => '0');
353
    ahbso.hirq(hirq) <= r.ctrlreg(12);
354
  end process comb;
355
 
356
 
357
        WDATA <= r.Dout;
358
        drive_bus <=  (r.drive_bus or (not r.nWR)) when ((r.Addr xor rr.Addr) = "00") else'0';
359
 
360
  -- constant AHB outputs
361
  ahbso.hresp   <= "00";                -- answer OK by default
362
  ahbso.hsplit  <= (others => '0');     -- no SPLIT transactions
363
  ahbso.hcache  <= '0';                 -- cacheable yes/no
364
  ahbso.hconfig <= hconfig;
365
  ahbso.hindex  <= hindex;
366
 
367
 
368
  reg : process (HCLK)
369
  begin
370
    if rising_edge(HCLK) then
371
      r  <= c;
372
      rr <= r;
373
    end if;
374
  end process;
375
 
376
  ---------------------------------------------------------------------------------------
377
  -- DEBUG SECTION for triggering on read/write inconsistency
378
  -- use a C program that writes data AND reads it immediately afterwards
379
  -- dbg_equal start with being '0' after reset, then goes high during the transaction
380
  -- it should not have a falling edge during the transactions
381
  -- -> trigger on that event
382
  -- note regarding HPI data transactions:
383
  --       the address is written first before writing/reading at address B"10"
384
  --       the data register is at address B"00"
385
  ---------------------------------------------------------------------------------------
386
 
387
  -- read at the rising edge of the read signal
388
  -- (before the next read data is received)
389
--  data_acquisition <=  '1' when rr.nrd = '1' and r.nrd = '0' else
390
--                       '0';
391
 
392
  -- read data to compare to
393
  in_data_probe <= r.din;
394
 
395
  check_data : process (HCLK, HRESETn)
396
  begin
397
    if HRESETn = '0' then
398
      out_data_probe <= (others => '0');
399
      equality_probe <= '0';
400
    elsif rising_edge(HCLK) then
401
      -- is data being written to the *data* register?
402
      if r.nwr = '0' and r.ncs = '0' and r.addr = "00" then
403
        out_data_probe <= r.dout;
404
      end if;
405
      if r.data_acquisition = '1' then
406
        if in_data_probe = out_data_probe then
407
          equality_probe <= '1';
408
        else
409
          equality_probe <= '0';
410
        end if;
411
      end if;
412
    end if;
413
  end process;
414
 
415
  dbg_equal <= equality_probe;
416
 
417
-- pragma translate_off
418
  bootmsg : report_version
419
    generic map ("ahb2hpi2" & tost(hindex) &
420
                 ": AHB-to-HPI Bridge, irq " &
421
                 tost(hirq));
422
-- pragma translate_on
423
 
424
end rtl;

powered by: WebSVN 2.1.0

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