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

Subversion Repositories core_arm

[/] [core_arm/] [trunk/] [vhdl/] [sparc/] [pci_gr.vhd] - Blame information for rev 5

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

Line No. Rev Author Line
1 2 tarookumic
----------------------------------------------------------------------------
2
--  This file is a part of the LEON VHDL model
3
--  Copyright (C) Gaisler Research 2003
4
--
5
--  This library is free software; you can redistribute it and/or
6
--  modify it under the terms of the GNU Lesser General Public
7
--  License as published by the Free Software Foundation; either
8
--  version 2 of the License, or (at your option) any later version.
9
--
10
--  See the file COPYING.LGPL for the full details of the license.
11
-----------------------------------------------------------------------------
12
-- Entity:      pci_gr
13
-- File:        pci_gr.vhd
14
-- Author:      Jiri Gaisler - Gaisler Research
15
-- Description: Simple PCI target interface
16
------------------------------------------------------------------------------
17
 
18
library ieee;
19
use ieee.std_logic_1164.all;
20
use ieee.std_logic_arith.all;
21
use work.amba.all;
22
use work.ambacomp.all;
23
use work.macro.all;
24
use work.leon_iface.all;
25
 
26
entity pci_gr is
27
   generic (
28
      device_id : integer := 0;          -- PCI device ID
29
      vendor_id : integer := 0;          -- PCI vendor ID
30
      nsync : integer range 1 to 2 := 1 -- 1 or 2 sync regs between clocks
31
);
32
   port(
33
      rst       : in std_logic;
34
      pcirst    : in std_logic;
35
      clk       : in std_logic;
36
      pciclk    : in std_logic;
37
      pcii      : in  pci_in_type;
38
      pcio      : out pci_out_type;
39
      ahbmi     : in  ahb_mst_in_type;
40
      ahbmo     : out ahb_mst_out_type;
41
      ahbsi     : in  ahb_slv_in_type;
42
      ahbso     : out ahb_slv_out_type
43
);
44
end;
45
 
46
architecture rtl of pci_gr is
47
 
48
constant CSYNC : integer := nsync-1;
49
constant MADDR_WIDTH : integer := 21;
50
constant zero : std_logic_vector(31 downto 0) := (others => '0');
51
subtype word4 is std_logic_vector(3 downto 0);
52
subtype word32 is std_logic_vector(31 downto 0);
53
constant pci_memory_read : word4 := "0110";
54
constant pci_memory_write : word4 := "0111";
55
constant pci_config_read : word4 := "1010";
56
constant pci_config_write : word4 := "1011";
57
type pci_input_type is record
58
  ad       : std_logic_vector(31 downto 0);
59
  cbe      : std_logic_vector(3 downto 0);
60
  frame    : std_logic;
61
  devsel   : std_logic;
62
  idsel    : std_logic;
63
  trdy     : std_logic;
64
  irdy     : std_logic;
65
  par      : std_logic;
66
  stop     : std_logic;
67
  rst      : std_logic;
68
end record;
69
 
70
type pci_target_state_type is (idle, b_busy, s_data, backoff, turn_ar);
71
type pci_reg_type is record
72
  addr     : std_logic_vector(MADDR_WIDTH-1 downto 0);
73
  data     : std_logic_vector(31 downto 0);
74
  cmd      : std_logic_vector(3 downto 0);
75
  state    : pci_target_state_type;
76
  csel     : std_logic;
77
  msel     : std_logic;
78
  read     : std_logic;
79
  devsel   : std_logic;
80
  trdy     : std_logic;
81
  stop     : std_logic;
82
  par      : std_logic;
83
  oe_par   : std_logic;
84
  oe_ad    : std_logic;
85
  oe_ctrl  : std_logic;
86
  bar0     : std_logic_vector(31 downto MADDR_WIDTH);
87
  page     : std_logic_vector(31 downto MADDR_WIDTH-1);
88
  men      : std_logic;
89
  laddr    : std_logic_vector(31 downto 0);
90
  ldata    : std_logic_vector(31 downto 0);
91
  lwrite   : std_logic;
92
  start    : std_logic;
93
  rready   : std_logic_vector(csync downto 0);
94
  wready   : std_logic_vector(csync downto 0);
95
  sync     : std_logic_vector(csync downto 0);
96
end record;
97
 
