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/] [gaisler/] [pci/] [pci_target.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 dimamali
------------------------------------------------------------------------------
2
--  This file is a part of the GRLIB VHDL IP LIBRARY
3
--  Copyright (C) 2003, Gaisler Research
4
--
5
--  This program is free software; you can redistribute it and/or modify
6
--  it under the terms of the GNU General Public License as published by
7
--  the Free Software Foundation; either version 2 of the License, or
8
--  (at your option) any later version.
9
--
10
--  This program is distributed in the hope that it will be useful,
11
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
--  GNU General Public License for more details.
14
--
15
--  You should have received a copy of the GNU General Public License
16
--  along with this program; if not, write to the Free Software
17
--  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
18
-----------------------------------------------------------------------------
19
-- Entity:      pci_target
20
-- File:        pci_target.vhd
21
-- Author:      Jiri Gaisler - Gaisler Research
22
-- Description: Simple PCI target interface
23
------------------------------------------------------------------------------
24
 
25
library ieee;
26
use ieee.std_logic_1164.all;
27
 
28
library grlib;
29
use grlib.amba.all;
30
use grlib.stdlib.all;
31
use grlib.devices.all;
32
library gaisler;
33
use gaisler.pci.all;
34
use gaisler.misc.all;
35
 
36
entity pci_target is
37
  generic (
38
    hindex    : integer := 0;
39
    abits     : integer := 21;
40
    device_id : integer := 0;            -- PCI device ID
41
    vendor_id : integer := 0;            -- PCI vendor ID
42
    nsync : integer range 1 to 2 := 1;  -- 1 or 2 sync regs between clocks
43
    oepol     : integer := 0);
44
  port(
45
    rst       : in std_logic;
46
    clk       : in std_logic;
47
    pciclk    : in std_logic;
48
    pcii      : in  pci_in_type;
49
    pcio      : out pci_out_type;
50
    ahbmi     : in  ahb_mst_in_type;
51
    ahbmo     : out ahb_mst_out_type
52
  );
53
end;
54
 
55
architecture rtl of pci_target is
56
 
57
constant REVISION : amba_version_type := 0;
58
constant hconfig : ahb_config_type := (
59
 
60
  others => zero32);
61
 
62
constant CSYNC : integer := nsync-1;
63
constant MADDR_WIDTH : integer := abits;
64
constant zero : std_logic_vector(31 downto 0) := (others => '0');
65
subtype word4 is std_logic_vector(3 downto 0);
66
subtype word32 is std_logic_vector(31 downto 0);
67
constant pci_memory_read : word4 := "0110";
68
constant pci_memory_write : word4 := "0111";
69
constant pci_config_read : word4 := "1010";
70
constant pci_config_write : word4 := "1011";
71
type pci_input_type is record
72
  ad       : std_logic_vector(31 downto 0);
73
  cbe      : std_logic_vector(3 downto 0);
74
  frame    : std_logic;
75
  devsel   : std_logic;
76
  idsel    : std_logic;
77
  trdy     : std_logic;
78
  irdy     : std_logic;
79
  par      : std_logic;
80
  stop     : std_logic;
81
  rst      : std_logic;
82
end record;
83
 
84
type pci_target_state_type is (idle, b_busy, s_data, backoff, turn_ar);
85
type pci_reg_type is record
86
  addr     : std_logic_vector(MADDR_WIDTH-1 downto 0);
87
  data     : std_logic_vector(31 downto 0);
88
  cmd      : std_logic_vector(3 downto 0);
89
  state    : pci_target_state_type;
90
  csel     : std_logic;
91
  msel     : std_logic;
92
  read     : std_logic;
93
  devsel   : std_logic;
94
  trdy     : std_logic;
95
  stop     : std_logic;
96
  par      : std_logic;
97
  oe_par   : std_logic;
98
  oe_ad    : std_logic;
99
  oe_ctrl  : std_logic;
100
  noe_par  : std_logic;
101
  noe_ad   : std_logic;
102
  noe_ctrl : std_logic;
103
  bar0     : std_logic_vector(31 downto MADDR_WIDTH);
104
  page     : std_logic_vector(31 downto MADDR_WIDTH-1);
105
  men      : std_logic;
106
  laddr    : std_logic_vector(31 downto 0);
107
  ldata    : std_logic_vector(31 downto 0);
108
  lwrite   : std_logic;
109
  start    : std_logic;
110
  rready   : std_logic_vector(csync downto 0);
111
  wready   : std_logic_vector(csync downto 0);
112
  sync     : std_logic_vector(csync downto 0);
113
end record;
114
 
115
type cpu_state_type is (idle, sync1, busy, sync2);
116
type cpu_reg_type is record
117
  data     : std_logic_vector(31 downto 0);
118
  state    : cpu_state_type;
119
  start    : std_logic_vector(csync downto 0);
120
  sync     : std_logic;
121
  rready    : std_logic;
122
  wready    : std_logic;
123
end record;
124
 
125
signal clk_int : std_logic;
126
signal pr : pci_input_type;
127
signal r, rin : pci_reg_type;
128
signal r2, r2in : cpu_reg_type;
129
signal dmai : ahb_dma_in_type;
130
signal dmao : ahb_dma_out_type;
131
 
132
signal roe_ad, rioe_ad : std_logic_vector(31 downto 0);
133
attribute syn_preserve : boolean;
134
attribute syn_preserve of roe_ad : signal is true;
135
begin
136
 
137
-- Back-end state machine (AHB clock domain)
138
 
139
  comb : process (rst, r2, r, dmao)
140
  variable vdmai : ahb_dma_in_type;
141
  variable v : cpu_reg_type;
142
  begin
143
    v := r2;
144
    vdmai.start := '0'; vdmai.burst := '0'; vdmai.size := "10";
145
    vdmai.address := r.laddr; v.sync := '1';
146
    vdmai.wdata := r.ldata; vdmai.write := r.lwrite; vdmai.irq := '0';
147
    v.start(0) := r2.start(csync); v.start(csync) := r.start;
148
    case r2.state is
149
    when idle =>
150
      v.sync := '0';
151
      if r2.start(0) = '1' then
152
        if r.lwrite = '1' then v.state := sync1; v.wready := '0';
153
        else v.state := busy; vdmai.start := '1'; end if;
154
      end if;
155
    when sync1 =>
156
      if r2.start(0) = '0' then v.state := busy; vdmai.start := '1'; end if;
157
    when busy =>
158
      if dmao.active = '1' then
159
        if dmao.ready = '1' then
160
          v.rready := not r.lwrite; v.data := dmao.rdata; v.state := sync2;
161
        end if;
162
      else vdmai.start := '1'; end if;
163
    when sync2 =>
164
      if r2.start(0) = '0' then
165
        v.state := idle;  v.wready := '1'; v.rready := '0';
166
      end if;
167
    end case;
168
 
169
    if rst = '0' then
170
      v.state := idle; v.rready := '0'; v.wready := '1';
171
    end if;
172
    r2in <= v; dmai <= vdmai;
173
  end process;
174
 
175
-- PCI target core (PCI clock domain)
176
 
177
  pcicomb : process(pr, pcii, r, r2, roe_ad)
178
  variable v : pci_reg_type;
179
  variable chit, mhit, hit, ready, cwrite, mwrite : std_logic;
180
  variable cdata, cwdata : std_logic_vector(31 downto 0);
181
  variable caddr : std_logic_vector(7 downto 2);
182
  variable voe_ad : std_logic_vector(31 downto 0);
183
  variable oe_ctrl, oe_par, oe_ad : std_ulogic;
184
  begin
185
    v := r; v.trdy := '1'; v.stop := '1'; voe_ad := roe_ad;
186
    v.oe_ad := '1'; v.devsel := '1'; mwrite := '0';
187
    v.rready(0) := r.rready(csync); v.rready(csync) := r2.rready;
188
    v.wready(0) := r.wready(csync); v.wready(csync) := r2.wready;
189
    v.sync(0) := r.sync(csync); v.sync(csync) := r2.sync;
190
 
191
-- address decoding
192
 
193
    if (r.state = s_data) and ((pr.irdy or r.trdy or r.read) = '0') then
194
      cwrite := r.csel;
195
      if ((r.msel and r.addr(MADDR_WIDTH-1)) = '1') and (pr.cbe = "0000") then
196
        v.page := pr.ad(31 downto MADDR_WIDTH-1);
197
      end if;
198
      if (pr.cbe = "0000") and  (r.addr(MADDR_WIDTH-1) = '1') then
199
        mwrite := r.msel;
200
      end if;
201
    else cwrite := '0'; end if;
202
    cdata := (others => '0'); caddr :=  r.addr(7 downto 2);
203
    case caddr is
204
    when "000000" =>                    -- 0x00, device & vendor id
205
      cdata := conv_std_logic_vector(DEVICE_ID, 16) &
206
        conv_std_logic_vector(VENDOR_ID, 16);
207
    when "000001" =>                    -- 0x04, status & command
208
      cdata(1) := r.men; cdata(26) := '1';
209
    when "000010" =>                    -- 0x08, class code & revision
210
    when "000011" =>                    -- 0x0c, latency & cacheline size
211
    when "000100" =>                    -- 0x10, BAR0
212
      cdata(31 downto MADDR_WIDTH) := r.bar0;
213
    when others =>
214
    end case;
215
 
216
    cwdata := pr.ad;
217
    if pr.cbe(3) = '1' then cwdata(31 downto 24) := cdata(31 downto 24); end if;
218
    if pr.cbe(2) = '1' then cwdata(23 downto 16) := cdata(23 downto 16); end if;
219
    if pr.cbe(1) = '1' then cwdata(15 downto  8) := cdata(15 downto  8); end if;
220
    if pr.cbe(0) = '1' then cwdata( 7 downto  0) := cdata( 7 downto  0); end if;
221
    if cwrite = '1' then
222
      case caddr is
223
      when "000001" =>                  -- 0x04, status & command
224
        v.men := cwdata(1);
225
      when "000100" =>                  -- 0x10, BAR0
226
        v.bar0 := cwdata(31 downto MADDR_WIDTH);
227
      when others =>
228
      end case;
229
    end if;
230
 
231
    if (((pr.cbe = pci_config_read) or (pr.cbe = pci_config_write))
232
        and (pr.ad(1 downto 0) = "00"))
233
    then chit := '1'; else chit := '0'; end if;
234
    if ((pr.cbe = pci_memory_read) or (pr.cbe = pci_memory_write))
235
        and (r.bar0 = pr.ad(31 downto MADDR_WIDTH))
236
        and (r.bar0 /= zero(31 downto MADDR_WIDTH))
237
    then mhit := '1'; else mhit := '0'; end if;
238
    hit := r.csel or r.msel;
239
    ready := r.csel or (r.rready(0) and r.read) or (r.wready(0) and not r.read and not r.start) or
240
         r.addr(MADDR_WIDTH-1);
241
 
242
-- target state machine
243
 
244
    case r.state is
245
    when idle  =>
246
      if pr.frame = '0' then v.state := b_busy; end if; -- !HIT ?
247
      v.addr := pr.ad(MADDR_WIDTH-1 downto 0); v.cmd := pr.cbe;
248
      v.csel := pr.idsel and chit;
249
      v.msel := r.men and mhit; v.read := not pr.cbe(0);
250
      if (r.sync(0) and r.start and r.lwrite)  = '1' then v.start := '0'; end if;
251
    when turn_ar =>
252
      if pr.frame = '1' then v.state := idle; end if;
253
      if pr.frame = '0' then v.state := b_busy; end if; -- !HIT ?
254
      v.addr := pr.ad(MADDR_WIDTH-1 downto 0); v.cmd := pr.cbe;
255
      v.csel := pr.idsel and chit;
256
      v.msel := r.men and mhit; v.read := not pr.cbe(0);
257
      if (r.sync(0) and r.start and r.lwrite)  = '1' then v.start := '0'; end if;
258
    when b_busy  =>
259
      if hit = '1' then
260
        v.state := s_data; v.trdy := not ready; v.stop := pr.frame and ready;
261
        v.devsel := '0';
262
      else
263
        v.state := backoff;
264
      end if;
265
    when s_data  =>
266
      v.stop := r.stop; v.devsel := '0';
267
      v.trdy := r.trdy or not pcii.irdy;
268
      if (pcii.frame and not pcii.irdy) = '1' then
269
        v.state := turn_ar; v.stop := '1'; v.trdy := '1'; v.devsel := '1';
270
      end if;
271
    when backoff =>
272
      if pr.frame = '1' then v.state := idle; end if;
273
    end case;
274
 
275
    if ((r.state = s_data) or (r.state = turn_ar)) and
276
       (((pr.irdy or pr.trdy) = '0') or
277
        ((not pr.irdy and not pr.stop and pr.trdy and not r.start and r.wready(0)) = '1'))
278
    then
279
      if (pr.trdy and r.read)= '0' then v.start := '0'; end if;
280
      if (r.start = '0') and ((r.msel and not r.addr(MADDR_WIDTH-1)) = '1') and
281
        (((pr.trdy and r.read and not r.rready(0)) or (not pr.trdy and not r.read)) = '1')
282
      then
283
        v.laddr := r.page & r.addr(MADDR_WIDTH-2 downto 0);
284
        v.ldata := pr.ad; v.lwrite := not r.read; v.start := '1';
285
      end if;
286
    end if;
287
 
288
    if (v.state = s_data) and (r.read = '1') then v.oe_ad := '0'; end if;
289
    v.oe_par := r.oe_ad;
290
    if r.csel = '1' then v.data := cdata;
291
    elsif r.addr(MADDR_WIDTH-1) = '1' then
292
      v.data(31 downto MADDR_WIDTH-1) := r.page;
293
      v.data(MADDR_WIDTH-2 downto 0) := (others => '0');
294
    else v.data := r2.data; end if;
295
    v.par := xorv(r.data & pcii.cbe);
296
 
297
    if (v.state = s_data) or (r.state = s_data) then
298
      v.oe_ctrl := '0';
299
    else v.oe_ctrl := '1'; end if;
300
 
301
    v.noe_ctrl := not v.oe_ctrl; v.noe_ad := not v.oe_ad; v.noe_par := not v.oe_par;
302
 
303
    if oepol = 1 then
304
      oe_ctrl := r.noe_ctrl; oe_ad := r.noe_ad; oe_par := r.noe_par;
305
      voe_ad := (others => v.noe_ad);
306
    else
307
      oe_ctrl := r.oe_ctrl; oe_ad := r.oe_ad; oe_par := r.oe_par;
308
      voe_ad := (others => v.oe_ad);
309
    end if;
310
 
311
    if pr.rst = '0' then
312
      v.state := idle; v.men := '0'; v.start := '0';
313
      v.bar0 := (others => '0'); v.msel := '0'; v.csel := '0';
314
      v.page := (others => '0');
315
      v.page(31 downto 30) := "01";
316
    end if;
317
    rin <= v;
318
    rioe_ad <= voe_ad;
319
 
320
 
321
    pcio.ctrlen   <= oe_ctrl;
322
    pcio.trdy     <= r.trdy;
323
    pcio.trdyen   <= oe_ctrl;
324
    pcio.stop     <= r.stop;
325
    pcio.stopen   <= oe_ctrl;
326
    pcio.devsel   <= r.devsel;
327
    pcio.devselen <= oe_ctrl;
328
    pcio.par      <= r.par;
329
    pcio.paren    <= oe_par;
330
    pcio.aden     <= oe_ad;
331
    pcio.ad       <= r.data;
332
 
333
    pcio.rst      <= '1';
334
 
335
  end process;
336
 
337
  pcir : process (pciclk, pcii.rst, r2)
338
  begin
339
    if rising_edge (pciclk) then
340
      pr.ad         <= to_x01(pcii.ad);
341
      pr.cbe        <= to_x01(pcii.cbe);
342
      pr.devsel     <= to_x01(pcii.devsel);
343
      pr.frame      <= to_x01(pcii.frame);
344
      pr.idsel      <= to_x01(pcii.idsel);
345
      pr.irdy       <= to_x01(pcii.irdy);
346
      pr.trdy       <= to_x01(pcii.trdy);
347
      pr.par        <= to_x01(pcii.par);
348
      pr.stop       <= to_x01(pcii.stop);
349
      pr.rst        <= to_x01(pcii.rst);
350
      r <= rin;
351
      roe_ad <= rioe_ad;
352
    end if;
353
    if pcii.rst = '0' then       -- asynch reset required
354
      r.oe_ctrl <= '1'; r.oe_par <= '1'; r.oe_ad <= '1';
355
      r.noe_ctrl <= '0'; r.noe_par <= '0'; r.noe_ad <= '0';
356
 
357
      if oepol = 0 then roe_ad <= (others => '1');
358
      else roe_ad <= (others => '0'); end if;
359
    end if;
360
  end process;
361
 
362
  cpur : process (clk)
363
  begin
364
    if rising_edge (clk) then
365
      r2 <= r2in;
366
    end if;
367
  end process;
368
 
369
  oe0 : if oepol = 0 generate
370
    pcio.perren  <= '1';
371
    pcio.cbeen   <= (others => '1');
372
    pcio.serren  <= '1';
373
    pcio.inten   <= '1';
374
    pcio.reqen   <= not pcii.rst;
375
    pcio.frameen <= '1';
376
    pcio.irdyen  <= '1';
377
    pcio.locken  <= '1';
378
  end generate;
379
 
380
  oe1 : if oepol = 1 generate
381
    pcio.perren  <= '0';
382
    pcio.cbeen   <= (others => '0');
383
    pcio.serren  <= '0';
384
    pcio.inten   <= '0';
385
    pcio.reqen   <= pcii.rst;
386
    pcio.frameen <= '0';
387
    pcio.irdyen  <= '0';
388
    pcio.locken  <= '0';
389
  end generate;
390
 
391
  pcio.vaden   <= roe_ad;
392
 
393
  pcio.cbe   <= "1111";
394
  pcio.perr  <= '1';
395
  pcio.serr  <= '1';
396
  pcio.int   <= '1';
397
  pcio.req   <= '1';
398
  pcio.frame <= '1';
399
  pcio.irdy  <= '1';
400
 
401
 
402
  ahbmst0 : ahbmst generic map (hindex => hindex, devid => GAISLER_PCITRG)
403
        port map (rst, clk, dmai, dmao, ahbmi, ahbmo);
404
 
405
-- pragma translate_off
406
    bootmsg : report_version
407
    generic map ("pci_target" & tost(hindex) &
408
        ": 32-bit PCI Target rev " & tost(REVISION) &
409
        ", " & tost(abits) & "-bit PCI memory BAR" );
410
-- pragma translate_on
411
 
412
 
413
end;

powered by: WebSVN 2.1.0

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