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/] [pcitb_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:      pcitb_target
20
-- File:        pcitb_target.vhd
21
-- Author:      Alf Vaerneus, Gaisler Research
22
-- Description: PCI Target emulator.
23
------------------------------------------------------------------------------
24
 
25
-- pragma translate_off
26
 
27
library ieee;
28
use ieee.std_logic_1164.all;
29
 
30
library grlib;
31
use grlib.stdlib.all;
32
library gaisler;
33
use gaisler.pcitb.all;
34
use gaisler.pcilib.all;
35
use gaisler.ambatest.all;
36
 
37
 
38
library std;
39
use std.textio.all;
40
 
41
 
42
entity pcitb_target is
43
  generic (
44
    slot : integer := 0;
45
    abits : integer := 10;
46
    bars : integer := 1;
47
    resptime : integer := 2;
48
    latency : integer := 0;
49
    rbuf : integer := 8;
50
    stopwd : boolean := true;
51
    tval : time := 7 ns;
52
    conf : config_header_type := config_init;
53
    dbglevel : integer := 1);
54
  port (
55
    -- PCI signals
56
    pciin     : in pci_type;
57
    pciout    : out pci_type;
58
    -- TB signals
59
    tbi       : in  tb_in_type;
60
    tbo       : out  tb_out_type
61
       );
62
end pcitb_target;
63
 
64
architecture tb of pcitb_target is
65
 
66
constant T_O : integer := 9;
67
constant word : std_logic_vector(2 downto 0) := "100";
68
 
69
type mem_type is array(0 to ((2**abits)-1)) of std_logic_vector(31 downto 0);
70
 
71
type state_type is(idle,respwait,write,read,latw);
72
type reg_type is record
73
  state         : state_type;
74
  pci           : pci_type;
75
  pcien         : std_logic;
76
  aden          : std_logic;
77
  paren         : std_logic;
78
  erren         : std_logic;
79
  write         : std_logic;
80
  waitcycles    : integer;
81
  latcnt        : integer;
82
  curword       : integer;
83
  first         : boolean;
84
  di            : std_logic_vector(31 downto 0);
85
  ad            : std_logic_vector(31 downto 0);
86
  comm          : std_logic_vector(3 downto 0);
87
  config        : config_header_type;
88
  cbe           : std_logic_vector(3 downto 0); -- *** sub-word write
89
end record;
90
 
91
signal r,rin : reg_type;
92
signal do : std_logic_vector(31 downto 0);
93
 
94
procedure writeconf(ad : in std_logic_vector(5 downto 0);
95
                    data : in std_logic_vector(31 downto 0);
96
                    vconfig : out config_header_type) is
97
begin
98
  case conv_integer(ad) is
99
--  when 0 => vconfig.devid := data(31 downto 16); vconfig.vendid <= data(15 downto 0);
100
  when 1 => vconfig.status := data(31 downto 16); vconfig.command := data(15 downto 0);
101
  when 2 => vconfig.class_code := data(31 downto 8); vconfig.revid := data(7 downto 0);
102
  when 3 => vconfig.bist := data(31 downto 24); vconfig.header_type := data(23 downto 16);
103
            vconfig.lat_timer := data(15 downto 8); vconfig.cache_lsize := data(7 downto 0);
104
  when 4 => vconfig.bar(0) := data;
105
  when 5 => vconfig.bar(1) := data;
106
  when 6 => vconfig.bar(2) := data;
107
  when 7 => vconfig.bar(3) := data;
108
  when 8 => vconfig.bar(4) := data;
109
  when 9 => vconfig.bar(5) := data;
110
  when 10 => vconfig.cis_p := data;
111
  when 11 => vconfig.subid := data(31 downto 16); vconfig.subvendid := data(15 downto 0);
112
  when 12 => vconfig.exp_rom_ba := data;
113
  when 13 => vconfig.max_lat := data(31 downto 24); vconfig.min_gnt := data(23 downto 16);
114
             vconfig.int_pin := data(15 downto 8); vconfig.int_line := data(7 downto 0);
115
  when others =>
116
  end case;
117
end procedure;
118
 
119
procedure readconf(ad : in std_logic_vector(5 downto 0); data : out std_logic_vector(31 downto 0)) is
120
begin
121
  case conv_integer(ad) is
122
  when 0 => data(31 downto 16) := (conv_std_logic_vector(slot,4) & r.config.devid(11 downto 0));
123
            data(15 downto 0) := r.config.vendid;
124
  when 1 => data(31 downto 16) := r.config.status; data(15 downto 0) := r.config.command;
125
  when 2 => data(31 downto 8) := r.config.class_code; data(7 downto 0) := r.config.revid;
126
  when 3 => data(31 downto 24) := r.config.bist; data(23 downto 16) := r.config.header_type;
127
            data(15 downto 8) := r.config.lat_timer; data(7 downto 0) := r.config.cache_lsize;
128
  when 4 => data := r.config.bar(0)(31 downto abits) & zero32(abits-1 downto 0);
129
  when 5 => if bars > 1 then data := r.config.bar(1)(31 downto 9) & zero32(8 downto 1) & '1';
130
            else data := (others => '0'); end if;
131
  when 6 => if bars > 2 then data := r.config.bar(2)(31 downto abits) & zero32(abits-1 downto 0);
132
            else data := (others => '0'); end if;
133
  when 7 => if bars > 3 then data := r.config.bar(3)(31 downto abits) & zero32(abits-1 downto 0);
134
            else data := (others => '0'); end if;
135
  when 8 => if bars > 4 then data := r.config.bar(4)(31 downto abits) & zero32(abits-1 downto 0);
136
            else data := (others => '0'); end if;
137
  when 9 => if bars > 5 then data := r.config.bar(5)(31 downto abits) & zero32(abits-1 downto 0);
138
            else data := (others => '0'); end if;
139
  when 10 => data := r.config.cis_p;
140
  when 11 => data(31 downto 16) := r.config.subid; data(15 downto 0) := r.config.subvendid;
141
  when 12 => data := r.config.exp_rom_ba;
142
  when 13 => data(31 downto 24) := r.config.max_lat; data(23 downto 16) := r.config.min_gnt;
143
             data(15 downto 8) := r.config.int_pin; data(7 downto 0) := r.config.int_line;
144
  when others =>
145
  end case;
146
end procedure;
147
 
148
function pci_hit(ad : std_logic_vector(31 downto 0);
149
                 c : std_logic_vector(3 downto 0);
150
                 idsel : std_logic;
151
                 con : config_header_type) return boolean is
152
variable hit : boolean;
153
begin
154
  hit := false;
155
 
156
  if ((c = CONF_READ or c = CONF_WRITE)
157
  and idsel = '1' and ad(1 downto 0) = "00")
158
  then hit := true;
159
  else
160
    for i in 0 to bars loop
161
      if i = 1 then
162
        if ((c = IO_READ or c = IO_WRITE)
163
        and ad(31 downto abits) = con.bar(i)(31 downto abits))
164
        then hit := true; end if;
165
      else
166
        if ((c = MEM_READ or c = MEM_WRITE or c = MEM_R_MULT or c = MEM_R_LINE or c = MEM_W_INV)
167
        and ad(31 downto abits) = con.bar(i)(31 downto abits))
168
        then hit := true; end if;
169
      end if;
170
    end loop;
171
  end if;
172
  return(hit);
173
end function;
174
 
175
 
176
 
177
begin
178
 
179
  cont : process
180
  file readfile,writefile : text;
181
  variable first : boolean := true;
182
  variable mem : mem_type;
183
  variable L : line;
184
  variable datahex : string(1 to 8);
185
  variable count : integer;
186
  begin
187
    if first then
188
      for i in 0 to ((2**abits)-1) loop
189
        mem(i) := (others => '0');
190
      end loop;
191
      first := false;
192
    elsif tbi.start = '1' then
193
      if tbi.usewfile then
194
        file_open(writefile, external_name => tbi.wfile(18 downto trimlen(tbi.wfile)), open_kind => write_mode);
195
        count := conv_integer(tbi.address);
196
        for i in 0 to tbi.no_words-1 loop
197
          write(L,printhex(mem(count),32));
198
          writeline(writefile,L);
199
          count := count+4;
200
        end loop;
201
        file_close(writefile);
202
      end if;
203
    elsif r.ad(0) /= 'U' then
204
      do <= mem(conv_integer(to_x01(r.ad)));
205
      --if r.write = '1' then mem(conv_integer(to_x01(r.ad))) := r.di; end if; -- *** sub-word write
206
      if r.write = '1' then
207
        case r.cbe is
208
        when "1110" =>
209
          mem(conv_integer(to_x01(r.ad)))(7 downto 0) := r.di(7 downto 0);
210
        when "1101" =>
211
          mem(conv_integer(to_x01(r.ad)))(15 downto 8) := r.di(15 downto 8);
212
        when "1011" =>
213
          mem(conv_integer(to_x01(r.ad)))(23 downto 16) := r.di(23 downto 16);
214
        when "0111" =>
215
          mem(conv_integer(to_x01(r.ad)))(31 downto 24) := r.di(31 downto 24);
216
        when "1100" =>
217
          mem(conv_integer(to_x01(r.ad)))(15 downto 0) := r.di(15 downto 0);
218
        when "0011" =>
219
          mem(conv_integer(to_x01(r.ad)))(31 downto 16) := r.di(31 downto 16);
220
        when others =>
221
          mem(conv_integer(to_x01(r.ad))) := r.di;
222
        end case;
223
      end if;
224
    end if;
225
    tbo.ready <= tbi.start;
226
    wait for 1 ns;
227
  end process;
228
 
229
  comb : process(pciin, do)
230
  variable v : reg_type;
231
  begin
232
    v := r; v.write := '0';
233
    v.pci.ad.par := xorv(r.pci.ad.ad & pciin.ad.cbe);
234
    v.paren := r.aden; v.erren := r.paren;
235
 
236
    case r.state is
237
    when idle =>
238
      if (r.pci.ifc.trdy and r.pci.ifc.stop and r.pci.ifc.devsel) = '1' then v.pcien := '1'; end if;
239
      v.aden := '1'; v.waitcycles := 1; v.latcnt := latency; v.first := true;
240
      v.pci.ifc.trdy := '1'; v.pci.ifc.stop := '1'; v.curword := 0;
241
      v.pci.ifc.devsel := '1'; v.pci.err.perr := '1';
242
      if pciin.ifc.frame = '0' then
243
        v.comm := pciin.ad.cbe;
244
        if pci_hit(pciin.ad.ad,pciin.ad.cbe,pciin.ifc.idsel(slot),v.config) then
245
          v.ad := zero32(31 downto abits) & pciin.ad.ad(abits-1 downto 0);
246
          if r.waitcycles = resptime then
247
            v.pci.ifc.devsel := '0'; v.pcien := '0';
248
            if pciin.ad.cbe(0) = '1' then v.state := write; v.pci.ifc.trdy := '0';
249
            else v.state := read; v.aden := '0'; end if;
250
          else v.state := respwait; v.waitcycles := r.waitcycles+1; end if;
251
        end if;
252
      end if;
253
    when respwait => -- Initial response time
254
      if r.waitcycles = resptime then
255
        v.pci.ifc.devsel := '0'; v.pcien := '0';
256
        if r.comm(0) = '1' then v.state := write; v.pci.ifc.trdy := '0';
257
        else v.state := read; v.aden := '0'; end if;
258
      else v.waitcycles := r.waitcycles+1; end if;
259
    when write => -- Write access
260
      if pciin.ifc.irdy = '0' then
261
        v.curword := r.curword+1;
262
        if r.comm = CONF_WRITE then writeconf(r.ad(7 downto 2),pciin.ad.ad,v.config);
263
        --else v.di := pciin.ad.ad; v.write := '1'; end if; -- *** sub-word write
264
        else v.di := pciin.ad.ad; v.write := '1'; v.cbe := pciin.ad.cbe; end if;
265
      end if;
266
      if r.write = '1' then v.ad := r.ad + "100"; end if;
267
      if pciin.ifc.frame = '1' then
268
        v.state := idle;
269
        v.pci.ifc.trdy := '1'; v.pci.ifc.devsel := '1';
270
      elsif (r.latcnt > 0 and pciin.ifc.irdy = '0') then v.state := latw; v.pci.ifc.trdy := '1'; v.latcnt := r.latcnt-1;
271
      end if;
272
    when read => -- Read access
273
      v.pci.ifc.trdy := '0';
274
      if (pciin.ifc.irdy = '0' or r.first = true) then
275
        v.ad := r.ad + "100"; v.first := false;
276
        if r.comm = CONF_READ then readconf(r.ad(7 downto 2),v.pci.ad.ad);
277
        else v.pci.ad.ad := do; end if;
278
      end if;
279
      if (pciin.ifc.trdy or pciin.ifc.irdy) = '0' then v.curword := r.curword+1; end if;
280
      if (pciin.ifc.frame and not (pciin.ifc.trdy and pciin.ifc.stop)) = '1' then
281
        v.state := idle; v.aden := '1';
282
        v.pci.ifc.trdy := '1'; v.pci.ifc.devsel := '1';
283
      elsif (r.latcnt > 0 and (pciin.ifc.trdy or pciin.ifc.irdy) = '0' and pciin.ifc.stop = '1') then
284
        v.state := latw; v.latcnt := r.latcnt-1; v.pci.ifc.trdy := '1';
285
      end if;
286
    when latw => -- Latency between data phases
287
      v.pci.ifc.trdy := '1';
288
      if r.write = '1' then v.ad := r.ad + "100"; end if;
289
      if (r.latcnt <= 1 and r.comm(0) = '0') then
290
        v.latcnt := latency;
291
        v.state := read; v.aden := '0';
292
      elsif r.latcnt = 0 then
293
        v.latcnt := latency;
294
        v.state := write; v.pci.ifc.trdy := '0';
295
      else v.latcnt := r.latcnt-1; end if;
296
    when others =>
297
    end case;
298
 
299
    -- Disconnect type
300
    if ((v.curword+1) >= rbuf) then
301
      if pciin.ifc.frame = '1' then
302
        v.pci.ifc.stop := '1';
303
      elsif stopwd then
304
        if r.pci.ifc.stop = '1' then
305
          v.pci.ifc.stop := v.pci.ifc.trdy;
306
        else
307
          if pciin.ifc.irdy = '0' then v.pci.ifc.trdy := '1'; end if;
308
          v.pci.ifc.stop := '0';
309
        end if;
310
      else
311
        v.pci.ifc.stop := '0';
312
        v.pci.ifc.trdy := '1';
313
      end if;
314
    end if;
315
 
316
    if pciin.syst.rst = '0' then
317
      v.state := idle;
318
      v.config := conf;
319
      v.waitcycles := 1;
320
      v.latcnt := latency;
321
      v.ad := (others => '0');
322
      v.di := (others => '0');
323
    end if;
324
 
325
    rin <= v;
326
 
327
  end process;
328
 
329
  clockreg : process(pciin.syst)
330
  begin
331
    if rising_edge(pciin.syst.clk) then
332
      r <= rin;
333
    end if;
334
  end process;
335
 
336
  pciout.ad.ad <= r.pci.ad.ad after tval when r.aden = '0' else (others => 'Z') after tval;
337
  pciout.ad.par <= r.pci.ad.par after tval when (r.paren = '0' and (r.pci.ad.par = '1' or r.pci.ad.par = '0')) else 'Z' after tval;
338
  pciout.ifc.trdy <= r.pci.ifc.trdy after tval when r.pcien = '0' else 'Z' after tval;
339
  pciout.ifc.stop <= r.pci.ifc.stop after tval when r.pcien = '0' else 'Z' after tval;
340
  pciout.ifc.devsel <= r.pci.ifc.devsel after tval when r.pcien = '0' else 'Z' after tval;
341
  pciout.err.perr <= r.pci.err.perr after tval when r.erren = '0' else 'Z' after tval;
342
 
343
end;
344
 
345
-- pragma translate_on

powered by: WebSVN 2.1.0

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