98
type cpu_state_type is (idle, sync1, busy, sync2);
99
type cpu_reg_type is record
100
  data     : std_logic_vector(31 downto 0);
101
  state    : cpu_state_type;
102
  start    : std_logic_vector(csync downto 0);
103
  sync     : std_logic;
104
  rready    : std_logic;
105
  wready    : std_logic;
106
end record;
107
 
108
signal clk_int : std_logic;
109
signal pr : pci_input_type;
110
signal r, rin : pci_reg_type;
111
signal r2, r2in : cpu_reg_type;
112
signal dmai : ahb_dma_in_type;
113
signal dmao : ahb_dma_out_type;
114
 
115
begin
116
 
117
-- Back-end state machine (AHB clock domain)
118
 
119
  comb : process (rst, r2, r, dmao)
120
  variable vdmai : ahb_dma_in_type;
121
  variable v : cpu_reg_type;
122
  begin
123
    v := r2;
124
    vdmai.start := '0'; vdmai.burst := '0'; vdmai.size := "10";
125
    vdmai.address := r.laddr(31 downto 2) & "00"; v.sync := '1';
126
    vdmai.wdata := r.ldata; vdmai.write := r.lwrite;
127
    v.start(0) := r2.start(csync); v.start(csync) := r.start;
128
    case r2.state is
129
    when idle =>
130
      v.sync := '0';
131
      if r2.start(0) = '1' then
132
        if  r.lwrite = '1' then v.state := sync1; v.wready := '0';
133
        else v.state := busy; vdmai.start := '1'; end if;
134
      end if;
135
    when sync1 =>
136
      if r2.start(0) = '0' then v.state := busy; vdmai.start := '1'; end if;
137
    when busy =>
138
      if dmao.active = '1' then
139
        if dmao.ready = '1' then
140
          v.rready := not r.lwrite; v.data := dmao.rdata; v.state := sync2;
141
        end if;
142
      else vdmai.start := '1'; end if;
143
    when sync2 =>
144
      if r2.start(0) = '0' then
145
        v.state := idle;  v.wready := '1'; v.rready := '0';
146
      end if;
147
    end case;
148
 
149
    if rst = '0' then
150
      v.state := idle; v.rready := '0'; v.wready := '1';
151
    end if;
152
    r2in <= v; dmai <= vdmai;
153
  end process;
154
 
155
-- PCI target core (PCI clock domain)
156
 
157
  pcicomb : process(pcirst, pr, pcii, r, r2)
158
  variable v : pci_reg_type;
159
  variable chit, mhit, hit, ready, cwrite, mwrite : std_logic;
160
  variable cdata, cwdata : std_logic_vector(31 downto 0);
161
  begin
162
    v := r; v.trdy := '1'; v.stop := '1';
163
    v.oe_ad := '1'; v.devsel := '1'; mwrite := '0';
164
    v.rready(0) := r.rready(csync); v.rready(csync) := r2.rready;
165
    v.wready(0) := r.wready(csync); v.wready(csync) := r2.wready;
166
    v.sync(0) := r.sync(csync); v.sync(csync) := r2.sync;
167
 
168
-- address decoding
169
 
170
    if (r.state = s_data) and ((pr.irdy or r.trdy or r.read) = '0') then
171
      cwrite := r.csel;
172
      if ((r.msel and r.addr(MADDR_WIDTH-1)) = '1') and (pr.cbe = "0000") then
173
        v.page := pr.ad(31 downto MADDR_WIDTH-1);
174
      end if;
175
      if (pr.cbe = "0000") and  (r.addr(MADDR_WIDTH-1) = '1') then
176
        mwrite := r.msel;
177
      end if;
178
    else cwrite := '0'; end if;
179
    cdata := (others => '0');
180
    case r.addr(7 downto 2) is
181
    when "000000" =>                    -- 0x00, device & vendor id
182
      cdata := std_logic_vector(conv_unsigned(DEVICE_ID, 16)) &
183
        std_logic_vector(conv_unsigned(VENDOR_ID, 16));
184
    when "000001" =>                    -- 0x04, status & command
185
      cdata(1) := r.men; cdata(25) := '1';
186
    when "000010" =>                    -- 0x08, class code & revision
187
    when "000011" =>                    -- 0x0c, latency & cacheline size
188
    when "000100" =>                    -- 0x10, BAR0
