1 |
9 |
nuubik |
library ieee;
|
2 |
|
|
use ieee.std_logic_1164.all;
|
3 |
|
|
use IEEE.std_logic_unsigned.all;
|
4 |
|
|
use IEEE.std_logic_arith.all;
|
5 |
|
|
|
6 |
|
|
entity serirq is
|
7 |
|
|
port (
|
8 |
|
|
clock : in std_logic;
|
9 |
|
|
reset_n : in std_logic;
|
10 |
|
|
slot_sel : in std_logic_vector(4 downto 0); --clk no of IRQ defined in Ser irq for PCI systems spec.
|
11 |
|
|
serirq : inout std_logic;
|
12 |
|
|
irq : in std_logic
|
13 |
|
|
);
|
14 |
|
|
end entity serirq;
|
15 |
|
|
|
16 |
|
|
architecture RTL of serirq is
|
17 |
|
|
|
18 |
|
|
type reg_type is
|
19 |
|
|
record
|
20 |
|
|
irq_idle : boolean; --idle mode only host can start irq cycles quiet mode is entered by 2 clock stop, 3 clock stop keeps or enters idle mode
|
21 |
|
|
irq_frame : boolean; --currently in running irq frame
|
22 |
|
|
serirq_oe : std_logic; --oe does pulldown
|
23 |
|
|
low_count : std_logic_vector(3 downto 0);
|
24 |
|
|
slot_count : std_logic_vector(7 downto 0);
|
25 |
|
|
irq_count : std_logic_vector(3 downto 0); --wait before irq auto issue
|
26 |
|
|
|
27 |
|
|
irq_sync : std_logic; --sync stage
|
28 |
|
|
end record;
|
29 |
|
|
|
30 |
|
|
signal reg, reg_in : reg_type;
|
31 |
|
|
signal comb_oe : std_logic;
|
32 |
|
|
|
33 |
|
|
|
34 |
|
|
begin
|
35 |
|
|
|
36 |
|
|
serirq<='0' when comb_oe='1' else
|
37 |
|
|
'Z';
|
38 |
|
|
|
39 |
|
|
|
40 |
|
|
-- Design pattern process 1 Implementation
|
41 |
|
|
comb : process (serirq,slot_sel,irq,reg)
|
42 |
|
|
variable reg_v : reg_type;
|
43 |
|
|
begin
|
44 |
|
|
-- Design pattern
|
45 |
|
|
reg_v:=reg; --pre set default var state
|
46 |
|
|
------------------------------------
|
47 |
|
|
--- <implementation> ---
|
48 |
|
|
------------------------------------
|
49 |
|
|
reg_v.irq_sync:=irq;
|
50 |
|
|
--clear signel cycle oe
|
51 |
|
|
reg_v.serirq_oe:='0'; --disable pulldown (this can never be longer than 1 cycle)
|
52 |
|
|
|
53 |
|
|
--Frame start contition wait
|
54 |
|
|
if reg_v.irq_idle and not reg_v.irq_frame then -- Idle mode wait for host to start
|
55 |
|
|
if serirq='0' then -- count low cycles
|
56 |
|
|
reg_v.low_count:=reg_v.low_count + 1;
|
57 |
|
|
else -- see if the event is a start frame event
|
58 |
|
|
if reg_v.low_count>"0011" then -- cycle start
|
59 |
|
|
reg_v.irq_frame:=true;
|
60 |
|
|
end if;
|
61 |
|
|
reg_v.low_count:=(others=>'0');
|
62 |
|
|
end if;
|
63 |
|
|
elsif not reg_v.irq_idle and not reg_v.irq_frame and reg.irq_sync='1' then -- in active mode we can start the irq frame
|
64 |
|
|
if reg_v.irq_count>"0010" then
|
65 |
|
|
reg_v.serirq_oe:='1'; --enable pulldonw
|
66 |
|
|
reg_v.irq_frame:=true; -- frame should start
|
67 |
|
|
else
|
68 |
|
|
reg_v.irq_count:=reg_v.irq_count + 1;
|
69 |
|
|
end if;
|
70 |
|
|
else -- in frame
|
71 |
|
|
reg_v.irq_count:=(others=>'0'); --
|
72 |
|
|
end if;
|
73 |
|
|
|
74 |
|
|
--In IRQ frame
|
75 |
|
|
if reg_v.irq_frame and reg_v.slot_count<x"FF" then --don't allow cnt overflow for slots
|
76 |
|
|
reg_v.slot_count:=reg_v.slot_count + 1;
|
77 |
|
|
else
|
78 |
|
|
reg_v.slot_count:=(others=>'0'); --reset when out of frame
|
79 |
|
|
end if;
|
80 |
|
|
|
81 |
|
|
--Slot sel must use register value as it is incremented above in the variable for next cycle
|
82 |
|
|
if reg_v.irq_frame and slot_sel/="00000" and reg.slot_count(7 downto 0)="000"&slot_sel and reg.irq_sync='1' then --when slot and irq active to pull on the serirq
|
83 |
|
|
reg_v.serirq_oe:='1'; --enable pulldonw
|
84 |
|
|
end if;
|
85 |
|
|
|
86 |
|
|
-- End irq frame and enter idle or active mode
|
87 |
|
|
if reg_v.irq_frame then
|
88 |
|
|
if serirq='0' then -- count low cycles
|
89 |
|
|
reg_v.low_count:=reg_v.low_count + 1;
|
90 |
|
|
else -- see type of stop frame frame event
|
91 |
|
|
if reg_v.low_count=x"2" then
|
92 |
|
|
reg_v.irq_frame:=false;
|
93 |
|
|
reg_v.irq_idle:=false; --enter active mode
|
94 |
|
|
elsif reg_v.low_count>x"2" then
|
95 |
|
|
reg_v.irq_idle:=true; --enter idle mode
|
96 |
|
|
reg_v.irq_frame:=false;
|
97 |
|
|
end if;
|
98 |
|
|
reg_v.low_count:=(others=>'0');
|
99 |
|
|
end if;
|
100 |
|
|
end if;
|
101 |
|
|
|
102 |
|
|
-- Design pattern
|
103 |
|
|
-- drive register input signals
|
104 |
|
|
reg_in<=reg_v;
|
105 |
|
|
-- drive module outputs signals
|
106 |
|
|
--port_comb_out<= reg_v.port_comb; --combinatorial output example
|
107 |
|
|
--port_reg_out<= reg.port_reg; --registered output example
|
108 |
|
|
comb_oe<=reg_v.serirq_oe; --cominatorial out
|
109 |
|
|
end process;
|
110 |
|
|
|
111 |
|
|
-- Pattern process 2, Registers
|
112 |
|
|
regs : process (clock,reset_n)
|
113 |
|
|
begin
|
114 |
|
|
if reset_n='0' then
|
115 |
|
|
reg.irq_idle<=true; -- start up in idle mode
|
116 |
|
|
reg.irq_frame<=false; --start up out of irq frame
|
117 |
|
|
reg.slot_count<=(others=>'0');
|
118 |
|
|
reg.low_count<=(others=>'0');
|
119 |
|
|
reg.irq_count<=(others=>'0');
|
120 |
|
|
reg.irq_sync<='0';
|
121 |
|
|
reg.serirq_oe<='0'; -- on reset all agents enter tristated mode
|
122 |
|
|
elsif rising_edge(clock) then
|
123 |
|
|
reg<=reg_in;
|
124 |
|
|
end if;
|
125 |
|
|
end process;
|
126 |
|
|
|
127 |
|
|
|
128 |
|
|
end architecture RTL;
|