Skip to content

Commit e01b930

Browse files
authored
Merge pull request #1339 from slaclab/pre-release
Release Candidate v2.65.0
2 parents 1fe2b35 + e7b23d6 commit e01b930

File tree

20 files changed

+1419
-100
lines changed

20 files changed

+1419
-100
lines changed
Lines changed: 290 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,290 @@
1+
-------------------------------------------------------------------------------
2+
-- Company : SLAC National Accelerator Laboratory
3+
-------------------------------------------------------------------------------
4+
-- Description:
5+
-- Block serves as an FIFO that buffers a user-selectable number of frames
6+
-- (defined by TLAST). Useful for benchmarking latency of IPs.
7+
-------------------------------------------------------------------------------
8+
-- This file is part of 'SLAC Firmware Standard Library'.
9+
-- It is subject to the license terms in the LICENSE.txt file found in the
10+
-- top-level directory of this distribution and at:
11+
-- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html.
12+
-- No part of 'SLAC Firmware Standard Library', including this file,
13+
-- may be copied, modified, propagated, or distributed except according to
14+
-- the terms contained in the LICENSE.txt file.
15+
-------------------------------------------------------------------------------
16+
17+
library ieee;
18+
use ieee.std_logic_1164.all;
19+
use ieee.std_logic_unsigned.all;
20+
use ieee.std_logic_arith.all;
21+
22+
library surf;
23+
use surf.StdRtlPkg.all;
24+
use surf.AxiStreamPkg.all;
25+
use surf.AxiLitePkg.all;
26+
27+
entity AxiStreamBatchingFifo is
28+
generic (
29+
-- General Configurations
30+
TPD_G : time := 1 ns;
31+
FIFO_ADDR_WIDTH_G : integer range 4 to 48 := 9;
32+
-- AXI Stream Port Configurations
33+
SLAVE_AXI_CONFIG_G : AxiStreamConfigType;
34+
MASTER_AXI_CONFIG_G : AxiStreamConfigType);
35+
port (
36+
-- Control Port
37+
axilClk : in sl;
38+
axilRst : in sl;
39+
sAxilWriteMaster : in AxiLiteWriteMasterType;
40+
sAxilWriteSlave : out AxiLiteWriteSlaveType;
41+
sAxilReadMaster : in AxiLiteReadMasterType;
42+
sAxilReadSlave : out AxiLiteReadSlaveType;
43+
44+
-- Slave Port
45+
sAxisClk : in sl;
46+
sAxisRst : in sl;
47+
sAxisMaster : in AxiStreamMasterType;
48+
sAxisSlave : out AxiStreamSlaveType;
49+
50+
-- Master Port
51+
mAxisClk : in sl;
52+
mAxisRst : in sl;
53+
mAxisMaster : out AxiStreamMasterType;
54+
mAxisSlave : in AxiStreamSlaveType);
55+
end AxiStreamBatchingFifo;
56+
57+
architecture rtl of AxiStreamBatchingFifo is
58+
59+
signal batchSizeAxiL : slv(31 downto 0);
60+
signal batchSize : slv(31 downto 0);
61+
62+
signal axisMasterSync : AxiStreamMasterType;
63+
signal axisSlaveSync : AxiStreamSlaveType;
64+
65+
signal axisMasterFifo : AxiStreamMasterType;
66+
signal axisSlaveFifo : AxiStreamSlaveType;
67+
68+
type RegType is record
69+
frameBatched : slv(31 downto 0);
70+
frameToSend : slv(31 downto 0);
71+
sending : sl;
72+
end record;
73+
74+
constant REG_INIT_C : RegType := (
75+
frameBatched => (others => '0'),
76+
frameToSend => (others => '0'),
77+
sending => '0'
78+
);
79+
80+
signal r : RegType := REG_INIT_C;
81+
signal rin : RegType;
82+
83+
signal rAxilWriteSlave : AxiLiteWriteSlaveType := AXI_LITE_WRITE_SLAVE_INIT_C;
84+
signal rAxilReadSlave : AxiLiteReadSlaveType := AXI_LITE_READ_SLAVE_INIT_C;
85+
signal rinAxilWriteSlave : AxiLiteWriteSlaveType := AXI_LITE_WRITE_SLAVE_INIT_C;
86+
signal rinAxilReadSlave : AxiLiteReadSlaveType := AXI_LITE_READ_SLAVE_INIT_C;
87+
88+
signal combAxisMaster : AxiStreamMasterType;
89+
signal combAxisSlave : AxiStreamSlaveType;
90+
91+
begin
92+
93+
----------------------------------
94+
------- CONTROL INTERFACE -------
95+
----------------------------------
96+
97+
comb_axil : process (sAxilReadMaster, sAxilWriteMaster, axilRst, rAxilWriteSlave, rAxilReadSlave) is
98+
variable vAxilWriteSlave : AxiLiteWriteSlaveType := AXI_LITE_WRITE_SLAVE_INIT_C;
99+
variable vAxilReadSlave : AxiLiteReadSlaveType := AXI_LITE_READ_SLAVE_INIT_C;
100+
variable regCon : AxiLiteEndPointType;
101+
variable vBatchSize : slv(31 downto 0);
102+
begin
103+
104+
-- Latch input values
105+
vAxilWriteSlave := rAxilWriteSlave;
106+
vAxilReadSlave := rAxilReadSlave;
107+
108+
-- Determine the transaction type
109+
axiSlaveWaitTxn(regCon, sAxilWriteMaster, sAxilReadMaster, vAxilWriteSlave, vAxilReadSlave);
110+
111+
-- Read batch size
112+
axiSlaveRegister(regCon, "0000", 0, vBatchSize); -- 2-bit wide because only one reg
113+
114+
-- Closeout the transaction
115+
axiSlaveDefault(regCon, vAxilWriteSlave, vAxilReadSlave, AXI_RESP_DECERR_C);
116+
117+
-- Synchronous reset
118+
if (axilRst = '1') then
119+
vAxilWriteSlave := AXI_LITE_WRITE_SLAVE_INIT_C;
120+
vAxilReadSlave := AXI_LITE_READ_SLAVE_INIT_C;
121+
end if;
122+
123+
-- Combinatory output
124+
rinAxilReadSlave <= vAxilReadSlave;
125+
rinAxilWriteSlave <= vAxilWriteSlave;
126+
batchSizeAxiL <= vBatchSize;
127+
128+
-- Outputs
129+
sAxilReadSlave <= rAxilReadSlave;
130+
sAxilWriteSlave <= rAxilWriteSlave;
131+
end process comb_axil;
132+
133+
seq_axil : process (axilClk) is
134+
begin
135+
if rising_edge(axilClk) then
136+
rAxilReadSlave <= rinAxilReadSlave after TPD_G;
137+
rAxilWriteSlave <= rinAxilWriteSlave after TPD_G;
138+
end if;
139+
end process seq_axil;
140+
141+
----------------------------------
142+
----- END CONTROL INTERFACE -----
143+
----------------------------------
144+
145+
146+
----------------------------------
147+
----- CLOCK DOMAIN CROSSINGS -----
148+
----------------------------------
149+
-- All control signals need to be brought into the mAxisClk domain
150+
-- State of the main FIFO becomes more consistent
151+
152+
U_Axis_CDC : entity surf.AxiStreamFifoV2
153+
generic map(
154+
TPD_G => TPD_G,
155+
MEMORY_TYPE_G => "auto",
156+
GEN_SYNC_FIFO_G => false,
157+
FIFO_ADDR_WIDTH_G => 5, -- Shallow, just for sync
158+
SLAVE_AXI_CONFIG_G => SLAVE_AXI_CONFIG_G,
159+
MASTER_AXI_CONFIG_G => SLAVE_AXI_CONFIG_G) -- Do not change shape
160+
port map(
161+
sAxisClk => sAxisClk,
162+
sAxisRst => sAxisRst,
163+
sAxisMaster => sAxisMaster,
164+
sAxisSlave => sAxisSlave,
165+
166+
mAxisClk => mAxisClk,
167+
mAxisRst => mAxisRst,
168+
mAxisMaster => axisMasterSync,
169+
mAxisSlave => axisSlaveSync );
170+
171+
U_BatchSize_CDC : entity surf.SynchronizerFifo
172+
generic map(
173+
TPD_G => TPD_G,
174+
DATA_WIDTH_G => 32,
175+
INIT_G => x"0000_0001")
176+
port map(
177+
wr_clk => axilClk,
178+
din => batchSizeAxiL,
179+
rd_clk => mAxisClk,
180+
dout => batchSize);
181+
182+
----------------------------------
183+
--- END CLOCK DOMAIN CROSSINGS ---
184+
----------------------------------
185+
186+
187+
----------------------------------
188+
--------- MAIN DATA FIFO ---------
189+
----------------------------------
190+
191+
U_Data_FIFO : entity surf.AxiStreamFifoV2
192+
generic map(
193+
TPD_G => TPD_G,
194+
FIFO_ADDR_WIDTH_G => FIFO_ADDR_WIDTH_G,
195+
GEN_SYNC_FIFO_G => true,
196+
SLAVE_AXI_CONFIG_G => SLAVE_AXI_CONFIG_G,
197+
MASTER_AXI_CONFIG_G => MASTER_AXI_CONFIG_G)
198+
port map(
199+
-- Slave Port
200+
sAxisClk => mAxisClk,
201+
sAxisRst => mAxisRst,
202+
sAxisMaster => axisMasterSync,
203+
sAxisSlave => axisSlaveSync,
204+
205+
-- Master Port
206+
mAxisClk => mAxisClk,
207+
mAxisRst => mAxisRst,
208+
mAxisMaster => axisMasterFifo,
209+
mAxisSlave => axisSlaveFifo );
210+
211+
----------------------------------
212+
------- END MAIN DATA FIFO -------
213+
----------------------------------
214+
215+
-- These signals are not responsible for hanshakes and can
216+
-- just be forwarded
217+
combAxisMaster.tData <= axisMasterFifo.tData;
218+
combAxisMaster.tStrb <= axisMasterFifo.tStrb;
219+
combAxisMaster.tKeep <= axisMasterFifo.tKeep;
220+
combAxisMaster.tLast <= axisMasterFifo.tLast;
221+
combAxisMaster.tDest <= axisMasterFifo.tDest;
222+
combAxisMaster.tId <= axisMasterFifo.tId;
223+
combAxisMaster.tUser <= axisMasterFifo.tUser;
224+
225+
comb : process (r, axisMasterFifo, axisSlaveFifo, axisMasterSync, axisSlaveSync, batchSize, combAxisSlave) is
226+
variable v : RegType;
227+
variable isAcceptedFrame : sl;
228+
variable isOutputFrame : sl;
229+
begin
230+
-- Latch current state
231+
v := r;
232+
233+
-- Check if there is a frame accepted
234+
isAcceptedFrame := axisMasterSync.tValid and axisMasterSync.tLast and axisSlaveSync.tReady;
235+
isOutputFrame := r.sending and axisMasterFifo.tValid and axisMasterFifo.tLast and axisSlaveFifo.tReady;
236+
237+
-- Update counters
238+
if isAcceptedFrame = '1' then
239+
v.frameBatched := r.frameBatched + 1;
240+
else
241+
v.frameBatched := r.frameBatched;
242+
end if;
243+
244+
if isOutputFrame = '1' then
245+
v.frameBatched := v.frameBatched - 1;
246+
v.frameToSend := r.frameToSend - 1;
247+
end if;
248+
249+
if v.frameToSend = 0 then
250+
v.sending := '0';
251+
end if;
252+
253+
if r.sending = '0' and r.frameBatched >= batchSize then
254+
v.sending := '1';
255+
v.frameToSend := batchSize;
256+
end if;
257+
258+
combAxisMaster.tValid <= r.sending and axisMasterFifo.tValid;
259+
axisSlaveFifo.tReady <= r.sending and combAxisSlave.tReady;
260+
261+
rin <= v;
262+
end process comb;
263+
264+
seq : process(mAxisClk) is
265+
begin
266+
if rising_edge(mAxisClk) then
267+
if mAxisRst = '1' then
268+
r <= REG_INIT_C after TPD_G;
269+
else
270+
r <= rin after TPD_G;
271+
end if;
272+
end if;
273+
end process seq;
274+
275+
-- Avoid having combinatorial outputs on the output
276+
-- AxiStream by adding a pipeline stage
277+
U_Output_Pipeline : entity surf.AxiStreamPipeline
278+
generic map(
279+
TPD_G => TPD_G)
280+
port map(
281+
axisClk => mAxisClk,
282+
axisRst => mAxisRst,
283+
284+
sAxisMaster => combAxisMaster,
285+
sAxisSlave => combAxisSlave,
286+
287+
mAxisMaster => mAxisMaster,
288+
mAxisSlave => mAxisSlave);
289+
290+
end rtl;

0 commit comments

Comments
 (0)