189
      cdata(31 downto MADDR_WIDTH) := r.bar0;
190
    when others =>
191
    end case;
192
 
193
    cwdata := pr.ad;
194
    if pr.cbe(3) = '1' then cwdata(31 downto 24) := cdata(31 downto 24); end if;
195
    if pr.cbe(2) = '1' then cwdata(23 downto 16) := cdata(23 downto 16); end if;
196
    if pr.cbe(1) = '1' then cwdata(15 downto  8) := cdata(15 downto  8); end if;
197
    if pr.cbe(0) = '1' then cwdata( 7 downto  0) := cdata( 7 downto  0); end if;
198
    if cwrite = '1' then
199
      case r.addr(7 downto 2) is
200
      when "000001" =>                  -- 0x04, status & command
201
        v.men := cwdata(1);
202
      when "000100" =>                  -- 0x10, BAR0
203
        v.bar0 := cwdata(31 downto MADDR_WIDTH);
204
      when others =>
205
      end case;
206
    end if;
207
 
208
    if (((pr.cbe = pci_config_read) or (pr.cbe = pci_config_write))
209
        and (pr.ad(1 downto 0) = "00"))
210
    then chit := '1'; else chit := '0'; end if;
211
    if ((pr.cbe = pci_memory_read) or (pr.cbe = pci_memory_write))
212
        and (r.bar0 = pr.ad(31 downto MADDR_WIDTH))
213
        and (r.bar0 /= zero(31 downto MADDR_WIDTH))
214
    then mhit := '1'; else mhit := '0'; end if;
215
    hit := r.csel or r.msel;
216
    ready := r.csel or (r.rready(0) and r.read) or (r.wready(0) and not r.read and not r.start) or
217
         r.addr(MADDR_WIDTH-1);
218
 
219
-- target state machine
220
 
221
    case r.state is
222
    when idle  =>
223
      if pr.frame = '0' then v.state := b_busy; end if; -- !HIT ?
224
      v.addr := pr.ad(MADDR_WIDTH-1 downto 0); v.cmd := pr.cbe;
225
      v.csel := pr.idsel and chit;
226
      v.msel := r.men and mhit; v.read := not pr.cbe(0);
227
      if (r.sync(0) and r.start and r.lwrite)  = '1' then v.start := '0'; end if;
228
    when turn_ar =>
229
      if pr.frame = '1' then v.state := idle; end if;
230
      if pr.frame = '0' then v.state := b_busy; end if; -- !HIT ?
231
      v.addr := pr.ad(MADDR_WIDTH-1 downto 0); v.cmd := pr.cbe;
232
      v.csel := pr.idsel and chit;
233
      v.msel := r.men and mhit; v.read := not pr.cbe(0);
234
      if (r.sync(0) and r.start and r.lwrite)  = '1' then v.start := '0'; end if;
235
    when b_busy  =>
236
      if hit = '1' then
237
        v.state := s_data; v.trdy := not ready; v.stop := pr.frame and ready;
238
        v.devsel := '0';
239
      else
240
        v.state := backoff;
241
      end if;
242
    when s_data  =>
243
      v.stop := r.stop; v.devsel := '0';
244
      v.trdy := r.trdy or not pcii.pci_irdy_in_n;
245
      if (pcii.pci_frame_in_n and not pcii.pci_irdy_in_n) = '1' then
246
        v.state := turn_ar; v.stop := '1'; v.trdy := '1'; v.devsel := '1';
247
      end if;
248
    when backoff =>
249
      if pr.frame = '1' then v.state := idle; end if;
250
    end case;
251
 
252
    if ((r.state = s_data) or (r.state = turn_ar)) and
253
       (((pr.irdy or pr.trdy) = '0') or
254
        ((not pr.irdy and not pr.stop and pr.trdy and not r.start and r.wready(0)) = '1'))
255
    then
256
      if (pr.trdy and r.read)= '0' then v.start := '0'; end if;
257
      if (r.start = '0') and ((r.msel and not r.addr(MADDR_WIDTH-1)) = '1') and
258
        (((pr.trdy and r.read) or (not pr.trdy and not r.read)) = '1')
259
      then
260
        v.laddr := r.page & r.addr(MADDR_WIDTH-2 downto 0);
261
        v.ldata := pr.ad; v.lwrite := not r.read; v.start := '1';
