This repository has been archived by the owner on Apr 16, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
axihp_writer.vhd
307 lines (244 loc) · 9.65 KB
/
axihp_writer.vhd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
----------------------------------------------------------------------------
-- axihp_writer.vhd
-- AXIHP Writer (Async, In Flight)
-- Version 1.5
--
-- Copyright (C) 2013 H.Poetzl
--
-- This program is free software: you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- as published by the Free Software Foundation, either version
-- 2 of the License, or (at your option) any later version.
----------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.ALL;
use IEEE.numeric_std.ALL;
library unisim;
use unisim.VCOMPONENTS.all;
entity axihp_writer is
generic (
DATA_WIDTH : natural := 64;
DATA_COUNT : natural := 16;
-- ADDR_MASK : std_logic_vector (31 downto 0) := x"00FFFFFF";
-- ADDR_DATA : std_logic_vector (31 downto 0) := x"1B000000";
ADDR_MAX : std_logic_vector (31 downto 0) := x"1A000000" );
port (
m_axi_aclk : in std_logic;
m_axi_areset_n : in std_logic;
enable : in std_logic;
inactive : out std_logic;
--
-- unfornunately this is not supported by vivado block designs, we need to
-- break out these signals
-- m_axi_wo : out axi3s_write_in_r;
-- write address
m_axi_wo_awid : out std_logic_vector (2 downto 0);
m_axi_wo_awaddr : out std_logic_vector (31 downto 0);
m_axi_wo_awburst : out std_logic_vector (1 downto 0);
m_axi_wo_awlen : out std_logic_vector (3 downto 0);
m_axi_wo_awsize : out std_logic_vector (2 downto 0);
m_axi_wo_awprot : out std_logic_vector (2 downto 0);
m_axi_wo_awvalid : out std_ulogic;
m_axi_wo_awcache : out std_logic_vector(3 downto 0);
-- write data
m_axi_wo_wid : out std_logic_vector (2 downto 0);
m_axi_wo_wdata : out std_logic_vector (63 downto 0);
m_axi_wo_wstrb : out std_logic_vector (7 downto 0);
m_axi_wo_wlast : out std_ulogic;
m_axi_wo_wvalid : out std_ulogic;
-- write response
m_axi_wo_bready : out std_ulogic;
-- m_axi_wi : in axi3s_write_out_r;
-- write address
m_axi_wi_awready : in std_ulogic;
m_axi_wi_wacount : in std_logic_vector (5 downto 0);
-- write data
m_axi_wi_wready : in std_ulogic;
m_axi_wi_wcount : in std_logic_vector (7 downto 0);
-- write response
m_axi_wi_bid : in std_logic_vector (5 downto 0);
m_axi_wi_bresp : in std_logic_vector (1 downto 0);
m_axi_wi_bvalid : in std_ulogic;
--
addr_clk : out std_logic;
addr_enable : out std_logic;
addr_in : in std_logic_vector (31 downto 0);
addr_empty : in std_logic;
--
data_clk : out std_logic;
data_enable : out std_logic;
data_in : in std_logic_vector (DATA_WIDTH - 1 downto 0);
data_empty : in std_logic;
--
write_strobe : in std_logic_vector (7 downto 0);
--
writer_error : out std_logic;
writer_active : out std_logic_vector (3 downto 0);
writer_unconf : out std_logic_vector (3 downto 0) );
end entity axihp_writer;
architecture RTL of axihp_writer is
ATTRIBUTE KEEP_HIERARCHY : STRING;
attribute KEEP_HIERARCHY of RTL : architecture is "TRUE";
constant awlen_c : std_logic_vector (3 downto 0)
:= std_logic_vector (to_unsigned(DATA_COUNT - 1, 4));
signal active : unsigned(3 downto 0) := x"0";
signal unconf : unsigned(3 downto 0) := x"0";
signal awvalid : std_logic := '0';
signal wvalid : std_logic := '0';
signal wlast : std_logic;
signal bready : std_logic := '0';
signal data_en : std_logic;
signal addr_en : std_logic;
signal resp_en : std_logic;
ATTRIBUTE X_INTERFACE_INFO : STRING;
ATTRIBUTE X_INTERFACE_INFO of m_axi_wo_awid: SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI AWID";
ATTRIBUTE X_INTERFACE_INFO of m_axi_wo_awaddr: SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI AWADDR";
ATTRIBUTE X_INTERFACE_INFO of m_axi_wo_awlen: SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI AWLEN";
ATTRIBUTE X_INTERFACE_INFO of m_axi_wo_awsize: SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI AWSIZE";
ATTRIBUTE X_INTERFACE_INFO of m_axi_wo_awburst: SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI AWBURST";
ATTRIBUTE X_INTERFACE_INFO of m_axi_wo_awprot: SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI AWPROT";
ATTRIBUTE X_INTERFACE_INFO of m_axi_wo_awvalid: SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI AWVALID";
ATTRIBUTE X_INTERFACE_INFO of m_axi_wo_wid: SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI WID";
ATTRIBUTE X_INTERFACE_INFO of m_axi_wo_wdata: SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI WDATA";
ATTRIBUTE X_INTERFACE_INFO of m_axi_wo_wstrb: SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI WSTRB";
ATTRIBUTE X_INTERFACE_INFO of m_axi_wo_wlast: SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI WLAST";
ATTRIBUTE X_INTERFACE_INFO of m_axi_wo_wvalid: SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI WVALID";
ATTRIBUTE X_INTERFACE_INFO of m_axi_wo_bready: SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI BREADY";
ATTRIBUTE X_INTERFACE_INFO of m_axi_wo_awcache: SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI AWCACHE";
ATTRIBUTE X_INTERFACE_INFO of m_axi_wi_wready: SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI WREADY";
ATTRIBUTE X_INTERFACE_INFO of m_axi_wi_bid: SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI BID";
ATTRIBUTE X_INTERFACE_INFO of m_axi_wi_bresp: SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI BRESP";
ATTRIBUTE X_INTERFACE_INFO of m_axi_wi_bvalid: SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI BVALID";
ATTRIBUTE X_INTERFACE_INFO of m_axi_wi_awready: SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI AWREADY";
begin
--------------------------------------------------------------------
-- Address Pipeline
--------------------------------------------------------------------
addr_en <= awvalid and m_axi_wi_awready;
addr_proc : process (m_axi_aclk, m_axi_wi_awready, m_axi_wi_wacount, m_axi_wi_wready, m_axi_wi_wcount, m_axi_wi_bid, m_axi_wi_bresp, m_axi_wi_bvalid)
begin
if rising_edge(m_axi_aclk) then
if m_axi_areset_n = '0' then -- reset
awvalid <= '0';
elsif awvalid = '0' then -- idle phase
if enable = '1' and -- writer enabled
addr_empty = '0' and -- address available
active(3) = '0' then -- below max
awvalid <= '1';
end if;
end if;
if awvalid = '1' then -- active phase
if m_axi_wi_awready = '1' then
awvalid <= '0';
end if;
end if;
end if;
end process;
m_axi_wo_awaddr <= addr_in when addr_in < ADDR_MAX else ADDR_MAX;
m_axi_wo_awvalid <= awvalid;
addr_enable <= addr_en;
--------------------------------------------------------------------
-- Data Pipeline
--------------------------------------------------------------------
SRL16E_inst : SRL16E
generic map (
INIT => x"0001")
port map (
CLK => m_axi_aclk, -- Clock input
CE => data_en, -- Clock enable input
D => wlast, -- SRL data input
Q => wlast, -- SRL data output
A0 => awlen_c(0), -- Select[0] input
A1 => awlen_c(1), -- Select[1] input
A2 => awlen_c(2), -- Select[2] input
A3 => awlen_c(3) ); -- Select[3] input
data_en <= wvalid and m_axi_wi_wready;
write_proc : process (m_axi_aclk, m_axi_wi_awready, m_axi_wi_wacount, m_axi_wi_wready, m_axi_wi_wcount, m_axi_wi_bid, m_axi_wi_bresp, m_axi_wi_bvalid)
begin
if rising_edge(m_axi_aclk) then
if m_axi_areset_n = '0' then -- reset
wvalid <= '0';
elsif wvalid = '0' then -- idle phase
if data_empty = '0' and -- fifo not empty
active /= x"0" then -- inactive
wvalid <= '1';
end if;
else -- active phase
if wlast = '1' then
wvalid <= '0';
end if;
end if;
end if;
end process;
m_axi_wo_wdata(DATA_WIDTH - 1 downto 0) <= data_in;
m_axi_wo_wvalid <= wvalid;
m_axi_wo_wlast <= wlast;
data_enable <= data_en;
--------------------------------------------------------------------
-- Response Pipeline
--------------------------------------------------------------------
resp_en <= bready and m_axi_wi_bvalid;
bresp_proc : process (m_axi_aclk)
begin
if rising_edge(m_axi_aclk) then
if m_axi_areset_n = '0' then -- reset
bready <= '0';
elsif bready = '0' then -- idle phase
if enable = '1' then -- writer enabled
bready <= '1';
end if;
else -- active phase
if unconf = x"0" then -- all done
bready <= '0';
end if;
end if;
end if;
end process;
m_axi_wo_bready <= bready;
writer_error <= '1' when
resp_en = '1' and m_axi_wi_bresp /= "00" else '0';
--------------------------------------------------------------------
-- In Flight Accounting
--------------------------------------------------------------------
active_proc : process (m_axi_aclk)
begin
if rising_edge(m_axi_aclk) then
if addr_en = '1' and
wlast = '0' then -- one more
active <= active + "1";
elsif addr_en = '0' and
wlast = '1' then -- one less
active <= active - "1";
end if;
end if;
end process;
unconf_proc : process (m_axi_aclk)
begin
if rising_edge(m_axi_aclk) then
if addr_en = '1' and
resp_en = '0' then -- one more
unconf <= unconf + "1";
elsif addr_en = '0' and
resp_en = '1' then -- one less
unconf <= unconf - "1";
end if;
end if;
end process;
inactive <= '1' when active = x"0"
and unconf = x"0" else '0';
--------------------------------------------------------------------
-- Constant Values, Clocks
--------------------------------------------------------------------
m_axi_wo_awid <= (others => '0');
m_axi_wo_wid <= (others => '0');
m_axi_wo_awlen <= awlen_c;
m_axi_wo_awburst <= "01";
-- 11 for 8 bytes
-- 10 for 4 bytes
m_axi_wo_awsize <= "011";
m_axi_wo_wstrb <= write_strobe;
m_axi_wo_awprot <= "000";
m_axi_wo_awcache <= "0011";
data_clk <= m_axi_aclk;
addr_clk <= m_axi_aclk;
end RTL;