Skip to content

Commit aec0740

Browse files
committed
bnoc/committed: Add committed_padder component
Add a module that pads committed frames to a minimum size by appending a constant padding byte. Frames already meeting or exceeding the minimum size are passed through unchanged. Configuration: - min_size_c: Minimum frame size (positive generic) - padding_byte_c: Padding byte value (default x"00") Implementation uses a 2-deep FIFO to break combinatorial paths between input and output. The output stage maintains a down-counter initialized to min_size_c, decremented for each data byte output. When the input frame ends, padding is added if counter hasn't reached zero before outputting the commit/cancel status. Includes comprehensive testbench covering: - Short frames (require padding) - Exact size frames (no padding) - Long frames (no padding) - Empty frames (full padding) - Both commit and cancel status handling
1 parent d2c6a6e commit aec0740

File tree

7 files changed

+396
-0
lines changed

7 files changed

+396
-0
lines changed

lib/nsl_bnoc/committed/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ vhdl-sources += committed_prefill_buffer.vhd
88
vhdl-sources += committed_header_inserter.vhd
99
vhdl-sources += committed_header_extractor.vhd
1010
vhdl-sources += committed_fifo_slice.vhd
11+
vhdl-sources += committed_padder.vhd
1112
vhdl-sources += committed_statistics.vhd
1213

1314
deps += nsl_memory.fifo

lib/nsl_bnoc/committed/committed.pkg.vhd

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,26 @@ package committed is
236236
);
237237
end component;
238238

239+
-- Pads frames to a minimum size by appending a constant padding byte.
240+
-- Frames already meeting or exceeding min_size_c are passed through unchanged.
241+
-- The status byte is always forwarded after padding.
242+
component committed_padder is
243+
generic(
244+
min_size_c : positive;
245+
padding_byte_c : byte := x"00"
246+
);
247+
port(
248+
reset_n_i : in std_ulogic;
249+
clock_i : in std_ulogic;
250+
251+
in_i : in committed_req_t;
252+
in_o : out committed_ack_t;
253+
254+
out_o : out committed_req_t;
255+
out_i : in committed_ack_t
256+
);
257+
end component;
258+
239259
-- A module asserting valid_o exactly during one cycle at end of
240260
-- every frame. Gives out statistic about past frame when valid_o
241261
-- is asserted.
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
library ieee;
2+
use ieee.std_logic_1164.all;
3+
use ieee.numeric_std.all;
4+
5+
library nsl_bnoc, nsl_data, nsl_logic;
6+
use nsl_logic.bool.all;
7+
use nsl_bnoc.committed.all;
8+
use nsl_data.bytestream.all;
9+
10+
entity committed_padder is
11+
generic(
12+
min_size_c : positive;
13+
padding_byte_c : byte := x"00"
14+
);
15+
port(
16+
reset_n_i : in std_ulogic;
17+
clock_i : in std_ulogic;
18+
19+
in_i : in committed_req;
20+
in_o : out committed_ack;
21+
22+
out_o : out committed_req;
23+
out_i : in committed_ack
24+
);
25+
end entity;
26+
27+
architecture beh of committed_padder is
28+
29+
type in_state_t is (
30+
IN_RESET,
31+
IN_DATA,
32+
IN_COMMIT,
33+
IN_CANCEL
34+
);
35+
36+
type out_state_t is (
37+
OUT_RESET,
38+
OUT_DATA,
39+
OUT_PAD,
40+
OUT_COMMIT,
41+
OUT_CANCEL
42+
);
43+
44+
constant fifo_depth_c : integer := 2;
45+
46+
type regs_t is
47+
record
48+
in_state : in_state_t;
49+
50+
fifo: byte_string(0 to fifo_depth_c-1);
51+
fifo_fillness: integer range 0 to fifo_depth_c;
52+
53+
out_state : out_state_t;
54+
out_left : integer range 0 to min_size_c-1;
55+
end record;
56+
57+
signal r, rin: regs_t;
58+
59+
begin
60+
61+
regs: process(clock_i, reset_n_i) is
62+
begin
63+
if rising_edge(clock_i) then
64+
r <= rin;
65+
end if;
66+
67+
if reset_n_i = '0' then
68+
r.in_state <= IN_RESET;
69+
r.out_state <= OUT_RESET;
70+
end if;
71+
end process;
72+
73+
transition: process(r, in_i, out_i) is
74+
variable fifo_push, fifo_pop: boolean;
75+
begin
76+
rin <= r;
77+
78+
fifo_pop := false;
79+
fifo_push := false;
80+
81+
case r.in_state is
82+
when IN_RESET =>
83+
rin.in_state <= IN_DATA;
84+
rin.fifo_fillness <= 0;
85+
86+
when IN_DATA =>
87+
if r.fifo_fillness < fifo_depth_c and in_i.valid = '1' then
88+
if in_i.last = '0' then
89+
fifo_push := true;
90+
elsif in_i.data(0) = '1' then
91+
rin.in_state <= IN_COMMIT;
92+
else
93+
rin.in_state <= IN_CANCEL;
94+
end if;
95+
end if;
96+
97+
when IN_COMMIT | IN_CANCEL =>
98+
if (r.out_state = OUT_COMMIT or r.out_state = OUT_CANCEL)
99+
and out_i.ready = '1' then
100+
rin.in_state <= IN_DATA;
101+
end if;
102+
end case;
103+
104+
case r.out_state is
105+
when OUT_RESET =>
106+
rin.out_state <= OUT_DATA;
107+
rin.out_left <= min_size_c-1;
108+
109+
when OUT_DATA =>
110+
fifo_pop := r.fifo_fillness > 0 and out_i.ready = '1';
111+
112+
if fifo_pop and r.out_left > 0 then
113+
rin.out_left <= r.out_left - 1;
114+
end if;
115+
116+
if r.fifo_fillness = 0 or (r.fifo_fillness = 1 and out_i.ready = '1') then
117+
if r.in_state = IN_CANCEL then
118+
-- Early exit for cancelled frames, skip padding
119+
rin.out_state <= OUT_CANCEL;
120+
elsif r.in_state = IN_COMMIT then
121+
-- Check if padding is needed for committed frames
122+
if r.out_left = 0 or (r.out_left = 1 and fifo_pop) then
123+
rin.out_state <= OUT_COMMIT;
124+
else
125+
rin.out_state <= OUT_PAD;
126+
end if;
127+
end if;
128+
end if;
129+
130+
when OUT_PAD =>
131+
if out_i.ready = '1' then
132+
if r.out_left = 0 then
133+
rin.out_state <= OUT_COMMIT;
134+
else
135+
rin.out_left <= r.out_left - 1;
136+
end if;
137+
end if;
138+
139+
when OUT_COMMIT | OUT_CANCEL =>
140+
if out_i.ready = '1' then
141+
rin.out_state <= OUT_RESET;
142+
rin.out_left <= min_size_c-1;
143+
end if;
144+
end case;
145+
146+
if fifo_push and fifo_pop then
147+
rin.fifo <= shift_left(r.fifo);
148+
rin.fifo(r.fifo_fillness-1) <= in_i.data;
149+
elsif fifo_push then
150+
rin.fifo(r.fifo_fillness) <= in_i.data;
151+
rin.fifo_fillness <= r.fifo_fillness + 1;
152+
elsif fifo_pop then
153+
rin.fifo <= shift_left(r.fifo);
154+
rin.fifo_fillness <= r.fifo_fillness - 1;
155+
end if;
156+
end process;
157+
158+
moore: process(r) is
159+
begin
160+
in_o.ready <= '0';
161+
out_o <= committed_req_idle_c;
162+
163+
case r.out_state is
164+
when OUT_RESET =>
165+
null;
166+
167+
when OUT_DATA =>
168+
out_o <= committed_flit(r.fifo(0), valid => r.fifo_fillness /= 0);
169+
170+
when OUT_PAD =>
171+
out_o <= committed_flit(padding_byte_c);
172+
173+
when OUT_COMMIT =>
174+
out_o <= committed_commit(true);
175+
176+
when OUT_CANCEL =>
177+
out_o <= committed_commit(false);
178+
end case;
179+
180+
case r.in_state is
181+
when IN_RESET | IN_COMMIT | IN_CANCEL =>
182+
null;
183+
184+
when IN_DATA =>
185+
in_o.ready <= to_logic(r.fifo_fillness < fifo_depth_c);
186+
end case;
187+
end process;
188+
189+
end architecture;

tests/bnoc/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
tb += committed_header
2+
tb += committed_padder
23
tb += crc
34
tb += framed_router
45
tb += spi_committed_sink
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
top = work.tb
2+
work-srcdir = $(SRC_DIR)/src
3+
tool = ghdl
4+
hwdep = simulation
5+
6+
include ../../../build/build.mk
7+
8+
$(target).ghw:
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
vhdl-sources += tb.vhd
2+
3+
deps += nsl_bnoc.committed
4+
deps += nsl_bnoc.testing
5+
deps += nsl_data.bytestream
6+
deps += nsl_data.text
7+
deps += nsl_simulation.assertions
8+
deps += nsl_simulation.driver
9+
deps += nsl_simulation.logging

0 commit comments

Comments
 (0)