1 |
145 |
lanttu |
-------------------------------------------------------------------------------
|
2 |
|
|
-- Title : N2H2 rx channel
|
3 |
|
|
-- Project :
|
4 |
|
|
-------------------------------------------------------------------------------
|
5 |
|
|
-- File : n2h2_rx_chan.vhd
|
6 |
|
|
-- Author : kulmala3
|
7 |
|
|
-- Created : 02.06.2005
|
8 |
|
|
-- Last update: 2011-04-06
|
9 |
|
|
-- Description: One channel for N2H2
|
10 |
|
|
-- supports 32 and 64b data widths only due to low cost implemementation :)
|
11 |
|
|
-------------------------------------------------------------------------------
|
12 |
|
|
-- Copyright (c) 2005
|
13 |
|
|
-------------------------------------------------------------------------------
|
14 |
|
|
-- Revisions :
|
15 |
|
|
-- Date Version Author Description
|
16 |
|
|
-- 02.06.2005 1.0 AK Created
|
17 |
|
|
-------------------------------------------------------------------------------
|
18 |
|
|
|
19 |
|
|
library ieee;
|
20 |
|
|
use ieee.std_logic_1164.all;
|
21 |
|
|
use ieee.std_logic_arith.all;
|
22 |
|
|
use ieee.std_logic_unsigned.all;
|
23 |
|
|
|
24 |
|
|
entity n2h2_rx_chan is
|
25 |
|
|
|
26 |
|
|
generic (
|
27 |
|
|
data_width_g : integer := 0;
|
28 |
|
|
hibi_addr_width_g : integer := 0;
|
29 |
|
|
addr_width_g : integer := 0;
|
30 |
|
|
amount_width_g : integer := 0;
|
31 |
|
|
addr_cmp_lo_g : integer := 0;
|
32 |
|
|
addr_cmp_hi_g : integer := 0
|
33 |
|
|
);
|
34 |
|
|
|
35 |
|
|
port (
|
36 |
|
|
clk : in std_logic;
|
37 |
|
|
rst_n : in std_logic;
|
38 |
|
|
|
39 |
|
|
-- keep still until a new init
|
40 |
|
|
avalon_addr_in : in std_logic_vector(addr_width_g-1 downto 0);
|
41 |
|
|
hibi_addr_in : in std_logic_vector(hibi_addr_width_g-1 downto 0);
|
42 |
|
|
irq_amount_in : in std_logic_vector(amount_width_g-1 downto 0);
|
43 |
|
|
|
44 |
|
|
hibi_data_in : in std_logic_vector(hibi_addr_width_g-1 downto 0);
|
45 |
|
|
hibi_av_in : in std_logic;
|
46 |
|
|
hibi_empty_in : in std_logic;
|
47 |
|
|
init_in : in std_logic;
|
48 |
|
|
irq_ack_in : in std_logic;
|
49 |
|
|
avalon_waitreq_in : in std_logic;
|
50 |
|
|
avalon_we_in : in std_logic;
|
51 |
|
|
|
52 |
|
|
avalon_addr_out : out std_logic_vector(addr_width_g-1 downto 0);
|
53 |
|
|
avalon_we_out : out std_logic;
|
54 |
|
|
avalon_be_out : out std_logic_vector(data_width_g/8-1 downto 0);
|
55 |
|
|
addr_match_out : out std_logic;
|
56 |
|
|
addr_match_cmb_out : out std_logic;
|
57 |
|
|
irq_out : out std_logic
|
58 |
|
|
);
|
59 |
|
|
|
60 |
|
|
end n2h2_rx_chan;
|
61 |
|
|
|
62 |
|
|
architecture rtl of n2h2_rx_chan is
|
63 |
|
|
constant dont_care_c : std_logic := 'X';
|
64 |
|
|
constant addr_offset_c : integer := data_width_g/8;
|
65 |
|
|
|
66 |
|
|
constant words_per_hibi_data_c : integer := data_width_g/32;
|
67 |
|
|
constant upper_valid_c : std_logic := '0'; -- in case of odd data amount, is
|
68 |
|
|
-- either uppoer ('1') or lower ('0') half-word valid?
|
69 |
|
|
constant be_width_c : integer := data_width_g/8;
|
70 |
|
|
signal addr_match_r : std_logic;
|
71 |
|
|
signal addr_match_cmb_s : std_logic;
|
72 |
|
|
signal avalon_addr_r : std_logic_vector(addr_width_g-1 downto 0);
|
73 |
|
|
signal enable_r : std_logic;
|
74 |
|
|
signal ena_av_empty : std_logic_vector(2 downto 0);
|
75 |
|
|
signal irq_counter_r : std_logic_vector(amount_width_g-1 downto 0);
|
76 |
|
|
signal irq_r : std_logic;
|
77 |
|
|
signal we_match_waitreq : std_logic_vector(2 downto 0);
|
78 |
|
|
|
79 |
|
|
|
80 |
|
|
begin -- rtl
|
81 |
|
|
|
82 |
|
|
we_match_waitreq <= avalon_we_in & addr_match_r & avalon_waitreq_in;
|
83 |
|
|
avalon_we_out <= addr_match_r and enable_r;
|
84 |
|
|
irq_out <= irq_r;
|
85 |
|
|
|
86 |
|
|
addr_match_out <= addr_match_r and enable_r;
|
87 |
|
|
addr_match_cmb_out <= addr_match_cmb_s;
|
88 |
|
|
avalon_addr_out <= avalon_addr_r;
|
89 |
|
|
|
90 |
|
|
ena_av_empty <= enable_r & hibi_av_in & hibi_empty_in;
|
91 |
|
|
|
92 |
|
|
addr_match : process (hibi_data_in, hibi_addr_in, addr_match_r, ena_av_empty)
|
93 |
|
|
begin -- process addr_match
|
94 |
|
|
|
95 |
|
|
case ena_av_empty is
|
96 |
|
|
when "000" | "010" | "011" | "001" =>
|
97 |
|
|
addr_match_cmb_s <= '0';
|
98 |
|
|
when "110" =>
|
99 |
|
|
if hibi_data_in(addr_cmp_hi_g downto addr_cmp_lo_g) =
|
100 |
|
|
hibi_addr_in(addr_cmp_hi_g downto addr_cmp_lo_g) then
|
101 |
|
|
addr_match_cmb_s <= '1';
|
102 |
|
|
else
|
103 |
|
|
addr_match_cmb_s <= '0';
|
104 |
|
|
end if;
|
105 |
|
|
when others =>
|
106 |
|
|
addr_match_cmb_s <= addr_match_r;
|
107 |
|
|
end case;
|
108 |
|
|
|
109 |
|
|
end process addr_match;
|
110 |
|
|
|
111 |
|
|
addr_match_reg : process (clk, rst_n)
|
112 |
|
|
begin -- process addr_matching
|
113 |
|
|
if rst_n = '0' then -- asynchronous reset (active low)
|
114 |
|
|
addr_match_r <= '0';
|
115 |
|
|
elsif clk'event and clk = '1' then -- rising clock edge
|
116 |
|
|
|
117 |
|
|
addr_match_r <= addr_match_cmb_s;
|
118 |
|
|
|
119 |
|
|
end if;
|
120 |
|
|
end process addr_match_reg;
|
121 |
|
|
|
122 |
|
|
|
123 |
|
|
ena : process (clk, rst_n)
|
124 |
|
|
variable inter_addr : std_logic_vector(addr_width_g-1 downto 0);
|
125 |
|
|
begin -- process ena
|
126 |
|
|
if rst_n = '0' then -- asynchronous reset (active low)
|
127 |
|
|
enable_r <= '0';
|
128 |
|
|
irq_counter_r <= (others => '1');
|
129 |
|
|
avalon_addr_r <= (others => dont_care_c);
|
130 |
|
|
irq_r <= '0';
|
131 |
|
|
|
132 |
|
|
elsif clk'event and clk = '1' then -- rising clock edge
|
133 |
|
|
|
134 |
|
|
if init_in = '1' then
|
135 |
|
|
enable_r <= '1';
|
136 |
|
|
irq_counter_r <= irq_amount_in;
|
137 |
|
|
avalon_addr_r <= avalon_addr_in;
|
138 |
|
|
else
|
139 |
|
|
enable_r <= enable_r;
|
140 |
|
|
irq_counter_r <= irq_counter_r;
|
141 |
|
|
avalon_addr_r <= avalon_addr_r;
|
142 |
|
|
end if;
|
143 |
|
|
|
144 |
|
|
if irq_ack_in = '1' then
|
145 |
|
|
irq_r <= '0';
|
146 |
|
|
else
|
147 |
|
|
irq_r <= irq_r;
|
148 |
|
|
end if;
|
149 |
|
|
|
150 |
|
|
case we_match_waitreq is
|
151 |
|
|
when "110" =>
|
152 |
|
|
-- we're writing here
|
153 |
|
|
if irq_counter_r <= conv_std_logic_vector(words_per_hibi_data_c, amount_width_g) then
|
154 |
|
|
avalon_addr_r <= avalon_addr_r+addr_offset_c; -- what if not increased?
|
155 |
|
|
enable_r <= '0';
|
156 |
|
|
irq_r <= '1';
|
157 |
|
|
irq_counter_r <= irq_counter_r;
|
158 |
|
|
else
|
159 |
|
|
avalon_addr_r <= avalon_addr_r +addr_offset_c;
|
160 |
|
|
irq_counter_r <= irq_counter_r-words_per_hibi_data_c;
|
161 |
|
|
enable_r <= '1';
|
162 |
|
|
-- irq_r <= '0'; --already assigned earlier
|
163 |
|
|
end if;
|
164 |
|
|
|
165 |
|
|
when others =>
|
166 |
|
|
-- irq_counter_r <= irq_counter_r;
|
167 |
|
|
-- enable_r <= enable_r;
|
168 |
|
|
-- irq_r <= '0';
|
169 |
|
|
end case;
|
170 |
|
|
|
171 |
|
|
-- purpose: sets the avalon byteenable signal
|
172 |
|
|
|
173 |
|
|
|
174 |
|
|
end if;
|
175 |
|
|
end process ena;
|
176 |
|
|
|
177 |
|
|
byteena : process (irq_counter_r)
|
178 |
|
|
begin -- process byteena
|
179 |
|
|
if irq_counter_r = conv_std_logic_vector(1, amount_width_g) and words_per_hibi_data_c = 2 then
|
180 |
|
|
-- odd number of words wanted, e.g. 64 bit hibi, wanted 5 32-bit
|
181 |
|
|
-- words
|
182 |
|
|
avalon_be_out(be_width_c-1 downto be_width_c/2) <= (others => upper_valid_c);
|
183 |
|
|
avalon_be_out(be_width_c/2-1 downto 0) <= (others => (not upper_valid_c));
|
184 |
|
|
else
|
185 |
|
|
avalon_be_out <= (others => '1');
|
186 |
|
|
end if;
|
187 |
|
|
|
188 |
|
|
end process byteena;
|
189 |
|
|
|
190 |
|
|
|
191 |
|
|
|
192 |
|
|
end rtl;
|