262
      end if;
263
    end if;
264
 
265
    if (v.state = s_data) and (r.read = '1') then v.oe_ad := '0'; end if;
266
    v.oe_par := r.oe_ad;
267
    if r.csel = '1' then v.data := cdata;
268
    elsif r.addr(MADDR_WIDTH-1) = '1' then
269
      v.data(31 downto MADDR_WIDTH-1) := r.page;
270
      v.data(MADDR_WIDTH-2 downto 0) := (others => '0');
271
    else v.data := r2.data; end if;
272
    v.par := xorv(r.data & pcii.pci_cbein_n);
273
 
274
    if (v.state = s_data) or (r.state = s_data) then
275
      v.oe_ctrl := '0';
276
    else v.oe_ctrl := '1'; end if;
277
 
278
    if pr.rst = '0' then
279
      v.state := idle; v.men := '0'; v.start := '0';
280
      v.bar0 := (others => '0'); v.msel := '0'; v.csel := '0';
281
      v.page := ('0', '1', others => '0');
282
    end if;
283
    rin <= v;
284
  end process;
285
 
286
  pcir : process (pciclk, pcirst, r2)
287
  begin
288
    if rising_edge (pciclk) then
289
      pr.ad         <= to_x01(pcii.pci_adin);
290
      pr.cbe        <= to_x01(pcii.pci_cbein_n);
291
      pr.devsel     <= to_x01(pcii.pci_devsel_in_n);
292
      pr.frame      <= to_x01(pcii.pci_frame_in_n);
293
      pr.idsel      <= to_x01(pcii.pci_idsel_in);
294
      pr.irdy       <= to_x01(pcii.pci_irdy_in_n);
295
      pr.trdy       <= to_x01(pcii.pci_trdy_in_n);
296
      pr.par        <= to_x01(pcii.pci_par_in);
297
      pr.stop       <= to_x01(pcii.pci_stop_in_n);
298
      pr.rst        <= to_x01(pcii.pci_rst_in_n);
299
      r <= rin;
300
    end if;
301
    if pcirst = '0' then -- asynch reset required
302
       r.oe_ad <= '1'; r.oe_ctrl <= '1'; r.oe_par <= '1';
303
    end if;
304
  end process;
305
 
306
  cpur : process (clk)
307
  begin
308
    if rising_edge (clk) then
309
      r2 <= r2in;
310
    end if;
311
  end process;
312
 
313
    pcio.pci_cbe0_en_n <= '1';
314
    pcio.pci_cbe1_en_n <= '1';
315
    pcio.pci_cbe2_en_n <= '1';
316
    pcio.pci_cbe3_en_n <= '1';
317
 
318
    pcio.pci_cbeout_n <= "1111";
319
 
320
    pcio.pci_aden_n <= (others => r.oe_ad);
321
    pcio.pci_adout <= r.data;
322
 
323
    pcio.pci_trdy_out_n   <= r.trdy;
324
    pcio.pci_ctrl_en_n    <= r.oe_ctrl;
325
    pcio.pci_stop_out_n   <= r.stop;
326
    pcio.pci_devsel_out_n <= r.devsel;
327
    pcio.pci_par_out     <= r.par;
328
    pcio.pci_par_en_n    <= r.oe_par;
329
    pcio.pci_perr_out_n  <= '1';
330
    pcio.pci_perr_en_n   <= '1';
331
    pcio.pci_serr_out_n  <= '1';
332
    pcio.pci_serr_en_n   <= '1';
333
    pcio.pci_int_out_n   <= '1';
334
    pcio.pci_int_en_n  <= '1';
335
 
336
    pcio.pci_req_en_n  <= '1';
337
    pcio.pci_req_out_n <= '1';
338
    pcio.pci_frame_en_n <= '1';
339
    pcio.pci_frame_out_n <= '1';
340
    pcio.pci_irdy_en_n <= '1';
341
    pcio.pci_irdy_out_n <= '1';
342
    pcio.pci_lock_en_n <= '1';
343
 
344
    ahbso.hready <= '1';
345
    ahbso.hresp <= HRESP_OKAY;
346
 
347
    ahbmst0 : ahbmst port map (rst, clk, dmai, dmao, ahbmi, ahbmo);
348
 
349
end;

powered by: WebSVN 2.1.0

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