1 |
9 |
buenos |
-- *************************************************************** //
|
2 |
|
|
-- //
|
3 |
|
|
-- PCI_TARGET-Wishbone_MASTER INTERFACE MODULE (PCI-mini) //
|
4 |
|
|
-- v4.0 //
|
5 |
|
|
-- //
|
6 |
|
|
-- The original PCI module is from: Ben Jackson. //
|
7 |
|
|
-- http://www.ben.com/minipci/verilog.php //
|
8 |
|
|
-- //
|
9 |
|
|
-- Istvan Nagy, buenos@freemail.hu //
|
10 |
|
|
-- //
|
11 |
|
|
-- //
|
12 |
|
|
-- DOWNLOADED FROM OPENCORES. (License = GPL) //
|
13 |
|
|
-- //
|
14 |
|
|
-- *************************************************************** //
|
15 |
|
|
--
|
16 |
|
|
-- The core implements a 16MB relocable memory image. Relocable on the
|
17 |
|
|
-- wb bus. the wb address = 4M*wb_baseaddr_reg + PCI_addr[23:2]
|
18 |
|
|
-- Only Dword aligned Dword accesses allowed on the PCI. This way
|
19 |
|
|
-- we can access to the 4GB wb-space through a 16MB PCI-window.
|
20 |
|
|
-- The addressing on the wb-bus, is Dword addressing, while on the
|
21 |
|
|
-- PCI bus, the addressing is byte addressing. A(pci)=A(wb)*4
|
22 |
|
|
-- The PCI address is increasing by 4, and we get 4 bytes. The wb
|
23 |
|
|
-- address is increasing by 1, and we get 1 Dword (= 4 bytes also).
|
24 |
|
|
-- The wb_baseaddr_reg is the wb image relocation register, can be
|
25 |
|
|
-- accessed at 50h address in the PCI configuration space.
|
26 |
|
|
-- Other bridge status and command is at the 54h and 58h addresses.
|
27 |
|
|
-- if access fails with timeout, then the address will be in the
|
28 |
|
|
-- wb address will be stored in the failed_addr_reg at 5Ch address.
|
29 |
|
|
--
|
30 |
|
|
-- Wishbone compatibility:
|
31 |
|
|
-- Wishbone signals: wb_address, wb_dat_o, wb_dat_i, wb_sel_o, wb_cyc_o,
|
32 |
|
|
-- wb_stb_o, wb_wr_o, wb_reset_o, wb_clk_o, wb_ack_i.
|
33 |
|
|
-- Not implemented wb signals: error, lock, retry, tag-signals.
|
34 |
|
|
-- The peripheral has to response with ack in 16 clk cycles.
|
35 |
|
|
-- The core has wishbone clk and reset outputs, just like a Syscon module.
|
36 |
|
|
-- The core generates single reads/writes. These are made of 4 phases, so
|
37 |
|
|
-- dont write new data, until internal data movement finishes: about 300...500ns
|
38 |
|
|
--
|
39 |
|
|
-- PCI compatibility:
|
40 |
|
|
-- Only single DWORD reads/writes are supported. between them, the software has
|
41 |
|
|
-- to wait 300...500nsec, to prevent data corrupting. STOP signaling is not
|
42 |
|
|
-- implemented, so target terminations also not.
|
43 |
|
|
-- Single Byte access is NOT supported! It may cause corrupt data.
|
44 |
|
|
-- The core uses INTA interrupt signal. There are some special PCI config
|
45 |
|
|
-- registers, from 50h...60h config-space addresses.
|
46 |
|
|
-- PCI-parity: it generates parity, but doesnt check incoming parity.
|
47 |
|
|
-- Because of the PC chipset, if you read a value and write it back,
|
48 |
|
|
-- the chipset will not write anything, because it can see the data is not
|
49 |
|
|
-- changed. This is important at some peripherals, where you write, to control.
|
50 |
|
|
-- Device specific PCI config header registers:
|
51 |
|
|
-- name: addr: function:
|
52 |
|
|
-- wb_baseaddr_reg; 50h A(wb)=(A(pci)-BAR0)/4 + wb_baseaddr_reg. RESET TO 0
|
53 |
|
|
-- user_status_reg; 54h not used yet
|
54 |
|
|
-- user_command_reg; 58h not used yet
|
55 |
|
|
-- failed_addr_reg; 5Ch address, when timeout occurs on the wb bus.
|
56 |
|
|
--
|
57 |
|
|
-- Local bus arbitration:
|
58 |
|
|
-- This is not really wishbone compatible, but needed for the PCI.
|
59 |
|
|
-- The method is: "brute force". it means if the PCI interface wants to
|
60 |
|
|
-- be mastering on the local (wishbone) bus, then it will be mastering,
|
61 |
|
|
-- so, the other master(s) must stop anything immediately. The req signal
|
62 |
|
|
-- goes high when there is an Address hit on teh PCI bus. so the other
|
63 |
|
|
-- master has few clk cycles to finish.
|
64 |
|
|
-- Restrictions: the peripherals have to be fast: If the other master
|
65 |
|
|
-- starts a transaction before req goes high, the ack has to arrive before
|
66 |
|
|
-- the PCI interface starts its own transaction. (max 4clk ACK delay)
|
67 |
|
|
-- The other master or the bus unit must sense the req, and give bus
|
68 |
|
|
-- mastering to the PCI-IF immediatelly, not just when the other master
|
69 |
|
|
-- finished everything, like at normal arbitration schemes.
|
70 |
|
|
--
|
71 |
|
|
-- Buffering:
|
72 |
|
|
-- There is a single Dword buffering only.
|
73 |
|
|
--
|
74 |
|
|
-- The led_out interface:
|
75 |
|
|
-- only for system-debug: we can write to the LEDs, at any address.
|
76 |
|
|
-- (in the same time there is a wishbone write also)
|
77 |
|
|
--
|
78 |
|
|
-- Changes since original version: wishbone interface,
|
79 |
|
|
-- bigger memory-image, parity-generation,
|
80 |
|
|
-- interrupt handling. Code size is 3x bigger. New registers,
|
81 |
|
|
-- V4.0 is completely re-written from scratch in VHDL. It has some features removed,
|
82 |
|
|
-- like address remapping or user reset control.
|
83 |
|
|
--
|
84 |
|
|
-- Device Compatibility:
|
85 |
|
|
-- Until v3.3 the code was tested on Xilinx FPGAs (sp2, sp3) with ISE 4.7-9.1 and VIA/AMD chipsets.
|
86 |
|
|
-- Version 3.4 has modifications to work on Actel/Microsemi ProASIC3 with Sinplify and Intel Atom chipset.
|
87 |
|
|
-- (v3.4 was not tested on Xilinx FPGAs) To make sure that it runs on the Actel FPGA, we have to use the
|
88 |
|
|
-- timing constraint SDC file, AND ALSO set the P&R to Timing optimized and "effort"=high.
|
89 |
|
|
--
|
90 |
|
|
-- *************************************************************** //
|
91 |
|
|
|
92 |
|
|
|
93 |
|
|
library IEEE;
|
94 |
|
|
use IEEE.STD_LOGIC_1164.ALL;
|
95 |
|
|
use IEEE.STD_LOGIC_ARITH.ALL;
|
96 |
|
|
use IEEE.STD_LOGIC_UNSIGNED.ALL;
|
97 |
|
|
|
98 |
|
|
|
99 |
|
|
--entity header ----------------------------------------------------------------
|
100 |
|
|
entity pci is
|
101 |
|
|
Port ( --ports:
|
102 |
|
|
reset : in std_logic;
|
103 |
|
|
pciclk : in std_logic;
|
104 |
|
|
frame : in std_logic;
|
105 |
|
|
irdy : in std_logic;
|
106 |
|
|
trdy : out std_logic;
|
107 |
|
|
devsel : out std_logic;
|
108 |
|
|
idsel : in std_logic;
|
109 |
|
|
ad : inout std_logic_vector(31 downto 0);
|
110 |
|
|
cbe : in std_logic_vector(3 downto 0);
|
111 |
|
|
par : inout std_logic;
|
112 |
|
|
stop : out std_logic;
|
113 |
|
|
inta : out std_logic;
|
114 |
|
|
serr : out std_logic;
|
115 |
|
|
perr : out std_logic;
|
116 |
|
|
led_out : out std_logic_vector(3 downto 0);
|
117 |
|
|
wb_address : out std_logic_vector(31 downto 0);
|
118 |
|
|
wb_dat_o : out std_logic_vector(31 downto 0);
|
119 |
|
|
wb_dat_i : in std_logic_vector(31 downto 0);
|
120 |
|
|
wb_sel_o : out std_logic_vector(3 downto 0);
|
121 |
|
|
wb_cyc_o : out std_logic;
|
122 |
|
|
wb_stb_o : out std_logic;
|
123 |
|
|
wb_wr_o : out std_logic;
|
124 |
|
|
wb_reset_o : out std_logic;
|
125 |
|
|
wb_clk_o : out std_logic;
|
126 |
|
|
wb_ack_i : in std_logic;
|
127 |
|
|
wb_irq : in std_logic;
|
128 |
|
|
wb_req : out std_logic;
|
129 |
|
|
wb_gnt : in std_logic;
|
130 |
|
|
wb_req_other : in std_logic;
|
131 |
|
|
contr_o : out std_logic_vector(7 downto 0)
|
132 |
|
|
);
|
133 |
|
|
end pci;
|
134 |
|
|
|
135 |
|
|
|
136 |
|
|
|
137 |
|
|
|
138 |
|
|
|
139 |
|
|
|
140 |
|
|
--architecture start ------------------------------------------------------------
|
141 |
|
|
architecture Behavioral of pci is
|
142 |
|
|
|
143 |
|
|
|
144 |
|
|
|
145 |
|
|
|
146 |
|
|
-- SOME CONSTANTS ---------------------------------------------------------------
|
147 |
|
|
CONSTANT DEVICE_ID : std_logic_vector := X"9500";
|
148 |
|
|
CONSTANT VENDOR_ID : std_logic_vector := X"11AA"; -- 160X11AA : std_logic_vector := actel,
|
149 |
|
|
CONSTANT DEVICE_CLASS : std_logic_vector := X"118000"; -- some examples: 068000=bridge/other, 078000=simple_comm_contr/other, 118000=data_acquisition/other
|
150 |
|
|
CONSTANT DEVICE_REV : std_logic_vector := X"01";
|
151 |
|
|
CONSTANT SUBSYSTEM_ID : std_logic_vector := X"0001"; -- Card identifier
|
152 |
|
|
CONSTANT SUBSYSTEM_VENDOR_ID : std_logic_vector := X"13C7"; -- 13C7 : std_logic_vector := bluechip technology
|
153 |
|
|
CONSTANT DEVSEL_TIMING : std_logic_vector := "00"; -- Fast!
|
154 |
|
|
CONSTANT ST_IDLE : std_logic_vector := "000";
|
155 |
|
|
CONSTANT ST_BUSY : std_logic_vector := "010";
|
156 |
|
|
CONSTANT ST_MEMREAD : std_logic_vector := "100";
|
157 |
|
|
CONSTANT ST_MEMWRITE : std_logic_vector := "101";
|
158 |
|
|
CONSTANT ST_CFGREAD : std_logic_vector := "110";
|
159 |
|
|
CONSTANT ST_CFGWRITE : std_logic_vector := "111";
|
160 |
|
|
CONSTANT ST_HOLD : std_logic_vector := "001";
|
161 |
|
|
CONSTANT MEMREAD : std_logic_vector := "0110"; --cbe
|
162 |
|
|
CONSTANT MEMWRITE : std_logic_vector := "0111"; --cbe
|
163 |
|
|
CONSTANT CFGREAD : std_logic_vector := "1010"; --cbe
|
164 |
|
|
CONSTANT CFGWRITE : std_logic_vector := "1011"; --cbe
|
165 |
|
|
CONSTANT WB_BASEADDRESS : std_logic_vector := "00000000000000000000000000000000";
|
166 |
|
|
CONSTANT INT_PIN_INFO : std_logic_vector := "00000001"; --which interrupt signal is connected on the PCB? 0=none, 1=INTA, 2=INTB, 3=INTC, 4=INTD
|
167 |
|
|
|
168 |
|
|
|
169 |
|
|
|
170 |
|
|
|
171 |
|
|
|
172 |
|
|
-- INTERNAL SIGNALS -------------------------------------------------------------
|
173 |
|
|
SIGNAL wb0_state : std_logic_VECTOR(7 DOWNTO 0);
|
174 |
|
|
SIGNAL wb_transaction_complete : std_logic;
|
175 |
|
|
SIGNAL start_read_wb0 : std_logic;
|
176 |
|
|
SIGNAL start_write_wb0 : std_logic;
|
177 |
|
|
SIGNAL wb_address_feed : std_logic_VECTOR(31 DOWNTO 0);
|
178 |
|
|
SIGNAL wb_dat_o_feed : std_logic_VECTOR(31 DOWNTO 0);
|
179 |
|
|
SIGNAL wb_dat_i_latched : std_logic_VECTOR(31 DOWNTO 0);
|
180 |
|
|
SIGNAL wb_sel_o_feed : std_logic_VECTOR(3 DOWNTO 0);
|
181 |
|
|
|
182 |
|
|
SIGNAL pci_state : std_logic_VECTOR(2 DOWNTO 0);
|
183 |
|
|
SIGNAL second_clock_pci : std_logic;
|
184 |
|
|
SIGNAL assert_stop : std_logic;
|
185 |
|
|
SIGNAL data : std_logic_VECTOR(31 DOWNTO 0);
|
186 |
|
|
SIGNAL wr_data_pci : std_logic_VECTOR(31 DOWNTO 0);
|
187 |
|
|
SIGNAL ad_latched : std_logic_VECTOR(31 DOWNTO 0);
|
188 |
|
|
SIGNAL cbe_latched : std_logic_VECTOR(3 DOWNTO 0);
|
189 |
|
|
SIGNAL frame_latched : std_logic;
|
190 |
|
|
SIGNAL irdy_latched : std_logic;
|
191 |
|
|
SIGNAL idsel_latched : std_logic;
|
192 |
|
|
SIGNAL cbe_latched2 : std_logic_VECTOR(3 DOWNTO 0);
|
193 |
|
|
SIGNAL frame_latched2 : std_logic;
|
194 |
|
|
|
195 |
|
|
SIGNAL pci_address : std_logic_VECTOR(31 DOWNTO 0);
|
196 |
|
|
SIGNAL pci_address_previous : std_logic_VECTOR(31 DOWNTO 0);
|
197 |
|
|
SIGNAL pci_address_readonly : std_logic_VECTOR(31 DOWNTO 0);
|
198 |
|
|
SIGNAL hit : std_logic;
|
199 |
|
|
SIGNAL int_stat : std_logic;
|
200 |
|
|
SIGNAL addr_hit : std_logic;
|
201 |
|
|
SIGNAL cfg_hit : std_logic;
|
202 |
|
|
SIGNAL baseaddr : std_logic_VECTOR(7 DOWNTO 0);
|
203 |
|
|
SIGNAL int_line : std_logic_VECTOR(7 DOWNTO 0);
|
204 |
|
|
SIGNAL int_dis : std_logic;
|
205 |
|
|
SIGNAL data_par : std_logic;
|
206 |
|
|
SIGNAL memen : std_logic;
|
207 |
|
|
SIGNAL dummyreg32 : std_logic_VECTOR(31 DOWNTO 0);
|
208 |
|
|
|
209 |
|
|
|
210 |
|
|
|
211 |
|
|
|
212 |
|
|
|
213 |
|
|
--------- COMPONENT DECLARATIONS (introducing the IPs) --------------------------
|
214 |
|
|
--none
|
215 |
|
|
|
216 |
|
|
|
217 |
|
|
--architecture body start -------------------------------------------------------
|
218 |
|
|
begin
|
219 |
|
|
|
220 |
|
|
|
221 |
|
|
|
222 |
|
|
--------- COMPONENT INSTALLATIONS (connecting the IPs to local signals) ---------
|
223 |
|
|
--none
|
224 |
|
|
|
225 |
|
|
|
226 |
|
|
-- local Logic ------------------------------------------------------------------
|
227 |
|
|
|
228 |
|
|
led_out <= "0000";
|
229 |
|
|
contr_o <= "00000000";
|
230 |
|
|
|
231 |
|
|
|
232 |
|
|
|
233 |
|
|
|
234 |
|
|
-- ************** WISBONE BACK-end INTERFACE ****************************
|
235 |
|
|
-- **********************************************************************
|
236 |
|
|
|
237 |
|
|
--main state machine: set states, capture inputs, set addr/data outputs
|
238 |
|
|
--minimum 2 clock cycles / transaction. writes are posted, reads have wait states.
|
239 |
|
|
process (reset, pciclk, wb0_state, start_read_wb0, start_write_wb0,
|
240 |
|
|
wb_address_feed, wb_dat_o_feed, wb_sel_o_feed)
|
241 |
|
|
begin
|
242 |
|
|
if (reset='0') then
|
243 |
|
|
wb0_state <= "00000000";
|
244 |
|
|
wb_transaction_complete <= '0';
|
245 |
|
|
wb_address <= "00000000000000000000000000000000";
|
246 |
|
|
wb_sel_o <= "0000";
|
247 |
|
|
wb_dat_o <= "00000000000000000000000000000000";
|
248 |
|
|
wb_transaction_complete <='0';
|
249 |
|
|
wb_dat_i_latched <= "00000000000000000000000000000000";
|
250 |
|
|
else
|
251 |
|
|
if (pciclk'event and pciclk = '1') then
|
252 |
|
|
case ( wb0_state ) is
|
253 |
|
|
|
254 |
|
|
--********** IDLE STATE **********
|
255 |
|
|
when "00000000" => --state 0
|
256 |
|
|
wb_transaction_complete <='0';
|
257 |
|
|
wb_sel_o <= wb_sel_o_feed;
|
258 |
|
|
wb_address <= wb_address_feed;
|
259 |
|
|
if (start_read_wb0 ='1') then --go to read
|
260 |
|
|
wb0_state <= "00000001";
|
261 |
|
|
elsif (start_write_wb0 ='1') then --go to write
|
262 |
|
|
wb0_state <= "00000010";
|
263 |
|
|
wb_dat_o <= wb_dat_o_feed;
|
264 |
|
|
end if;
|
265 |
|
|
|
266 |
|
|
--********** READ STATE **********
|
267 |
|
|
--set the outputs,
|
268 |
|
|
--if ACK asserted, sample the data input
|
269 |
|
|
--The hold requirements are oversatisfyed by going back to idle, and by the fact that the slave uses the cyc/stb/wr strobes synchronously.
|
270 |
|
|
when "00000001" => --state 1
|
271 |
|
|
if (wb_ack_i='1') then
|
272 |
|
|
wb_dat_i_latched <= wb_dat_i; --sample the incoming data
|
273 |
|
|
wb_transaction_complete <='1'; --signalling ready, but only for one clock cycle
|
274 |
|
|
wb0_state <= "00000000"; --go to state 0
|
275 |
|
|
else
|
276 |
|
|
wb_transaction_complete <='0';
|
277 |
|
|
end if;
|
278 |
|
|
|
279 |
|
|
--********** WRITE STATE **********
|
280 |
|
|
--if ACK asserted, go back to idle
|
281 |
|
|
--The hold requirements are oversatisfyed by waiting for ACK to remove write data
|
282 |
|
|
when "00000010" => --state 2
|
283 |
|
|
if (wb_ack_i='1') then
|
284 |
|
|
wb0_state <= "00000000"; --go to state 0
|
285 |
|
|
wb_transaction_complete <='1';
|
286 |
|
|
else
|
287 |
|
|
wb_transaction_complete <='0';
|
288 |
|
|
end if;
|
289 |
|
|
|
290 |
|
|
when others => --error
|
291 |
|
|
wb0_state <= "00000000"; --go to state 0
|
292 |
|
|
end case;
|
293 |
|
|
end if;
|
294 |
|
|
end if;
|
295 |
|
|
end process;
|
296 |
|
|
--sync control on wb-control signals:
|
297 |
|
|
process (reset, wb0_state)
|
298 |
|
|
begin
|
299 |
|
|
if (reset='0') then
|
300 |
|
|
wb_cyc_o <= '0';
|
301 |
|
|
wb_stb_o <= '0';
|
302 |
|
|
wb_wr_o <= '0';
|
303 |
|
|
else
|
304 |
|
|
if (wb0_state = "00000000") then --idle
|
305 |
|
|
wb_cyc_o <= '0';
|
306 |
|
|
wb_stb_o <= '0';
|
307 |
|
|
wb_wr_o <= '0';
|
308 |
|
|
elsif (wb0_state = "00000001") then --read
|
309 |
|
|
wb_cyc_o <= '1';
|
310 |
|
|
wb_stb_o <= '1';
|
311 |
|
|
wb_wr_o <= '0';
|
312 |
|
|
elsif (wb0_state = "00000010") then --write
|
313 |
|
|
wb_cyc_o <= '1';
|
314 |
|
|
wb_stb_o <= '1';
|
315 |
|
|
wb_wr_o <= '1';
|
316 |
|
|
else
|
317 |
|
|
wb_cyc_o <= '0';
|
318 |
|
|
wb_stb_o <= '0';
|
319 |
|
|
wb_wr_o <= '0';
|
320 |
|
|
end if;
|
321 |
|
|
end if;
|
322 |
|
|
end process;
|
323 |
|
|
|
324 |
|
|
wb_reset_o <= not reset;
|
325 |
|
|
wb_clk_o <= pciclk;
|
326 |
|
|
wb_sel_o_feed <= "1111"; --only 32bit accesses are supported
|
327 |
|
|
|
328 |
|
|
|
329 |
|
|
|
330 |
|
|
-- wishbone arbitration:
|
331 |
|
|
--not supported at the moment:
|
332 |
|
|
wb_req <= '1';
|
333 |
|
|
-- xx <- wb_req_other, wb_gnt
|
334 |
|
|
|
335 |
|
|
|
336 |
|
|
|
337 |
|
|
|
338 |
|
|
|
339 |
|
|
|
340 |
|
|
|
341 |
|
|
|
342 |
|
|
|
343 |
|
|
|
344 |
|
|
|
345 |
|
|
|
346 |
|
|
-- ************** THE PCI I/O STATEMACHINE ******************************
|
347 |
|
|
-- **********************************************************************
|
348 |
|
|
process (reset, pciclk)
|
349 |
|
|
begin
|
350 |
|
|
if (reset='0') then
|
351 |
|
|
trdy <= 'Z';
|
352 |
|
|
devsel <= 'Z';
|
353 |
|
|
ad <= "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
|
354 |
|
|
par <= 'Z';
|
355 |
|
|
stop <= 'Z';
|
356 |
|
|
start_read_wb0 <= '0';
|
357 |
|
|
start_write_wb0 <= '0';
|
358 |
|
|
wb_address_feed <= "11111111111111111111111111111111";
|
359 |
|
|
wb_dat_o_feed <= "11111111111111111111111111111111";
|
360 |
|
|
pci_state <= ST_IDLE;
|
361 |
|
|
ad_latched <= (others => '0');
|
362 |
|
|
cbe_latched <= "0000";
|
363 |
|
|
frame_latched <= '1';
|
364 |
|
|
irdy_latched <= '1';
|
365 |
|
|
idsel_latched <= '0';
|
366 |
|
|
second_clock_pci <= '0';
|
367 |
|
|
wr_data_pci <= (others => '0');
|
368 |
|
|
assert_stop <= '0';
|
369 |
|
|
dummyreg32 <= (others => '0');
|
370 |
|
|
baseaddr <= (others => '0');
|
371 |
|
|
int_line <= (others => '0');
|
372 |
|
|
int_dis <= '0';
|
373 |
|
|
memen <= '0';
|
374 |
|
|
pci_address <= (others => '0');
|
375 |
|
|
pci_address_previous <= (others => '1');
|
376 |
|
|
pci_address_readonly <= (others => '0');
|
377 |
|
|
data <= (others => '0');
|
378 |
|
|
cbe_latched2 <= "0000";
|
379 |
|
|
frame_latched2 <= '1';
|
380 |
|
|
else
|
381 |
|
|
if (pciclk'event and pciclk = '1') then
|
382 |
|
|
|
383 |
|
|
--latching some signals to break timing path:
|
384 |
|
|
ad_latched <= ad;
|
385 |
|
|
cbe_latched <= cbe;
|
386 |
|
|
frame_latched <= frame;
|
387 |
|
|
irdy_latched <= irdy;
|
388 |
|
|
idsel_latched <= idsel;
|
389 |
|
|
--again::
|
390 |
|
|
cbe_latched2 <= cbe_latched;
|
391 |
|
|
frame_latched2 <= frame_latched;
|
392 |
|
|
|
393 |
|
|
case ( pci_state ) is
|
394 |
|
|
|
395 |
|
|
--********** idle STATE **********
|
396 |
|
|
when ST_IDLE => --state 000
|
397 |
|
|
--pci signals:
|
398 |
|
|
trdy <= 'Z';
|
399 |
|
|
ad <= "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
|
400 |
|
|
par <= 'Z';
|
401 |
|
|
stop <= 'Z';
|
402 |
|
|
--logic:
|
403 |
|
|
--address handling/latching:
|
404 |
|
|
if (frame_latched = '0') then
|
405 |
|
|
pci_address <= ad_latched;
|
406 |
|
|
end if;
|
407 |
|
|
if (frame_latched2='0' and hit='1') then
|
408 |
|
|
--next state without decoding:
|
409 |
|
|
--pci_state(2) <= '1';
|
410 |
|
|
--pci_state(1) <= cbe_latched(3);
|
411 |
|
|
--pci_state(0) <= cbe_latched(0);
|
412 |
|
|
if (cbe_latched2 = MEMREAD) then
|
413 |
|
|
pci_state <= ST_MEMREAD ;
|
414 |
|
|
pci_address_readonly <= pci_address;
|
415 |
|
|
pci_address_previous <= pci_address_readonly;
|
416 |
|
|
elsif (cbe_latched2 = MEMWRITE) then
|
417 |
|
|
pci_state <= ST_MEMWRITE ;
|
418 |
|
|
elsif (cbe_latched2 = CFGREAD) then
|
419 |
|
|
pci_state <= ST_CFGREAD ;
|
420 |
|
|
elsif (cbe_latched2 = CFGWRITE) then
|
421 |
|
|
pci_state <= ST_CFGWRITE ;
|
422 |
|
|
end if;
|
423 |
|
|
devsel <= '0';
|
424 |
|
|
else
|
425 |
|
|
devsel <= 'Z';
|
426 |
|
|
end if;
|
427 |
|
|
start_read_wb0 <= '0';
|
428 |
|
|
start_write_wb0 <= '0';
|
429 |
|
|
assert_stop <= '0';
|
430 |
|
|
second_clock_pci <= '0';
|
431 |
|
|
|
432 |
|
|
--********** CFG Read STATE **********
|
433 |
|
|
when ST_CFGREAD => --state 110
|
434 |
|
|
second_clock_pci <= '1';
|
435 |
|
|
case (pci_address(7 downto 2)) is
|
436 |
|
|
when "000000" => --0
|
437 |
|
|
data (31 downto 16) <= DEVICE_ID;
|
438 |
|
|
data (15 downto 0) <= VENDOR_ID;
|
439 |
|
|
when "000001" => --1
|
440 |
|
|
data (31 downto 27) <= "00000";
|
441 |
|
|
data (26 downto 25 ) <= DEVSEL_TIMING;
|
442 |
|
|
data (24 downto 20) <= "00000";
|
443 |
|
|
data ( 19 ) <= int_stat;
|
444 |
|
|
data (18 downto 11) <= "00000000";
|
445 |
|
|
data ( 10 ) <= int_dis;
|
446 |
|
|
data (9 downto 2) <= "00000000";
|
447 |
|
|
data ( 1 ) <= memen;
|
448 |
|
|
data ( 0 ) <= '0';
|
449 |
|
|
when "000010" => --2
|
450 |
|
|
data (31 downto 8) <= DEVICE_CLASS;
|
451 |
|
|
data (7 downto 0) <= DEVICE_REV;
|
452 |
|
|
when "000100" => --4 (BAR0)
|
453 |
|
|
data (31 downto 24) <= baseaddr;
|
454 |
|
|
data (23 downto 0) <= (others => '0');
|
455 |
|
|
when "001011" => --11
|
456 |
|
|
data (31 downto 16) <= SUBSYSTEM_ID;
|
457 |
|
|
data (15 downto 0) <= SUBSYSTEM_VENDOR_ID;
|
458 |
|
|
when "001111" => --15
|
459 |
|
|
data (31 downto 16) <= (others => '0');
|
460 |
|
|
data (15 downto 8) <= INT_PIN_INFO;
|
461 |
|
|
data (7 downto 0) <= int_line;
|
462 |
|
|
--when "010000" => --16
|
463 |
|
|
--data ( downto ) <= ;
|
464 |
|
|
when others => --0
|
465 |
|
|
data <= "00000000000000000000000000000000";
|
466 |
|
|
end case;
|
467 |
|
|
--finishing off:
|
468 |
|
|
if (second_clock_pci='1' and irdy_latched='0') then
|
469 |
|
|
--pci signals:
|
470 |
|
|
trdy <= '0';
|
471 |
|
|
ad <= data;
|
472 |
|
|
par <= data_par;
|
473 |
|
|
pci_state <= ST_HOLD;
|
474 |
|
|
end if;
|
475 |
|
|
|
476 |
|
|
--********** CFG Write STATE **********
|
477 |
|
|
when ST_CFGWRITE => --state 111
|
478 |
|
|
if (second_clock_pci='0' and irdy_latched='0') then
|
479 |
|
|
wr_data_pci <= ad;
|
480 |
|
|
second_clock_pci <= '1';
|
481 |
|
|
end if;
|
482 |
|
|
--finishing off:
|
483 |
|
|
if (second_clock_pci='1') then
|
484 |
|
|
--pci signals:
|
485 |
|
|
devsel <= '1';
|
486 |
|
|
trdy <= '1';
|
487 |
|
|
stop <= '1';
|
488 |
|
|
pci_state <= ST_HOLD;
|
489 |
|
|
--set the appropriate register
|
490 |
|
|
case (pci_address(7 downto 2)) is
|
491 |
|
|
when "000001" => --1
|
492 |
|
|
int_dis <= wr_data_pci(10);
|
493 |
|
|
memen <= wr_data_pci(1);
|
494 |
|
|
when "000100" => --4 (BAR0)
|
495 |
|
|
baseaddr <= wr_data_pci(31 downto 24);
|
496 |
|
|
when "001111" => --15
|
497 |
|
|
int_line <= wr_data_pci(7 downto 0);
|
498 |
|
|
--when "010000" => --16
|
499 |
|
|
--data ( downto ) <= ;
|
500 |
|
|
when others => --0
|
501 |
|
|
dummyreg32 <= wr_data_pci;
|
502 |
|
|
end case;
|
503 |
|
|
elsif (irdy_latched='0') then --second_clock_pci='0'
|
504 |
|
|
trdy <= '0';
|
505 |
|
|
end if;
|
506 |
|
|
|
507 |
|
|
--********** Mem Read STATE **********
|
508 |
|
|
when ST_MEMREAD => --state 100
|
509 |
|
|
second_clock_pci <= '1';
|
510 |
|
|
--initialize wishbone read:
|
511 |
|
|
if (second_clock_pci='0' ) then
|
512 |
|
|
wb_address_feed(21 downto 0) <= pci_address (23 downto 2);
|
513 |
|
|
wb_address_feed(31 downto 22) <= (others => '0');
|
514 |
|
|
start_read_wb0 <= '1';
|
515 |
|
|
data <= wb_dat_i_latched;
|
516 |
|
|
else
|
517 |
|
|
start_read_wb0 <= '0';
|
518 |
|
|
end if;
|
519 |
|
|
if (pci_address_previous = pci_address_readonly) then
|
520 |
|
|
assert_stop <= '0';
|
521 |
|
|
else
|
522 |
|
|
assert_stop <= '1';
|
523 |
|
|
end if;
|
524 |
|
|
if (second_clock_pci='1' and irdy_latched='0') then
|
525 |
|
|
--pci signals:
|
526 |
|
|
ad <= data;
|
527 |
|
|
par <= data_par;
|
528 |
|
|
pci_state <= ST_HOLD;
|
529 |
|
|
if (assert_stop = '1') then --terminate with retry
|
530 |
|
|
stop <= '0';
|
531 |
|
|
trdy <= 'Z';
|
532 |
|
|
else --terminate with data
|
533 |
|
|
stop <= 'Z';
|
534 |
|
|
trdy <= '0';
|
535 |
|
|
pci_address_readonly <= (others => '1'); --so next time it will reqest a retry again
|
536 |
|
|
end if;
|
537 |
|
|
end if;
|
538 |
|
|
|
539 |
|
|
--********** Mem Write STATE **********
|
540 |
|
|
when ST_MEMWRITE => --state 101
|
541 |
|
|
if (second_clock_pci='0' and irdy_latched='0') then
|
542 |
|
|
wr_data_pci <= ad;
|
543 |
|
|
second_clock_pci <= '1';
|
544 |
|
|
end if;
|
545 |
|
|
--finishing off:
|
546 |
|
|
if (second_clock_pci='1') then
|
547 |
|
|
--pci signals:
|
548 |
|
|
devsel <= '1';
|
549 |
|
|
trdy <= '1';
|
550 |
|
|
stop <= '1';
|
551 |
|
|
pci_state <= ST_HOLD;
|
552 |
|
|
--set the awishbone bus to go
|
553 |
|
|
start_write_wb0 <= '1';
|
554 |
|
|
wb_address_feed(21 downto 0) <= pci_address (23 downto 2);
|
555 |
|
|
wb_address_feed(31 downto 22) <= (others => '0');
|
556 |
|
|
wb_dat_o_feed <= wr_data_pci;
|
557 |
|
|
elsif (irdy_latched='0') then --second_clock_pci='0'
|
558 |
|
|
trdy <= '0';
|
559 |
|
|
end if;
|
560 |
|
|
|
561 |
|
|
--********** busy STATE **********
|
562 |
|
|
--this is left over from the original PCI core
|
563 |
|
|
when ST_BUSY => --state 010
|
564 |
|
|
pci_state <= ST_IDLE; --go to state 0
|
565 |
|
|
|
566 |
|
|
--********** HOLD STATE **********
|
567 |
|
|
when ST_HOLD => --state 001
|
568 |
|
|
pci_state <= ST_IDLE; --go to state 0
|
569 |
|
|
trdy <= '1';
|
570 |
|
|
devsel <= '1';
|
571 |
|
|
stop <= '1';
|
572 |
|
|
start_write_wb0 <= '0';
|
573 |
|
|
|
574 |
|
|
when others => --error
|
575 |
|
|
pci_state <= ST_IDLE; --go to state 0
|
576 |
|
|
end case;
|
577 |
|
|
end if;
|
578 |
|
|
end if;
|
579 |
|
|
end process; --pci statemachine ends here
|
580 |
|
|
|
581 |
|
|
|
582 |
|
|
|
583 |
|
|
|
584 |
|
|
|
585 |
|
|
|
586 |
|
|
|
587 |
|
|
|
588 |
|
|
|
589 |
|
|
|
590 |
|
|
|
591 |
|
|
-- some PCI glue logic: -------------------------------------------------
|
592 |
|
|
|
593 |
|
|
--parity:
|
594 |
|
|
data_par <= (data(31) xor data(30) xor data(29) xor data(28)) xor
|
595 |
|
|
(data(27) xor data(26) xor data(25) xor data(24)) xor
|
596 |
|
|
(data(23) xor data(22) xor data(21) xor data(20)) xor
|
597 |
|
|
(data(19) xor data(18) xor data(17) xor data(16)) xor
|
598 |
|
|
(data(15) xor data(14) xor data(13) xor data(12)) xor
|
599 |
|
|
(data(11) xor data(10) xor data(9) xor data(8)) xor
|
600 |
|
|
(data(7) xor data(6) xor data(5) xor data(4)) xor
|
601 |
|
|
(cbe(3) xor cbe(2) xor cbe(1) xor cbe(0)) xor
|
602 |
|
|
(data(3) xor data(2) xor data(1) xor data(0)) ;
|
603 |
|
|
|
604 |
|
|
|
605 |
|
|
|
606 |
|
|
|
607 |
|
|
--these are not used:
|
608 |
|
|
serr <= 'Z';
|
609 |
|
|
perr <= 'Z';
|
610 |
|
|
|
611 |
|
|
|
612 |
|
|
|
613 |
|
|
--interrupt:
|
614 |
|
|
process ( reset, pciclk)
|
615 |
|
|
begin
|
616 |
|
|
if (reset='0') then
|
617 |
|
|
inta <= 'Z';
|
618 |
|
|
int_stat <= '0';
|
619 |
|
|
elsif (pciclk'event and pciclk='1') then
|
620 |
|
|
if (wb_irq = '1' and int_dis='0') then
|
621 |
|
|
inta <= '0';
|
622 |
|
|
else
|
623 |
|
|
inta <= 'Z';
|
624 |
|
|
end if;
|
625 |
|
|
int_stat <= wb_irq;
|
626 |
|
|
end if;
|
627 |
|
|
end process;
|
628 |
|
|
|
629 |
|
|
|
630 |
|
|
|
631 |
|
|
--address match detection logic:
|
632 |
|
|
process ( reset, pciclk )
|
633 |
|
|
begin
|
634 |
|
|
if (reset='0') then
|
635 |
|
|
cfg_hit <= '0';
|
636 |
|
|
addr_hit <= '0';
|
637 |
|
|
elsif (pciclk'event and pciclk='1') then
|
638 |
|
|
--config access:
|
639 |
|
|
if ((cbe_latched = CFGREAD or cbe_latched = CFGWRITE)
|
640 |
|
|
and idsel_latched='1'
|
641 |
|
|
and ad_latched(10 downto 8) = "000"
|
642 |
|
|
and ad_latched(1 downto 0) = "00") then
|
643 |
|
|
cfg_hit <= '1';
|
644 |
|
|
else
|
645 |
|
|
cfg_hit <= '0';
|
646 |
|
|
end if;
|
647 |
|
|
--memory access:
|
648 |
|
|
if ((cbe_latched = MEMREAD or cbe_latched = MEMWRITE)
|
649 |
|
|
and memen = '1'
|
650 |
|
|
and ad_latched(31 downto 24) = baseaddr) then
|
651 |
|
|
addr_hit <= '1';
|
652 |
|
|
else
|
653 |
|
|
addr_hit <= '0';
|
654 |
|
|
end if;
|
655 |
|
|
end if;
|
656 |
|
|
end process;
|
657 |
|
|
hit <= cfg_hit or addr_hit;
|
658 |
|
|
|
659 |
|
|
|
660 |
|
|
|
661 |
|
|
|
662 |
|
|
|
663 |
|
|
|
664 |
|
|
--end file ----------------------------------------------------------------------
|
665 |
|
|
end Behavioral;
|
666 |
|
|
|
667 |
|
|
|