📄 compressor.vhd
字号:
when 2 =>
result := "001000000000011";
when 3 =>
result := "001000000000100";
when 4 =>
result := "001000000000101";
when 5 =>
result := "001000000000110";
when 6 =>
result := "001100000001110";
when 7 =>
result := "010000000011110";
when 8 =>
result := "010100000111110";
when 9 =>
result := "011000001111110";
when 10 =>
result := "011100011111110";
when others => --11
result := "100000111111110";
end case;
else --DC chrominance table
case Cat is
when 0 =>
result := "000100000000000";
when 1 =>
result := "000100000000001";
when 2 =>
result := "000100000000010";
when 3 =>
result := "001000000000110";
when 4 =>
result := "001100000001110";
when 5 =>
result := "010000000011110";
when 6 =>
result := "010100000111110";
when 7 =>
result := "011000001111110";
when 8 =>
result := "011100011111110";
when 9 =>
result := "100000111111110";
when 10 =>
result := "100101111111110";
when others => --11
result := "101011111111110";
end case;
end if;
return result;
end CompressDC;
begin
with Save select addr <= addribk when '1', addri when others;
with CompressingInt select addrY <= addrY2 when '1', addrY1 when others;
with CompressingInt select addrCb <= addrCb2 when '1', addrCb1 when others;
with CompressingInt select addrCr <= addrCr2 when '1', addrCr1 when others;
with CompressingInt select weY <= weY2 when '1', weY1 when others;
with CompressingInt select weCb <= weCb2 when '1', weCb1 when others;
with CompressingInt select weCr <= weCr2 when '1', weCr1 when others;
with CompressingInt select dinY <= dinY2 when '1', dinY1 when others;
with CompressingInt select dinCb <= dinCb2 when '1', dinCb1 when others;
with CompressingInt select dinCr <= dinCr2 when '1', dinCr1 when others;
DCT1 : dct2d port map (ND,RDY,RFD,clk,DIND,DOUTD);
buffer_compY : buffer_comp port map (addrY,clk,dinY,doutY,weY);
buffer_compCb : buffer_comp_chrom port map (addrCb,clk,dinCb,doutCb,weCb);
buffer_compCr : buffer_comp_chrom port map (addrCr,clk,dinCr,doutCr,weCr);
Q_ROM1 : q_rom port map (addrQ,clk,doutQ);
Huffman_ROM : huff_rom port map (addrH,clk,doutH);
Tabla_Q1 : tabla_q port map(addrTablaQ,clk,doutTablaQ);
RGB2YCbCr : process(reset, clk)
--It applies the transformation from RGB to YCBCr and pass it to the JPEG process
-- but what we are going to save in the buffers will be the pixels of the components with
-- the JPEG level shift already applied, so that the transformation's last addition: [0;128;128] will become -[128;0;0]
variable Baton : integer range 0 to 3 := 0; --indicates the current state of the FSM
variable Red1 : std_logic_vector(17 downto 0);
variable Red2 : std_logic_vector(17 downto 0);
variable Red3 : std_logic_vector(17 downto 0);
variable Green1 : std_logic_vector(17 downto 0);
variable Green2 : std_logic_vector(17 downto 0);
variable Green3 : std_logic_vector(17 downto 0);
variable Blue1 : std_logic_vector(17 downto 0);
variable Blue2 : std_logic_vector(17 downto 0);
variable Blue3 : std_logic_vector(17 downto 0);
variable Cb, Cr : std_logic_vector(10 downto 0);
begin
if (reset = '1') then
Compressing <= '0';
addrY1 <= (others => '0');
addrCb1 <= (others => '0');
addrCr1 <= (others => '0');
weY1 <= '0';
weCb1 <= '0';
weCr1 <= '0';
dinCb1 <= (others => '0');
dinCr1 <= (others => '0');
dinY1 <= (others => '0');
LineToCompress <= "0000";
LineAbsToCompress <= (others => '0');
ColumnToCompress <= (others => '0');
Baton := 0;
Cb := (others => '0');
Cr := (others => '0');
ProcessingRGB <= '0';
MakeDCT <= '0';
Red1 := (others => '0');
Red2 := (others => '0');
Red3 := (others => '0');
Green1 := (others => '0');
Green2 := (others => '0');
Green3 := (others => '0');
Blue1 := (others => '0');
Blue2 := (others => '0');
Blue3 := (others => '0');
elsif (clk = '1' and clk'event) then
if CompressImage = '1' then
Compressing <= '1';
addrY1 <= (others => '0');
addrCb1 <= (others => '0');
addrCr1 <= (others => '0');
weY1 <= '0';
weCb1 <= '0';
weCr1 <= '0';
LineToCompress <= "0000";
LineAbsToCompress <= (others => '0');
ColumnToCompress <= (others => '0');
Baton := 0;
ProcessingRGB <= '0';
end if;
if (ProcessRGB = '1') then
ProcessingRGB <= '1'; --while this one is high, there won't be another ProcessRGB='1'
Baton := 1;
end if;
addrY1 <= Mult_Columns(LineToCompress) + ColumnToCompress;
addrCb1 <= Mult_Half_Columns(LineToCompress(3 downto 1)) + (ColumnToCompress(9 downto 1)); --for the subsampling
addrCr1 <= Mult_Half_Columns(LineToCompress(3 downto 1)) + (ColumnToCompress(9 downto 1));
--we pre-read the saved data, so as to average the chroma components Cb and Cr
--to be able to do a proper subsampling 2x2 1x1 1x1
case Baton is
when 0 =>
weY1 <= '0';
weCb1 <= '0';
weCr1 <= '0';
MakeDCT <= '0';
when 1 =>
--we apply only the transformation RGB to YCbCr
Red1 := Multiplier(Red, "0010011001"); --153
Red2 := Multiplier(Red, "0010101101"); --173
Red3 := "0000000000" & Red; --1
Green1 := Multiplier(Green, "1001011001"); --601
Green2 := Multiplier(Green, "0101010011"); --339
Green3 := Multiplier(Green, "0110101101"); --429
Blue1 := Multiplier(Blue, "0001110101"); --117
Blue2 := "0000000000" & Blue; --1
Blue3 := Multiplier(Blue, "0001010011"); --83
--the largest obtainable result would be 255*601=153255 (100101011010100111)
Baton := 2;
MakeDCT <= '0';
when 2 =>
--dinY1 <= "111110000000"; --for debugging, to make Y zero, so that in the resulting image the Blue channel will be Cb and the Red one will be Cr
dinY1 <= "0000" & (Red1(16 downto 9) + Green1(17 downto 10) + Blue1(17 downto 10) - "10000000");-- + Red1(8) + Green1(9) + Blue1(9)); --Red1/512+Green1/1024+Blue1/1024 and with -128 for the level shift
if Mono = '1' then
Cb := (others => '0');
Cr := (others => '0');
else
Cb := "000" & (Blue2(8 downto 1) - Red2(17 downto 10) - Green2(17 downto 10)); -- + Blue2(0) - Red2(9) - Green2(9)); --Red & Green between 1024 and Blue between 2
Cr := "000" & (Red3(8 downto 1) - Green3(17 downto 10) - Blue3(17 downto 10)); -- + Red3(0) - Green3(9) - Blue3(9)); --between 1024 all but Red
--debug: the bits added/substracted at the end are the nearest integer rounding
end if;
--Subsampling: average groups of 4 pixels in blocks of 2x2
if LineAbsToCompress(0) = '0' and ColumnToCompress(0) = '0' then --element (0,0)
--dinCb1 <= "0000" & Cb(7 downto 0);
--dinCr1 <= "0000" & Cr(7 downto 0);
dinCb1 <= "0000" & Cb(7 downto 0);
dinCr1 <= "0000" & Cr(7 downto 0);
elsif LineAbsToCompress(0) = '0' and ColumnToCompress(0) = '1' then --element (0,1)
Cb := (Cb(7) & Cb(7) & Cb(7) & Cb(7 downto 0)) + (doutCb(7) & doutCb(7 downto 0));
Cr := (Cr(7) & Cr(7) & Cr(7) & Cr(7 downto 0)) + (doutCr(7) & doutCr(7 downto 0));
dinCb1 <= "000" & Cb(8 downto 0);
dinCr1 <= "000" & Cr(8 downto 0);
elsif LineAbsToCompress(0) = '1' and ColumnToCompress(0) = '0' then --element (1,0)
Cb := (Cb(7) & Cb(7) & Cb(7) & Cb(7 downto 0)) + (doutCb(8) & doutCb(8 downto 0));
Cr := (Cr(7) & Cr(7) & Cr(7) & Cr(7 downto 0)) + (doutCr(8) & doutCr(8 downto 0));
dinCb1 <= "00" & Cb(9 downto 0);
dinCr1 <= "00" & Cr(9 downto 0);
else --element (1,1) before, we have added directly, now we add and write the average of the 4 pixels, so as to not lose precission
Cb := (Cb(7) & Cb(7) & Cb(7) & Cb(7 downto 0)) + (doutCb(9) & doutCb(9 downto 0));
Cr := (Cr(7) & Cr(7) & Cr(7) & Cr(7 downto 0)) + (doutCr(9) & doutCr(9 downto 0));
dinCb1 <= "0000" & Cb(9 downto 2);
dinCr1 <= "0000" & Cr(9 downto 2);
--next lines are for debugging purposes (instead of the last if,elsifs and else to write just
--one chrominance value for Cb and Cr instead of averaging)
--Cb := (Cb(7) & Cb(7) & Cb(7) & Cb(7 downto 2)) + (doutCb(7) & doutCb(7 downto 0));
--Cr := (Cr(7) & Cr(7) & Cr(7) & Cr(7 downto 2)) + (doutCr(7) & doutCr(7 downto 0));
--dinCb1 <= "0000" & Cb(7 downto 0);
--dinCr1 <= "0000" & Cr(7 downto 0);
--weCb1 <= '1';
--weCr1 <= '1';
--else
--weCb1 <= '0';
--weCr1 <= '0';
end if;
weY1 <= '1';
weCb1 <= '1';
weCr1 <= '1';
if (LineToCompress(2 downto 0) = "111") then
if (ColumnToCompress(2 downto 0) = "111") then --we've just written pixel 64 of the block [of 64 pixels]
MakeDCT <= '1';
else
MakeDCT <= '0';
end if;
else
MakeDCT <= '0';
end if;
if (ColumnToCompress = ImgColumns) then
LineToCompress <= LineToCompress + 1;
LineAbsToCompress <= LineAbsToCompress + 1;
ColumnToCompress <= (others => '0');
else
ColumnToCompress <= ColumnToCompress + 1;
end if;
Baton := 3;
when 3 => --with this dummy cycle we give time to CompressingInt to rise, if it must, and make the following "if" work fine
weY1 <= '0';
weCb1 <= '0';
weCr1 <= '0';
MakeDCT <= '0';
Baton := 0;
end case;
--MakeDCT is rised in cycle 0, in cycle 1 it is read by the process JPEG which then rises CompressingInt
--and in cycle 2 this process reads CompressingInt='1' so that in that intermediate cycle 1 is when
--the case "when 3 =>" gets executed and the following "if", in which MakeDCT is 1 and CompressingInt is 0
--but it is going to be inverted.
if (Baton = 0 and MakeDCT = '0' and CompressingInt = '0') then --it is fine!
if (LineAbsToCompress > ImgLines) then
Compressing <= '0'; --Compression has ended, image ready
LineAbsToCompress <= (others => '0'); --absolutely incredible, without this line it will only work for the
--first image (it took me much time to debug this one, folks)
end if;
ProcessingRGB <= '0';
end if;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -