1 |
2 |
amulder |
----------------------------------------------------------------------------------
|
2 |
|
|
-- Company:
|
3 |
|
|
-- Engineer: Aart Mulder
|
4 |
|
|
--
|
5 |
|
|
-- Create Date: 22:07:42 04/06/2012
|
6 |
|
|
-- Design Name:
|
7 |
|
|
-- Module Name: byte_segmentation - Behavioral
|
8 |
|
|
-- Project Name: CCITT4
|
9 |
|
|
--
|
10 |
|
|
-- Revision:
|
11 |
|
|
-- Revision 0.01 - File Created
|
12 |
|
|
-- The size of d_width_i and index has a width of 5 bits which
|
13 |
|
|
-- should be sufficient for most situations. With 5 bits a
|
14 |
|
|
-- maximum index of 31 can made, which gives a maximum d_i size
|
15 |
|
|
-- of 31 - 8 = 23 bits.
|
16 |
|
|
--
|
17 |
|
|
-- Revision 0.02 - Input width increased from 13 to 45 bit and the output to 32
|
18 |
|
|
-- bit. Probably 24 bit output width is sufficient enough but
|
19 |
|
|
-- for safety 32 is used for now.
|
20 |
|
|
--
|
21 |
|
|
-- Revision 0.03 - A little brainstorm session:
|
22 |
|
|
-- In worst case we get another huffman code
|
23 |
|
|
-- on every second pclk_i which is 12bit long. The longest huffman
|
24 |
|
|
-- code we can get is 45 bit followed by a 12bit code every other
|
25 |
|
|
-- pclk_i or a 16bit code on the next pclk_i event one time at a line
|
26 |
|
|
-- end.
|
27 |
|
|
-- Let say the maximum buffer size is 45 bit, then at least 2
|
28 |
|
|
-- 8bit buffer read operations are needed before the next pclk_i
|
29 |
|
|
-- event.
|
30 |
|
|
-- When using both the rising and falling edge, a clk_i frequency
|
31 |
|
|
-- of at least 2x pclk_i is needed because we can not read an write
|
32 |
|
|
-- to the buffer at the same time.
|
33 |
|
|
--
|
34 |
|
|
-- Revision 0.04 - byte_segmentation_v3 is made to be used in the capture_manager.
|
35 |
|
|
--
|
36 |
|
|
-- Note: byte_segmentation_v4 is omitted to match the revision numbers here with
|
37 |
|
|
-- the file numbers
|
38 |
|
|
--
|
39 |
|
|
-- Revision 0.05 - This is version 1 (byte_segmentation) with a changed output
|
40 |
|
|
-- port. Instead of one 8bit it has four 8bit ports which will
|
41 |
|
|
-- be used when needed. I.e. when more than 7 bits of data is
|
42 |
|
|
-- available the first one is used, the second one when more
|
43 |
|
|
-- than 15 bits are available and the third and fourth when
|
44 |
|
|
-- more than 23 respectively 31 bits are available in the shift
|
45 |
|
|
-- register.
|
46 |
|
|
-- Furthermore, a FIFO is added to buffer the input in case more
|
47 |
|
|
-- data is coming in than can be processed. Theoretically, in
|
48 |
|
|
-- CCITT4 situations can appear where a 28 bit tiff-run is followed
|
49 |
|
|
-- up by a 16 bit tiff-run with 2 clk_i periods in between.
|
50 |
|
|
--
|
51 |
|
|
-- NOTE: the huffman and fax4 modules has have been modified to
|
52 |
|
|
-- output the black or white run as soon as it is finished, i.e.
|
53 |
|
|
-- separately in time which decreases the maximum code length
|
54 |
|
|
-- to 28. This results in a shift register width of 28+7=35 bit.
|
55 |
|
|
--
|
56 |
|
|
----------------------------------------------------------------------------------
|
57 |
|
|
library IEEE;
|
58 |
|
|
use IEEE.STD_LOGIC_1164.ALL;
|
59 |
|
|
use IEEE.NUMERIC_STD.ALL;
|
60 |
|
|
|
61 |
|
|
entity byte_segmentation_v5 is
|
62 |
|
|
Generic (
|
63 |
|
|
INPUT_WIDTH_G : integer := 28;
|
64 |
|
|
INDEX_WIDTH_G : integer := 5;
|
65 |
|
|
OUTPUT_WIDTH_G : integer := 8
|
66 |
|
|
);
|
67 |
|
|
Port (
|
68 |
|
|
reset_i : in STD_LOGIC;
|
69 |
|
|
clk_i : in STD_LOGIC;
|
70 |
|
|
pclk_i : in STD_LOGIC;
|
71 |
|
|
d_i : in STD_LOGIC_VECTOR (INPUT_WIDTH_G-1 downto 0);
|
72 |
|
|
d_width_i : in STD_LOGIC_VECTOR (INDEX_WIDTH_G-1 downto 0);
|
73 |
|
|
d_rdy_i : in STD_LOGIC;
|
74 |
|
|
frame_finished_i :in STD_LOGIC;
|
75 |
|
|
frame_finished_o :out STD_LOGIC;
|
76 |
|
|
d1_o : out STD_LOGIC_VECTOR (OUTPUT_WIDTH_G-1 downto 0);
|
77 |
|
|
d_rdy1_o : out STD_LOGIC;
|
78 |
|
|
d2_o : out STD_LOGIC_VECTOR (OUTPUT_WIDTH_G-1 downto 0);
|
79 |
|
|
d_rdy2_o : out STD_LOGIC;
|
80 |
|
|
d3_o : out STD_LOGIC_VECTOR (OUTPUT_WIDTH_G-1 downto 0);
|
81 |
|
|
d_rdy3_o : out STD_LOGIC;
|
82 |
|
|
d4_o : out STD_LOGIC_VECTOR (OUTPUT_WIDTH_G-1 downto 0);
|
83 |
|
|
d_rdy4_o : out STD_LOGIC
|
84 |
|
|
);
|
85 |
|
|
end byte_segmentation_v5;
|
86 |
|
|
|
87 |
|
|
architecture Behavioral of byte_segmentation_v5 is
|
88 |
|
|
constant SHIFT_REG_SIZE_C : integer := (INPUT_WIDTH_G+OUTPUT_WIDTH_G)-1;
|
89 |
|
|
constant SHIFT_REG_INDEX_WIDTH_C : integer := INDEX_WIDTH_G+1;
|
90 |
|
|
|
91 |
|
|
signal shift_reg : std_logic_vector(SHIFT_REG_SIZE_C-1 downto 0) := (others => '1');
|
92 |
|
|
signal index : unsigned (SHIFT_REG_INDEX_WIDTH_C-1 downto 0) := (others => '0');
|
93 |
|
|
signal finish_frame : std_logic := '0';
|
94 |
|
|
signal frame_finished_prev : std_logic := '0';
|
95 |
|
|
signal reset_finish_frame : std_logic := '0';
|
96 |
|
|
signal index2 : std_logic_vector (5 downto 0) := (others => '0');
|
97 |
|
|
|
98 |
|
|
--FIFO signals
|
99 |
|
|
signal FIFO_din, FIFO_dout : std_logic_vector((INPUT_WIDTH_G+INDEX_WIDTH_G)-1 downto 0) := (others => '1');
|
100 |
|
|
signal FIFO_rd, FIFO_empty, FIFO_valid : std_logic := '0';
|
101 |
|
|
signal in_data : std_logic_vector(INPUT_WIDTH_G-1 downto 0);
|
102 |
|
|
signal in_data_width : std_logic_vector(SHIFT_REG_INDEX_WIDTH_C-1 downto 0);
|
103 |
|
|
signal FIFO_used : unsigned(3 downto 0);
|
104 |
|
|
|
105 |
|
|
begin
|
106 |
|
|
DualClkFIFO_ins : entity work.DualClkFIFO
|
107 |
|
|
GENERIC MAP (
|
108 |
|
|
DATA_WIDTH_G => INPUT_WIDTH_G+INDEX_WIDTH_G,
|
109 |
|
|
MEMORY_SIZE_G => 16,
|
110 |
|
|
MEMORY_ADDRESS_WIDTH_G => 4
|
111 |
|
|
)
|
112 |
|
|
PORT MAP (
|
113 |
|
|
rst_i => reset_i,
|
114 |
|
|
wr_clk_i => pclk_i,
|
115 |
|
|
rd_clk_i => clk_i,
|
116 |
|
|
empty_o => FIFO_empty,
|
117 |
|
|
full_o => open,
|
118 |
|
|
pull_i => FIFO_rd,
|
119 |
|
|
valid_o=> FIFO_valid,
|
120 |
|
|
push_i => d_rdy_i,
|
121 |
|
|
used_o => FIFO_used,
|
122 |
|
|
d_i => FIFO_din,
|
123 |
|
|
d_o => FIFO_dout
|
124 |
|
|
);
|
125 |
|
|
|
126 |
|
|
FIFO_din <= d_width_i & d_i;
|
127 |
|
|
in_data_width <= '0' & FIFO_dout((INPUT_WIDTH_G+INDEX_WIDTH_G)-1 downto INPUT_WIDTH_G);
|
128 |
|
|
in_data <= FIFO_dout(INPUT_WIDTH_G-1 downto 0);
|
129 |
|
|
|
130 |
|
|
index2 <= std_logic_vector(index);
|
131 |
|
|
|
132 |
|
|
--This process controls the read pin of the FIFO.
|
133 |
|
|
FIFO_rd_process : process(clk_i)
|
134 |
|
|
begin
|
135 |
|
|
if clk_i'event and clk_i = '0' then
|
136 |
|
|
if FIFO_empty = '0' then
|
137 |
|
|
if (FIFO_valid = '0' and index < to_unsigned(OUTPUT_WIDTH_G, SHIFT_REG_INDEX_WIDTH_C))
|
138 |
|
|
or (FIFO_rd = '1' and (index + unsigned(in_data_width)) < to_unsigned(8, SHIFT_REG_INDEX_WIDTH_C)) then
|
139 |
|
|
FIFO_rd <= '1';
|
140 |
|
|
else
|
141 |
|
|
FIFO_rd <= '0';
|
142 |
|
|
end if;
|
143 |
|
|
else
|
144 |
|
|
FIFO_rd <= '0';
|
145 |
|
|
end if;
|
146 |
|
|
end if;
|
147 |
|
|
end process FIFO_rd_process;
|
148 |
|
|
|
149 |
|
|
process(clk_i)
|
150 |
|
|
variable ind1, ind2, ind3, ind4 : integer range 0 to SHIFT_REG_SIZE_C := 0;
|
151 |
|
|
begin
|
152 |
|
|
if clk_i'event and clk_i = '1' then
|
153 |
|
|
reset_finish_frame <= '0';
|
154 |
|
|
|
155 |
|
|
if FIFO_valid = '1' and index < to_unsigned(OUTPUT_WIDTH_G, SHIFT_REG_INDEX_WIDTH_C) then
|
156 |
|
|
--
|
157 |
|
|
--The synthesiser complains that shift_reg(0) is equal to shift_reg(1) to shift_reg(6). When
|
158 |
|
|
--verifying by hand the following situations can apear:
|
159 |
|
|
-- SHIFT_REG_SIZE_C = 45+8-1=52
|
160 |
|
|
-- index = 0
|
161 |
|
|
-- d_width_i = 45
|
162 |
|
|
-- Gives: shift_reg(51 downto 7) <= input data
|
163 |
|
|
--
|
164 |
|
|
-- index = 7
|
165 |
|
|
-- d_width_i = 45
|
166 |
|
|
-- Gives: shift_reg(44 downto 0) <= input data
|
167 |
|
|
--
|
168 |
|
|
--So theoretically the warning is not correct.
|
169 |
|
|
--
|
170 |
|
|
d_rdy1_o <= '0';
|
171 |
|
|
d_rdy2_o <= '0';
|
172 |
|
|
d_rdy3_o <= '0';
|
173 |
|
|
d_rdy4_o <= '0';
|
174 |
|
|
ind3 := to_integer(unsigned(in_data_width))-1;
|
175 |
|
|
case index2 is
|
176 |
|
|
when std_logic_vector(to_unsigned(0, 6)) =>
|
177 |
|
|
ind2 := (SHIFT_REG_SIZE_C-0)-to_integer(unsigned(in_data_width));
|
178 |
|
|
shift_reg((SHIFT_REG_SIZE_C-1)-0 downto ind2) <= in_data(ind3 downto 0);
|
179 |
|
|
when std_logic_vector(to_unsigned(1, 6)) =>
|
180 |
|
|
ind2 := (SHIFT_REG_SIZE_C-1)-to_integer(unsigned(in_data_width));
|
181 |
|
|
shift_reg((SHIFT_REG_SIZE_C-1)-1 downto ind2) <= in_data(ind3 downto 0);
|
182 |
|
|
when std_logic_vector(to_unsigned(2, 6)) =>
|
183 |
|
|
ind2 := (SHIFT_REG_SIZE_C-2)-to_integer(unsigned(in_data_width));
|
184 |
|
|
shift_reg((SHIFT_REG_SIZE_C-1)-2 downto ind2) <= in_data(ind3 downto 0);
|
185 |
|
|
when std_logic_vector(to_unsigned(3, 6)) =>
|
186 |
|
|
ind2 := (SHIFT_REG_SIZE_C-3)-to_integer(unsigned(in_data_width));
|
187 |
|
|
shift_reg((SHIFT_REG_SIZE_C-1)-3 downto ind2) <= in_data(ind3 downto 0);
|
188 |
|
|
when std_logic_vector(to_unsigned(4, 6)) =>
|
189 |
|
|
ind2 := (SHIFT_REG_SIZE_C-4)-to_integer(unsigned(in_data_width));
|
190 |
|
|
shift_reg((SHIFT_REG_SIZE_C-1)-4 downto ind2) <= in_data(ind3 downto 0);
|
191 |
|
|
when std_logic_vector(to_unsigned(5, 6)) =>
|
192 |
|
|
ind2 := (SHIFT_REG_SIZE_C-5)-to_integer(unsigned(in_data_width));
|
193 |
|
|
shift_reg((SHIFT_REG_SIZE_C-1)-5 downto ind2) <= in_data(ind3 downto 0);
|
194 |
|
|
when std_logic_vector(to_unsigned(6, 6)) =>
|
195 |
|
|
ind2 := (SHIFT_REG_SIZE_C-6)-to_integer(unsigned(in_data_width));
|
196 |
|
|
shift_reg((SHIFT_REG_SIZE_C-1)-6 downto ind2) <= in_data(ind3 downto 0);
|
197 |
|
|
when std_logic_vector(to_unsigned(7, 6)) =>
|
198 |
|
|
ind2 := (SHIFT_REG_SIZE_C-7)-to_integer(unsigned(in_data_width));
|
199 |
|
|
shift_reg((SHIFT_REG_SIZE_C-1)-7 downto ind2) <= in_data(ind3 downto 0);
|
200 |
|
|
when others =>
|
201 |
|
|
shift_reg <= (others => '0');
|
202 |
|
|
end case;
|
203 |
|
|
index <= index + unsigned(in_data_width);
|
204 |
|
|
elsif index >= to_unsigned(OUTPUT_WIDTH_G*1, SHIFT_REG_INDEX_WIDTH_C) and index < to_unsigned(OUTPUT_WIDTH_G*2, SHIFT_REG_INDEX_WIDTH_C) then
|
205 |
|
|
--Move the highest OUTPUT_WIDTH_G bits to the output
|
206 |
|
|
d1_o <= shift_reg(SHIFT_REG_SIZE_C-1 downto SHIFT_REG_SIZE_C-OUTPUT_WIDTH_G);
|
207 |
|
|
d_rdy1_o <= '1';
|
208 |
|
|
d_rdy2_o <= '0';
|
209 |
|
|
d_rdy3_o <= '0';
|
210 |
|
|
d_rdy4_o <= '0';
|
211 |
|
|
--Shift the left over bits(all except OUTPUT_WIDTH_G highest) OUTPUT_WIDTH_G positions up/left
|
212 |
|
|
shift_reg(SHIFT_REG_SIZE_C-1 downto OUTPUT_WIDTH_G) <= shift_reg((SHIFT_REG_SIZE_C-1)-OUTPUT_WIDTH_G downto 0);
|
213 |
|
|
--Decrement the index with 8
|
214 |
|
|
index <= index - to_unsigned(OUTPUT_WIDTH_G, SHIFT_REG_INDEX_WIDTH_C);
|
215 |
|
|
elsif index >= to_unsigned(OUTPUT_WIDTH_G*2, SHIFT_REG_INDEX_WIDTH_C) and index < to_unsigned(OUTPUT_WIDTH_G*3, SHIFT_REG_INDEX_WIDTH_C) then
|
216 |
|
|
--Move the highest OUTPUT_WIDTH_G*2 bits to the output
|
217 |
|
|
d1_o <= shift_reg(SHIFT_REG_SIZE_C-1 downto SHIFT_REG_SIZE_C-OUTPUT_WIDTH_G);
|
218 |
|
|
d_rdy1_o <= '1';
|
219 |
|
|
d2_o <= shift_reg((SHIFT_REG_SIZE_C-1)-(OUTPUT_WIDTH_G*1) downto SHIFT_REG_SIZE_C-(OUTPUT_WIDTH_G*2));
|
220 |
|
|
d_rdy2_o <= '1';
|
221 |
|
|
d_rdy3_o <= '0';
|
222 |
|
|
d_rdy4_o <= '0';
|
223 |
|
|
--Shift the left over bits(all except OUTPUT_WIDTH_G*2 highest) OUTPUT_WIDTH_G*2 positions up/left
|
224 |
|
|
shift_reg(SHIFT_REG_SIZE_C-1 downto (OUTPUT_WIDTH_G*2)) <= shift_reg((SHIFT_REG_SIZE_C-1)-(OUTPUT_WIDTH_G*2) downto 0);
|
225 |
|
|
--Decrement the index with 16
|
226 |
|
|
index <= index - to_unsigned(OUTPUT_WIDTH_G*2, SHIFT_REG_INDEX_WIDTH_C);
|
227 |
|
|
elsif index >= to_unsigned(OUTPUT_WIDTH_G*3, SHIFT_REG_INDEX_WIDTH_C) and index < to_unsigned(OUTPUT_WIDTH_G*4, SHIFT_REG_INDEX_WIDTH_C) then
|
228 |
|
|
--Move the highest OUTPUT_WIDTH_G*3 bits to the output
|
229 |
|
|
d1_o <= shift_reg(SHIFT_REG_SIZE_C-1 downto SHIFT_REG_SIZE_C-OUTPUT_WIDTH_G);
|
230 |
|
|
d_rdy1_o <= '1';
|
231 |
|
|
d2_o <= shift_reg((SHIFT_REG_SIZE_C-1)-(OUTPUT_WIDTH_G*1) downto SHIFT_REG_SIZE_C-(OUTPUT_WIDTH_G*2));
|
232 |
|
|
d_rdy2_o <= '1';
|
233 |
|
|
d3_o <= shift_reg((SHIFT_REG_SIZE_C-1)-(OUTPUT_WIDTH_G*2) downto SHIFT_REG_SIZE_C-(OUTPUT_WIDTH_G*3));
|
234 |
|
|
d_rdy3_o <= '1';
|
235 |
|
|
d_rdy4_o <= '0';
|
236 |
|
|
--Shift the left over bits(all except OUTPUT_WIDTH_G*3 highest) OUTPUT_WIDTH_G*3 positions up/left
|
237 |
|
|
shift_reg(SHIFT_REG_SIZE_C-1 downto (OUTPUT_WIDTH_G*3)) <= shift_reg((SHIFT_REG_SIZE_C-1)-(OUTPUT_WIDTH_G*3) downto 0);
|
238 |
|
|
--Decrement the index with 24
|
239 |
|
|
index <= index - to_unsigned(OUTPUT_WIDTH_G*3, SHIFT_REG_INDEX_WIDTH_C);
|
240 |
|
|
elsif index >= to_unsigned(OUTPUT_WIDTH_G*4, SHIFT_REG_INDEX_WIDTH_C) then
|
241 |
|
|
--Move the highest OUTPUT_WIDTH_G*4 bits to the output
|
242 |
|
|
d1_o <= shift_reg(SHIFT_REG_SIZE_C-1 downto SHIFT_REG_SIZE_C-OUTPUT_WIDTH_G);
|
243 |
|
|
d_rdy1_o <= '1';
|
244 |
|
|
d2_o <= shift_reg((SHIFT_REG_SIZE_C-1)-(OUTPUT_WIDTH_G*1) downto SHIFT_REG_SIZE_C-(OUTPUT_WIDTH_G*2));
|
245 |
|
|
d_rdy2_o <= '1';
|
246 |
|
|
d3_o <= shift_reg((SHIFT_REG_SIZE_C-1)-(OUTPUT_WIDTH_G*2) downto SHIFT_REG_SIZE_C-(OUTPUT_WIDTH_G*3));
|
247 |
|
|
d_rdy3_o <= '1';
|
248 |
|
|
d4_o <= shift_reg((SHIFT_REG_SIZE_C-1)-(OUTPUT_WIDTH_G*3) downto SHIFT_REG_SIZE_C-(OUTPUT_WIDTH_G*4));
|
249 |
|
|
d_rdy4_o <= '1';
|
250 |
|
|
--Shift the left over bits(all except OUTPUT_WIDTH_G*4 highest) OUTPUT_WIDTH_G*4 positions up/left
|
251 |
|
|
shift_reg(SHIFT_REG_SIZE_C-1 downto (OUTPUT_WIDTH_G*4)) <= shift_reg((SHIFT_REG_SIZE_C-1)-(OUTPUT_WIDTH_G*4) downto 0);
|
252 |
|
|
--Decrement the index with 32
|
253 |
|
|
index <= index - to_unsigned(OUTPUT_WIDTH_G*4, SHIFT_REG_INDEX_WIDTH_C);
|
254 |
|
|
elsif finish_frame = '1' and FIFO_used = "0000" then
|
255 |
|
|
reset_finish_frame <= '1';
|
256 |
|
|
|
257 |
|
|
d1_o <= (others => '0');
|
258 |
|
|
if index > to_unsigned(0, SHIFT_REG_INDEX_WIDTH_C) then
|
259 |
|
|
d1_o(OUTPUT_WIDTH_G-1 downto OUTPUT_WIDTH_G-to_integer(index)) <= shift_reg(SHIFT_REG_SIZE_C-1 downto SHIFT_REG_SIZE_C-to_integer(index));
|
260 |
|
|
d_rdy1_o <= '1';
|
261 |
|
|
else
|
262 |
|
|
d_rdy1_o <= '0';
|
263 |
|
|
end if;
|
264 |
|
|
d_rdy2_o <= '0';
|
265 |
|
|
d_rdy3_o <= '0';
|
266 |
|
|
d_rdy4_o <= '0';
|
267 |
|
|
|
268 |
|
|
index <= (others => '0');
|
269 |
|
|
shift_reg <= (others => '0');
|
270 |
|
|
else
|
271 |
|
|
d_rdy1_o <= '0';
|
272 |
|
|
d_rdy2_o <= '0';
|
273 |
|
|
d_rdy3_o <= '0';
|
274 |
|
|
d_rdy4_o <= '0';
|
275 |
|
|
end if;
|
276 |
|
|
end if;
|
277 |
|
|
end process;
|
278 |
|
|
|
279 |
|
|
process(clk_i)
|
280 |
|
|
begin
|
281 |
|
|
if clk_i'event and clk_i = '1' then
|
282 |
|
|
frame_finished_prev <= frame_finished_i;
|
283 |
|
|
|
284 |
|
|
if frame_finished_i = '0' and frame_finished_prev = '1' then
|
285 |
|
|
finish_frame <= '1';
|
286 |
|
|
elsif reset_finish_frame = '1' then
|
287 |
|
|
finish_frame <= '0';
|
288 |
|
|
end if;
|
289 |
|
|
end if;
|
290 |
|
|
end process;
|
291 |
|
|
|
292 |
|
|
frame_finished_o <= reset_finish_frame;
|
293 |
|
|
|
294 |
|
|
end Behavioral;
|