【多通道视频写】+【多通道视频读】+【图像处理】:FPGA实现
包含:图像处理代码、通道输入代码(摄像头,以太网,hdmi)、通道输出代码(以太网,hdmi,可能的pcie)、缓存管理代码
多通道读写总线管理:
多通道的AXI仲裁方法【第三版】:互联状态机 - NoNounknow - 博客园 (cnblogs.com)
多通道的AXI仲裁方法【第二版】:简易仲裁和DMA拓展优化 - NoNounknow - 博客园 (cnblogs.com)
图像处理方法:
①:伽马校正:
目的:改变图像在人眼中的亮度;
原理:O_Pixel = (I_Pixel)^(1/Gamma_value)
实现方法:查找表
伽马2.2代码:变暗
//Curve of Gamma = 2.2 module Curve_Gamma_2P2 ( input [7:0] Pre_Data, output reg [7:0] Post_Data ); always@(*) begin case(Pre_Data) 8'h00 : Post_Data = 8'h00; 8'h01 : Post_Data = 8'h00; 8'h02 : Post_Data = 8'h00; 8'h03 : Post_Data = 8'h00; 8'h04 : Post_Data = 8'h00; 8'h05 : Post_Data = 8'h00; 8'h06 : Post_Data = 8'h00; 8'h07 : Post_Data = 8'h00; 8'h08 : Post_Data = 8'h00; 8'h09 : Post_Data = 8'h00; 8'h0A : Post_Data = 8'h00; 8'h0B : Post_Data = 8'h00; 8'h0C : Post_Data = 8'h00; 8'h0D : Post_Data = 8'h00; 8'h0E : Post_Data = 8'h00; 8'h0F : Post_Data = 8'h01; 8'h10 : Post_Data = 8'h01; 8'h11 : Post_Data = 8'h01; 8'h12 : Post_Data = 8'h01; 8'h13 : Post_Data = 8'h01; 8'h14 : Post_Data = 8'h01; 8'h15 : Post_Data = 8'h01; 8'h16 : Post_Data = 8'h01; 8'h17 : Post_Data = 8'h01; 8'h18 : Post_Data = 8'h01; 8'h19 : Post_Data = 8'h02; 8'h1A : Post_Data = 8'h02; 8'h1B : Post_Data = 8'h02; 8'h1C : Post_Data = 8'h02; 8'h1D : Post_Data = 8'h02; 8'h1E : Post_Data = 8'h02; 8'h1F : Post_Data = 8'h02; 8'h20 : Post_Data = 8'h03; 8'h21 : Post_Data = 8'h03; 8'h22 : Post_Data = 8'h03; 8'h23 : Post_Data = 8'h03; 8'h24 : Post_Data = 8'h03; 8'h25 : Post_Data = 8'h04; 8'h26 : Post_Data = 8'h04; 8'h27 : Post_Data = 8'h04; 8'h28 : Post_Data = 8'h04; 8'h29 : Post_Data = 8'h05; 8'h2A : Post_Data = 8'h05; 8'h2B : Post_Data = 8'h05; 8'h2C : Post_Data = 8'h05; 8'h2D : Post_Data = 8'h06; 8'h2E : Post_Data = 8'h06; 8'h2F : Post_Data = 8'h06; 8'h30 : Post_Data = 8'h06; 8'h31 : Post_Data = 8'h07; 8'h32 : Post_Data = 8'h07; 8'h33 : Post_Data = 8'h07; 8'h34 : Post_Data = 8'h08; 8'h35 : Post_Data = 8'h08; 8'h36 : Post_Data = 8'h08; 8'h37 : Post_Data = 8'h09; 8'h38 : Post_Data = 8'h09; 8'h39 : Post_Data = 8'h09; 8'h3A : Post_Data = 8'h0A; 8'h3B : Post_Data = 8'h0A; 8'h3C : Post_Data = 8'h0B; 8'h3D : Post_Data = 8'h0B; 8'h3E : Post_Data = 8'h0B; 8'h3F : Post_Data = 8'h0C; 8'h40 : Post_Data = 8'h0C; 8'h41 : Post_Data = 8'h0D; 8'h42 : Post_Data = 8'h0D; 8'h43 : Post_Data = 8'h0D; 8'h44 : Post_Data = 8'h0E; 8'h45 : Post_Data = 8'h0E; 8'h46 : Post_Data = 8'h0F; 8'h47 : Post_Data = 8'h0F; 8'h48 : Post_Data = 8'h10; 8'h49 : Post_Data = 8'h10; 8'h4A : Post_Data = 8'h11; 8'h4B : Post_Data = 8'h11; 8'h4C : Post_Data = 8'h12; 8'h4D : Post_Data = 8'h12; 8'h4E : Post_Data = 8'h13; 8'h4F : Post_Data = 8'h13; 8'h50 : Post_Data = 8'h14; 8'h51 : Post_Data = 8'h14; 8'h52 : Post_Data = 8'h15; 8'h53 : Post_Data = 8'h16; 8'h54 : Post_Data = 8'h16; 8'h55 : Post_Data = 8'h17; 8'h56 : Post_Data = 8'h17; 8'h57 : Post_Data = 8'h18; 8'h58 : Post_Data = 8'h19; 8'h59 : Post_Data = 8'h19; 8'h5A : Post_Data = 8'h1A; 8'h5B : Post_Data = 8'h1A; 8'h5C : Post_Data = 8'h1B; 8'h5D : Post_Data = 8'h1C; 8'h5E : Post_Data = 8'h1C; 8'h5F : Post_Data = 8'h1D; 8'h60 : Post_Data = 8'h1E; 8'h61 : Post_Data = 8'h1E; 8'h62 : Post_Data = 8'h1F; 8'h63 : Post_Data = 8'h20; 8'h64 : Post_Data = 8'h21; 8'h65 : Post_Data = 8'h21; 8'h66 : Post_Data = 8'h22; 8'h67 : Post_Data = 8'h23; 8'h68 : Post_Data = 8'h23; 8'h69 : Post_Data = 8'h24; 8'h6A : Post_Data = 8'h25; 8'h6B : Post_Data = 8'h26; 8'h6C : Post_Data = 8'h27; 8'h6D : Post_Data = 8'h27; 8'h6E : Post_Data = 8'h28; 8'h6F : Post_Data = 8'h29; 8'h70 : Post_Data = 8'h2A; 8'h71 : Post_Data = 8'h2B; 8'h72 : Post_Data = 8'h2B; 8'h73 : Post_Data = 8'h2C; 8'h74 : Post_Data = 8'h2D; 8'h75 : Post_Data = 8'h2E; 8'h76 : Post_Data = 8'h2F; 8'h77 : Post_Data = 8'h30; 8'h78 : Post_Data = 8'h31; 8'h79 : Post_Data = 8'h31; 8'h7A : Post_Data = 8'h32; 8'h7B : Post_Data = 8'h33; 8'h7C : Post_Data = 8'h34; 8'h7D : Post_Data = 8'h35; 8'h7E : Post_Data = 8'h36; 8'h7F : Post_Data = 8'h37; 8'h80 : Post_Data = 8'h38; 8'h81 : Post_Data = 8'h39; 8'h82 : Post_Data = 8'h3A; 8'h83 : Post_Data = 8'h3B; 8'h84 : Post_Data = 8'h3C; 8'h85 : Post_Data = 8'h3D; 8'h86 : Post_Data = 8'h3E; 8'h87 : Post_Data = 8'h3F; 8'h88 : Post_Data = 8'h40; 8'h89 : Post_Data = 8'h41; 8'h8A : Post_Data = 8'h42; 8'h8B : Post_Data = 8'h43; 8'h8C : Post_Data = 8'h44; 8'h8D : Post_Data = 8'h45; 8'h8E : Post_Data = 8'h46; 8'h8F : Post_Data = 8'h47; 8'h90 : Post_Data = 8'h49; 8'h91 : Post_Data = 8'h4A; 8'h92 : Post_Data = 8'h4B; 8'h93 : Post_Data = 8'h4C; 8'h94 : Post_Data = 8'h4D; 8'h95 : Post_Data = 8'h4E; 8'h96 : Post_Data = 8'h4F; 8'h97 : Post_Data = 8'h51; 8'h98 : Post_Data = 8'h52; 8'h99 : Post_Data = 8'h53; 8'h9A : Post_Data = 8'h54; 8'h9B : Post_Data = 8'h55; 8'h9C : Post_Data = 8'h57; 8'h9D : Post_Data = 8'h58; 8'h9E : Post_Data = 8'h59; 8'h9F : Post_Data = 8'h5A; 8'hA0 : Post_Data = 8'h5B; 8'hA1 : Post_Data = 8'h5D; 8'hA2 : Post_Data = 8'h5E; 8'hA3 : Post_Data = 8'h5F; 8'hA4 : Post_Data = 8'h61; 8'hA5 : Post_Data = 8'h62; 8'hA6 : Post_Data = 8'h63; 8'hA7 : Post_Data = 8'h64; 8'hA8 : Post_Data = 8'h66; 8'hA9 : Post_Data = 8'h67; 8'hAA : Post_Data = 8'h69; 8'hAB : Post_Data = 8'h6A; 8'hAC : Post_Data = 8'h6B; 8'hAD : Post_Data = 8'h6D; 8'hAE : Post_Data = 8'h6E; 8'hAF : Post_Data = 8'h6F; 8'hB0 : Post_Data = 8'h71; 8'hB1 : Post_Data = 8'h72; 8'hB2 : Post_Data = 8'h74; 8'hB3 : Post_Data = 8'h75; 8'hB4 : Post_Data = 8'h77; 8'hB5 : Post_Data = 8'h78; 8'hB6 : Post_Data = 8'h79; 8'hB7 : Post_Data = 8'h7B; 8'hB8 : Post_Data = 8'h7C; 8'hB9 : Post_Data = 8'h7E; 8'hBA : Post_Data = 8'h7F; 8'hBB : Post_Data = 8'h81; 8'hBC : Post_Data = 8'h82; 8'hBD : Post_Data = 8'h84; 8'hBE : Post_Data = 8'h85; 8'hBF : Post_Data = 8'h87; 8'hC0 : Post_Data = 8'h89; 8'hC1 : Post_Data = 8'h8A; 8'hC2 : Post_Data = 8'h8C; 8'hC3 : Post_Data = 8'h8D; 8'hC4 : Post_Data = 8'h8F; 8'hC5 : Post_Data = 8'h91; 8'hC6 : Post_Data = 8'h92; 8'hC7 : Post_Data = 8'h94; 8'hC8 : Post_Data = 8'h95; 8'hC9 : Post_Data = 8'h97; 8'hCA : Post_Data = 8'h99; 8'hCB : Post_Data = 8'h9A; 8'hCC : Post_Data = 8'h9C; 8'hCD : Post_Data = 8'h9E; 8'hCE : Post_Data = 8'h9F; 8'hCF : Post_Data = 8'hA1; 8'hD0 : Post_Data = 8'hA3; 8'hD1 : Post_Data = 8'hA5; 8'hD2 : Post_Data = 8'hA6; 8'hD3 : Post_Data = 8'hA8; 8'hD4 : Post_Data = 8'hAA; 8'hD5 : Post_Data = 8'hAC; 8'hD6 : Post_Data = 8'hAD; 8'hD7 : Post_Data = 8'hAF; 8'hD8 : Post_Data = 8'hB1; 8'hD9 : Post_Data = 8'hB3; 8'hDA : Post_Data = 8'hB5; 8'hDB : Post_Data = 8'hB6; 8'hDC : Post_Data = 8'hB8; 8'hDD : Post_Data = 8'hBA; 8'hDE : Post_Data = 8'hBC; 8'hDF : Post_Data = 8'hBE; 8'hE0 : Post_Data = 8'hC0; 8'hE1 : Post_Data = 8'hC2; 8'hE2 : Post_Data = 8'hC4; 8'hE3 : Post_Data = 8'hC5; 8'hE4 : Post_Data = 8'hC7; 8'hE5 : Post_Data = 8'hC9; 8'hE6 : Post_Data = 8'hCB; 8'hE7 : Post_Data = 8'hCD; 8'hE8 : Post_Data = 8'hCF; 8'hE9 : Post_Data = 8'hD1; 8'hEA : Post_Data = 8'hD3; 8'hEB : Post_Data = 8'hD5; 8'hEC : Post_Data = 8'hD7; 8'hED : Post_Data = 8'hD9; 8'hEE : Post_Data = 8'hDB; 8'hEF : Post_Data = 8'hDD; 8'hF0 : Post_Data = 8'hDF; 8'hF1 : Post_Data = 8'hE1; 8'hF2 : Post_Data = 8'hE3; 8'hF3 : Post_Data = 8'hE5; 8'hF4 : Post_Data = 8'hE7; 8'hF5 : Post_Data = 8'hEA; 8'hF6 : Post_Data = 8'hEC; 8'hF7 : Post_Data = 8'hEE; 8'hF8 : Post_Data = 8'hF0; 8'hF9 : Post_Data = 8'hF2; 8'hFA : Post_Data = 8'hF4; 8'hFB : Post_Data = 8'hF6; 8'hFC : Post_Data = 8'hF8; 8'hFD : Post_Data = 8'hFB; 8'hFE : Post_Data = 8'hFD; 8'hFF : Post_Data = 8'hFF; endcase end endmodule
伽马0.6代码:变亮
//Curve of Gamma = 0.6 module Gamma_06_Period ( input wire [7:0] Pre_Data , input wire Pre_clk , input wire Pre_Rst_n , input wire Pre_DE , input wire Pre_Vsync , input wire Pre_Hsync , output reg Post_DE , output reg Post_Vsync , output reg Post_Hsync , output reg [7:0] Post_Data ); always@(posedge Pre_clk) begin Post_DE <= Pre_DE ; Post_Vsync <= Pre_Vsync ; Post_Hsync <= Pre_Hsync ; end always@(posedge Pre_clk) if(Pre_Rst_n == 1'b0) begin Post_Data <= 8'h00; end else begin case(Pre_Data) 8'h00 : Post_Data = 8'h00; 8'h01 : Post_Data = 8'h09; 8'h02 : Post_Data = 8'h0E; 8'h03 : Post_Data = 8'h12; 8'h04 : Post_Data = 8'h15; 8'h05 : Post_Data = 8'h18; 8'h06 : Post_Data = 8'h1B; 8'h07 : Post_Data = 8'h1D; 8'h08 : Post_Data = 8'h20; 8'h09 : Post_Data = 8'h22; 8'h0A : Post_Data = 8'h25; 8'h0B : Post_Data = 8'h27; 8'h0C : Post_Data = 8'h29; 8'h0D : Post_Data = 8'h2B; 8'h0E : Post_Data = 8'h2D; 8'h0F : Post_Data = 8'h2F; 8'h10 : Post_Data = 8'h30; 8'h11 : Post_Data = 8'h32; 8'h12 : Post_Data = 8'h34; 8'h13 : Post_Data = 8'h36; 8'h14 : Post_Data = 8'h37; 8'h15 : Post_Data = 8'h39; 8'h16 : Post_Data = 8'h3B; 8'h17 : Post_Data = 8'h3C; 8'h18 : Post_Data = 8'h3E; 8'h19 : Post_Data = 8'h3F; 8'h1A : Post_Data = 8'h41; 8'h1B : Post_Data = 8'h42; 8'h1C : Post_Data = 8'h44; 8'h1D : Post_Data = 8'h45; 8'h1E : Post_Data = 8'h47; 8'h1F : Post_Data = 8'h48; 8'h20 : Post_Data = 8'h49; 8'h21 : Post_Data = 8'h4B; 8'h22 : Post_Data = 8'h4C; 8'h23 : Post_Data = 8'h4D; 8'h24 : Post_Data = 8'h4F; 8'h25 : Post_Data = 8'h50; 8'h26 : Post_Data = 8'h51; 8'h27 : Post_Data = 8'h53; 8'h28 : Post_Data = 8'h54; 8'h29 : Post_Data = 8'h55; 8'h2A : Post_Data = 8'h56; 8'h2B : Post_Data = 8'h58; 8'h2C : Post_Data = 8'h59; 8'h2D : Post_Data = 8'h5A; 8'h2E : Post_Data = 8'h5B; 8'h2F : Post_Data = 8'h5C; 8'h30 : Post_Data = 8'h5E; 8'h31 : Post_Data = 8'h5F; 8'h32 : Post_Data = 8'h60; 8'h33 : Post_Data = 8'h61; 8'h34 : Post_Data = 8'h62; 8'h35 : Post_Data = 8'h63; 8'h36 : Post_Data = 8'h64; 8'h37 : Post_Data = 8'h66; 8'h38 : Post_Data = 8'h67; 8'h39 : Post_Data = 8'h68; 8'h3A : Post_Data = 8'h69; 8'h3B : Post_Data = 8'h6A; 8'h3C : Post_Data = 8'h6B; 8'h3D : Post_Data = 8'h6C; 8'h3E : Post_Data = 8'h6D; 8'h3F : Post_Data = 8'h6E; 8'h40 : Post_Data = 8'h6F; 8'h41 : Post_Data = 8'h70; 8'h42 : Post_Data = 8'h71; 8'h43 : Post_Data = 8'h72; 8'h44 : Post_Data = 8'h73; 8'h45 : Post_Data = 8'h74; 8'h46 : Post_Data = 8'h75; 8'h47 : Post_Data = 8'h76; 8'h48 : Post_Data = 8'h77; 8'h49 : Post_Data = 8'h78; 8'h4A : Post_Data = 8'h79; 8'h4B : Post_Data = 8'h7A; 8'h4C : Post_Data = 8'h7B; 8'h4D : Post_Data = 8'h7C; 8'h4E : Post_Data = 8'h7D; 8'h4F : Post_Data = 8'h7E; 8'h50 : Post_Data = 8'h7F; 8'h51 : Post_Data = 8'h80; 8'h52 : Post_Data = 8'h81; 8'h53 : Post_Data = 8'h82; 8'h54 : Post_Data = 8'h83; 8'h55 : Post_Data = 8'h84; 8'h56 : Post_Data = 8'h85; 8'h57 : Post_Data = 8'h86; 8'h58 : Post_Data = 8'h87; 8'h59 : Post_Data = 8'h88; 8'h5A : Post_Data = 8'h89; 8'h5B : Post_Data = 8'h89; 8'h5C : Post_Data = 8'h8A; 8'h5D : Post_Data = 8'h8B; 8'h5E : Post_Data = 8'h8C; 8'h5F : Post_Data = 8'h8D; 8'h60 : Post_Data = 8'h8E; 8'h61 : Post_Data = 8'h8F; 8'h62 : Post_Data = 8'h90; 8'h63 : Post_Data = 8'h91; 8'h64 : Post_Data = 8'h91; 8'h65 : Post_Data = 8'h92; 8'h66 : Post_Data = 8'h93; 8'h67 : Post_Data = 8'h94; 8'h68 : Post_Data = 8'h95; 8'h69 : Post_Data = 8'h96; 8'h6A : Post_Data = 8'h97; 8'h6B : Post_Data = 8'h97; 8'h6C : Post_Data = 8'h98; 8'h6D : Post_Data = 8'h99; 8'h6E : Post_Data = 8'h9A; 8'h6F : Post_Data = 8'h9B; 8'h70 : Post_Data = 8'h9C; 8'h71 : Post_Data = 8'h9C; 8'h72 : Post_Data = 8'h9D; 8'h73 : Post_Data = 8'h9E; 8'h74 : Post_Data = 8'h9F; 8'h75 : Post_Data = 8'hA0; 8'h76 : Post_Data = 8'hA1; 8'h77 : Post_Data = 8'hA1; 8'h78 : Post_Data = 8'hA2; 8'h79 : Post_Data = 8'hA3; 8'h7A : Post_Data = 8'hA4; 8'h7B : Post_Data = 8'hA5; 8'h7C : Post_Data = 8'hA5; 8'h7D : Post_Data = 8'hA6; 8'h7E : Post_Data = 8'hA7; 8'h7F : Post_Data = 8'hA8; 8'h80 : Post_Data = 8'hA9; 8'h81 : Post_Data = 8'hA9; 8'h82 : Post_Data = 8'hAA; 8'h83 : Post_Data = 8'hAB; 8'h84 : Post_Data = 8'hAC; 8'h85 : Post_Data = 8'hAD; 8'h86 : Post_Data = 8'hAD; 8'h87 : Post_Data = 8'hAE; 8'h88 : Post_Data = 8'hAF; 8'h89 : Post_Data = 8'hB0; 8'h8A : Post_Data = 8'hB0; 8'h8B : Post_Data = 8'hB1; 8'h8C : Post_Data = 8'hB2; 8'h8D : Post_Data = 8'hB3; 8'h8E : Post_Data = 8'hB3; 8'h8F : Post_Data = 8'hB4; 8'h90 : Post_Data = 8'hB5; 8'h91 : Post_Data = 8'hB6; 8'h92 : Post_Data = 8'hB6; 8'h93 : Post_Data = 8'hB7; 8'h94 : Post_Data = 8'hB8; 8'h95 : Post_Data = 8'hB9; 8'h96 : Post_Data = 8'hB9; 8'h97 : Post_Data = 8'hBA; 8'h98 : Post_Data = 8'hBB; 8'h99 : Post_Data = 8'hBC; 8'h9A : Post_Data = 8'hBC; 8'h9B : Post_Data = 8'hBD; 8'h9C : Post_Data = 8'hBE; 8'h9D : Post_Data = 8'hBF; 8'h9E : Post_Data = 8'hBF; 8'h9F : Post_Data = 8'hC0; 8'hA0 : Post_Data = 8'hC1; 8'hA1 : Post_Data = 8'hC2; 8'hA2 : Post_Data = 8'hC2; 8'hA3 : Post_Data = 8'hC3; 8'hA4 : Post_Data = 8'hC4; 8'hA5 : Post_Data = 8'hC4; 8'hA6 : Post_Data = 8'hC5; 8'hA7 : Post_Data = 8'hC6; 8'hA8 : Post_Data = 8'hC7; 8'hA9 : Post_Data = 8'hC7; 8'hAA : Post_Data = 8'hC8; 8'hAB : Post_Data = 8'hC9; 8'hAC : Post_Data = 8'hC9; 8'hAD : Post_Data = 8'hCA; 8'hAE : Post_Data = 8'hCB; 8'hAF : Post_Data = 8'hCB; 8'hB0 : Post_Data = 8'hCC; 8'hB1 : Post_Data = 8'hCD; 8'hB2 : Post_Data = 8'hCE; 8'hB3 : Post_Data = 8'hCE; 8'hB4 : Post_Data = 8'hCF; 8'hB5 : Post_Data = 8'hD0; 8'hB6 : Post_Data = 8'hD0; 8'hB7 : Post_Data = 8'hD1; 8'hB8 : Post_Data = 8'hD2; 8'hB9 : Post_Data = 8'hD2; 8'hBA : Post_Data = 8'hD3; 8'hBB : Post_Data = 8'hD4; 8'hBC : Post_Data = 8'hD4; 8'hBD : Post_Data = 8'hD5; 8'hBE : Post_Data = 8'hD6; 8'hBF : Post_Data = 8'hD6; 8'hC0 : Post_Data = 8'hD7; 8'hC1 : Post_Data = 8'hD8; 8'hC2 : Post_Data = 8'hD8; 8'hC3 : Post_Data = 8'hD9; 8'hC4 : Post_Data = 8'hDA; 8'hC5 : Post_Data = 8'hDA; 8'hC6 : Post_Data = 8'hDB; 8'hC7 : Post_Data = 8'hDC; 8'hC8 : Post_Data = 8'hDC; 8'hC9 : Post_Data = 8'hDD; 8'hCA : Post_Data = 8'hDE; 8'hCB : Post_Data = 8'hDE; 8'hCC : Post_Data = 8'hDF; 8'hCD : Post_Data = 8'hE0; 8'hCE : Post_Data = 8'hE0; 8'hCF : Post_Data = 8'hE1; 8'hD0 : Post_Data = 8'hE2; 8'hD1 : Post_Data = 8'hE2; 8'hD2 : Post_Data = 8'hE3; 8'hD3 : Post_Data = 8'hE4; 8'hD4 : Post_Data = 8'hE4; 8'hD5 : Post_Data = 8'hE5; 8'hD6 : Post_Data = 8'hE6; 8'hD7 : Post_Data = 8'hE6; 8'hD8 : Post_Data = 8'hE7; 8'hD9 : Post_Data = 8'hE7; 8'hDA : Post_Data = 8'hE8; 8'hDB : Post_Data = 8'hE9; 8'hDC : Post_Data = 8'hE9; 8'hDD : Post_Data = 8'hEA; 8'hDE : Post_Data = 8'hEB; 8'hDF : Post_Data = 8'hEB; 8'hE0 : Post_Data = 8'hEC; 8'hE1 : Post_Data = 8'hED; 8'hE2 : Post_Data = 8'hED; 8'hE3 : Post_Data = 8'hEE; 8'hE4 : Post_Data = 8'hEE; 8'hE5 : Post_Data = 8'hEF; 8'hE6 : Post_Data = 8'hF0; 8'hE7 : Post_Data = 8'hF0; 8'hE8 : Post_Data = 8'hF1; 8'hE9 : Post_Data = 8'hF2; 8'hEA : Post_Data = 8'hF2; 8'hEB : Post_Data = 8'hF3; 8'hEC : Post_Data = 8'hF3; 8'hED : Post_Data = 8'hF4; 8'hEE : Post_Data = 8'hF5; 8'hEF : Post_Data = 8'hF5; 8'hF0 : Post_Data = 8'hF6; 8'hF1 : Post_Data = 8'hF7; 8'hF2 : Post_Data = 8'hF7; 8'hF3 : Post_Data = 8'hF8; 8'hF4 : Post_Data = 8'hF8; 8'hF5 : Post_Data = 8'hF9; 8'hF6 : Post_Data = 8'hFA; 8'hF7 : Post_Data = 8'hFA; 8'hF8 : Post_Data = 8'hFB; 8'hF9 : Post_Data = 8'hFB; 8'hFA : Post_Data = 8'hFC; 8'hFB : Post_Data = 8'hFD; 8'hFC : Post_Data = 8'hFD; 8'hFD : Post_Data = 8'hFE; 8'hFE : Post_Data = 8'hFE; 8'hFF : Post_Data = 8'hFF; endcase end endmodule
②:白平衡:
原理:图像处理算法:白平衡、除法器、乘法器~笔记-CSDN博客
具体原理:
(1): Ksum = Rsum + Gsum + Bsum
(2): Kaver = Ksum/[(Image_Size)*(Channel_Num)]
Raver = Rsum/Image_Size
Gaver = Gsum/Image_Size
Baver = Bsum/Image_Size
(3): Rgain = Kaver / Raver
Ggain = Kaver / Gaver
Bgain = Kaver / Baver
(4):
O_Rchannel_Pixel = I_Rchannel_Pixel * Rgain
O_Gchannel_Pixel = I_Gchannel_Pixel * Ggain
O_Bchannel_Pixel = I_Bchannel_Pixel * Bgain
代码:
module White_Balance #( parameter I_w = 1920, parameter I_h = 1080, parameter Channel_Num = 3 )( input wire Pre_CLK , input wire Pre_Rst , input wire Pre_Vsync , input wire Pre_de , input wire [7:0] Pre_Pixel_R , input wire [7:0] Pre_Pixel_G , input wire [7:0] Pre_Pixel_B , output wire Post_Vsync , output wire Post_de , output wire [7:0] Post_Pixel_R , output wire [7:0] Post_Pixel_G , output wire [7:0] Post_Pixel_B , output wire [23:0] Post_Pixel_Total ); //========================================= Define Ports =========================================// localparam Shift_Num = 21; localparam Kaver_Divisor = I_w*I_h*Channel_Num; reg [2:0] Delay_Pre_de ; wire Pose_Pre_de ; wire Nege_Pre_de ; reg r_Pre_Vsync ; wire Pose_Pre_Vsync ; wire Nege_Pre_Vsync ; reg [31:0] Red_Sum ; reg [31:0] Green_Sum ; reg [31:0] Blue_Sum ; reg [32:0] K_Sum ; reg [10:0] Aver_R ; reg [10:0] Aver_G ; reg [10:0] Aver_B ; reg [32:0] Aver_K ; reg Calcu_Kaver ; wire [63 : 0] Kaver_Result ; wire Kaver_vaild ; //Pixel*Kaver wire [18 : 0] Multi_RxKaver ; wire [18 : 0] Multi_GxKaver ; wire [18 : 0] Multi_BxKaver ; //Pixel*Kaver/Pixel_aver wire [39 : 0] Div_RxKaver_D_Raver ; wire Div_RxKaver_vaild ; wire [39 : 0] Div_GxKaver_D_Gaver ; wire Div_GxKaver_vaild ; wire [39 : 0] Div_BxKaver_D_Baver ; wire Div_BxKaver_vaild ; wire [18:0] Quo_R_Pixel ; wire [18:0] Quo_G_Pixel ; wire [18:0] Quo_B_Pixel ; reg r_Post_de ; reg [7:0] r_Post_Pixel_R ; reg [7:0] r_Post_Pixel_G ; reg [7:0] r_Post_Pixel_B ; //========================================= Define Ports =========================================// always @(posedge Pre_CLK) begin Delay_Pre_de <= {Delay_Pre_de[1:0],Pre_de}; r_Pre_Vsync <= Pre_Vsync; end assign Pose_Pre_Vsync = (Pre_Vsync == 1'b1)&&(r_Pre_Vsync == 1'b0); assign Nege_Pre_Vsync = (Pre_Vsync == 1'b0)&&(r_Pre_Vsync == 1'b1); //Calcu_Kaver always @(posedge Pre_CLK) begin if(Pre_Rst == 1'b1) begin Calcu_Kaver <= 1'b0; end else if(Nege_Pre_Vsync == 1'b1) begin Calcu_Kaver <= 1'b1; end else begin Calcu_Kaver <= 1'b0; end end //Pixel Sum always @(posedge Pre_CLK) begin if(Pre_Rst == 1'b1) begin Red_Sum <= 'd0; Green_Sum <= 'd0; Blue_Sum <= 'd0; K_Sum <= 'd0; end else if(Calcu_Kaver == 1'b1) begin Red_Sum <= 'd0; Green_Sum <= 'd0; Blue_Sum <= 'd0; K_Sum <= 'd0; end else if(Pre_de == 1'b1) begin Red_Sum <= Red_Sum + Pre_Pixel_R; Green_Sum <= Green_Sum + Pre_Pixel_G; Blue_Sum <= Blue_Sum + Pre_Pixel_B; K_Sum <= K_Sum + Pre_Pixel_R + Pre_Pixel_G + Pre_Pixel_B; end else begin Red_Sum <= Red_Sum ; Green_Sum <= Green_Sum; Blue_Sum <= Blue_Sum ; K_Sum <= K_Sum ; end end //Div Pipeline = 16 Div_Kaver Kaver_Comput_33D23 ( .aclk ( Pre_CLK ), // input wire aclk .aresetn ( !Pre_Rst ), // input wire aresetn .s_axis_divisor_tvalid ( Calcu_Kaver ), // input wire s_axis_divisor_tvalid .s_axis_divisor_tdata ( Kaver_Divisor ), // input wire [23 : 0] s_axis_divisor_tdata .s_axis_dividend_tvalid( Calcu_Kaver ), // input wire s_axis_dividend_tvalid .s_axis_dividend_tdata ( K_Sum ), // input wire [39 : 0] s_axis_dividend_tdata .m_axis_dout_tvalid ( Kaver_vaild ), // output wire m_axis_dout_tvalid .m_axis_dout_tdata ( Kaver_Result ) // output wire [63 : 0] m_axis_dout_tdata [56:24] ); //aver always @(posedge Pre_CLK) begin if(Pre_Rst == 1'b1) begin Aver_R <= 'd0; Aver_G <= 'd0; Aver_B <= 'd0; end else if(Calcu_Kaver == 1'b1) begin Aver_R <= Red_Sum[21+:11] ; Aver_G <= Green_Sum[21+:11]; Aver_B <= Blue_Sum[21+:11] ; end else begin Aver_R <= Aver_R; Aver_G <= Aver_G; Aver_B <= Aver_B; end end always @(posedge Pre_CLK) begin if(Pre_Rst == 1'b1) begin Aver_K <= 'd0; end else if(Kaver_vaild == 1'b1) begin Aver_K <= Kaver_Result[56:24]; end else begin Aver_K <= Aver_K; end end //Multi Pipeline = 3 //Red Pixel_Multi_Kaver Pixel_Multi_Kaver_Red_8x11 ( .CLK ( Pre_CLK ), // input wire CLK .A ( Pre_Pixel_R ), // input wire [7 : 0] .B ( Aver_K[10:0] ), // input wire [10 : 0] .P ( Multi_RxKaver ) // output wire [18 : 0] ); //Div Pipeline = 16 Div_GenGain Div_GenGain_Red ( .aclk ( Pre_CLK ), // input wire aclk .aresetn ( !Pre_Rst ), // input wire aresetn .s_axis_divisor_tvalid ( Delay_Pre_de[2] ), // input wire s_axis_divisor_tvalid .s_axis_divisor_tdata ( Aver_R ), // input wire [15 : 0] s_axis_divisor_tdata .s_axis_dividend_tvalid ( Delay_Pre_de[2] ), // input wire s_axis_dividend_tvalid .s_axis_dividend_tdata ( Multi_RxKaver ), // input wire [23 : 0] s_axis_dividend_tdata .m_axis_dout_tvalid ( Div_RxKaver_vaild ), // output wire m_axis_dout_tvalid .m_axis_dout_tdata ( Div_RxKaver_D_Raver ) // output wire [39 : 0] m_axis_dout_tdata [34:16] ); //Gre Pixel_Multi_Kaver Pixel_Multi_Kaver_Gre_8x11 ( .CLK ( Pre_CLK ), // input wire CLK .A ( Pre_Pixel_G ), // input wire [7 : 0] .B ( Aver_K[10:0] ), // input wire [10 : 0] .P ( Multi_GxKaver ) // output wire [18 : 0] ); Div_GenGain Div_GenGain_Gre ( .aclk ( Pre_CLK ), // input wire aclk .aresetn ( !Pre_Rst ), // input wire aresetn .s_axis_divisor_tvalid ( Delay_Pre_de[2] ), // input wire s_axis_divisor_tvalid .s_axis_divisor_tdata ( Aver_G ), // input wire [15 : 0] s_axis_divisor_tdata .s_axis_dividend_tvalid ( Delay_Pre_de[2] ), // input wire s_axis_dividend_tvalid .s_axis_dividend_tdata ( Multi_GxKaver ), // input wire [23 : 0] s_axis_dividend_tdata .m_axis_dout_tvalid ( Div_GxKaver_vaild ), // output wire m_axis_dout_tvalid .m_axis_dout_tdata ( Div_GxKaver_D_Gaver ) // output wire [39 : 0] m_axis_dout_tdata ); //Blue Pixel_Multi_Kaver Pixel_Multi_Kaver_Blu_8x11 ( .CLK ( Pre_CLK ), // input wire CLK .A ( Pre_Pixel_B ), // input wire [7 : 0] .B ( Aver_K[10:0] ), // input wire [10 : 0] .P ( Multi_BxKaver ) // output wire [18 : 0] ); Div_GenGain Div_GenGain_Blu ( .aclk ( Pre_CLK ), // input wire aclk .aresetn ( !Pre_Rst ), // input wire aresetn .s_axis_divisor_tvalid ( Delay_Pre_de[2] ), // input wire s_axis_divisor_tvalid .s_axis_divisor_tdata ( Aver_B ), // input wire [15 : 0] s_axis_divisor_tdata .s_axis_dividend_tvalid ( Delay_Pre_de[2] ), // input wire s_axis_dividend_tvalid .s_axis_dividend_tdata ( Multi_BxKaver ), // input wire [23 : 0] s_axis_dividend_tdata .m_axis_dout_tvalid ( Div_BxKaver_vaild ), // output wire m_axis_dout_tvalid .m_axis_dout_tdata ( Div_BxKaver_D_Baver ) // output wire [39 : 0] m_axis_dout_tdata ); assign Quo_R_Pixel = Div_RxKaver_D_Raver[34:16]; assign Quo_G_Pixel = Div_GxKaver_D_Gaver[34:16]; assign Quo_B_Pixel = Div_BxKaver_D_Baver[34:16]; always @(posedge Pre_CLK) begin if(Pre_Rst == 1'b1) begin r_Post_Pixel_R <= 'd0; end else if(Div_RxKaver_vaild == 1'b1) begin if(Quo_R_Pixel > 8'd255) begin r_Post_Pixel_R <= 8'd255; end else begin r_Post_Pixel_R <= Quo_R_Pixel[7:0]; end end else begin r_Post_Pixel_R <= r_Post_Pixel_R; end end always @(posedge Pre_CLK) begin if(Pre_Rst == 1'b1) begin r_Post_Pixel_G <= 'd0; end else if(Div_GxKaver_vaild == 1'b1) begin if(Quo_G_Pixel > 8'd255) begin r_Post_Pixel_G <= 8'd255; end else begin r_Post_Pixel_G <= Quo_G_Pixel[7:0]; end end else begin r_Post_Pixel_G <= r_Post_Pixel_G; end end always @(posedge Pre_CLK) begin if(Pre_Rst == 1'b1) begin r_Post_Pixel_B <= 'd0; end else if(Div_BxKaver_vaild == 1'b1) begin if(Quo_B_Pixel > 8'd255) begin r_Post_Pixel_B <= 8'd255; end else begin r_Post_Pixel_B <= Quo_B_Pixel[7:0]; end end else begin r_Post_Pixel_B <= r_Post_Pixel_B; end end always @(posedge Pre_CLK) begin if(Pre_Rst == 1'b1) begin r_Post_de <= 1'b0; end else if(Div_BxKaver_vaild == 1'b1) begin r_Post_de <= 1'b1; end else begin r_Post_de <= 1'b0; end end assign Post_Vsync = r_Pre_Vsync ; assign Post_de = r_Post_de; assign Post_Pixel_R = r_Post_Pixel_R; assign Post_Pixel_G = r_Post_Pixel_G; assign Post_Pixel_B = r_Post_Pixel_B; assign Post_Pixel_Total = {r_Post_Pixel_R,r_Post_Pixel_G,r_Post_Pixel_B}; // ila_0 White_ILA ( // .clk(Pre_CLK), // .probe0( Pre_de ),//1 // .probe1( Pre_Vsync ),//1 // .probe2( Calcu_Kaver ),//1 // .probe3( Pre_Pixel_R ),//8 // .probe4( Pre_Pixel_G ),//8 // .probe5( Pre_Pixel_B ),//8 // .probe6( Kaver_vaild ),//1 // .probe7( Aver_R ),//11 // .probe8( Aver_G ),//11 // .probe9( Aver_B ),//11 // .probe10( K_Sum ),//33 // .probe11( Aver_K ),//33 // .probe12( Multi_RxKaver ),//19 // .probe13( Multi_GxKaver ),//19 // .probe14( Multi_BxKaver ),//19 // .probe15( Delay_Pre_de ),//3 // .probe16( Post_Pixel_R ),//8 // .probe17( Post_Pixel_G ),//8 // .probe18( Post_Pixel_B ),//8 // .probe19( Post_de ),//1 // .probe20( Div_BxKaver_vaild ) //1 // ); endmodule
输入通道管理:
(1)相机输入通道
1.相机配置操作和输入时钟处理:
相机配置:Sony IMX222相机的配置和解析-CSDN博客
MIPI配置的OV5640的使用_mc5640 mipi-CSDN博客
输入时钟:为输入时钟接PLL,偏移45°以后再接入模块,保证准确采集数据。
2.输入信号的数据解析:
解析情况1:
串行:DVP格式
原理心得:
并行LVDS:MIPI格式
1.原理:
手写MIPI(一):MIPI-CSI-2 RAW10笔记_mipi csi协议-CSDN博客
2.代码:整体思路:
(1):dphy:
利用IBUFD实现差分转单端,BUFD实现分频,其中需要过一次时钟增强,通过ISerdes实现串行转并行,完成dphy;
1 `timescale 1ns / 1ps 2 module Mipi_dphy_rx #( 3 Mipi_Lane_Num = 2 4 )( 5 input wire Rst_n , 6 //Mipi 7 input wire I_Mipi_phy_clk_p , 8 input wire I_Mipi_phy_clk_n , 9 input wire [1:0] I_Mipi_phy_lane_p , 10 input wire [1:0] I_Mipi_phy_lane_n , 11 12 output wire O_Mipi_CSI_Byte_CLK ,//Slow Clk 13 output wire [7:0] O_Mipi_CSI_Byte_Lane0_Data , 14 output wire [7:0] O_Mipi_CSI_Byte_Lane1_Data 15 ); 16 wire Bufd_CLK ; 17 wire Bufd_Slow_Clk ; 18 wire Buff_Clk ; 19 wire Buff_Clk_inv ; 20 wire clock_enable ; 21 //clk 22 //diff to single:clk 23 IBUFDS 24 #(.IOSTANDARD ("LVDS_25")) 25 ibufds_clk_inst 26 (.I ( I_Mipi_phy_clk_p ), 27 .IB ( I_Mipi_phy_clk_n ), 28 .O ( Bufd_CLK )); 29 30 // High Speed BUFIO clock buffer 31 BUFIO bufio_inst 32 (.O ( Buff_Clk ), 33 .I ( Bufd_CLK )); 34 35 // BUFR generates the slow clock 36 BUFR 37 #(.SIM_DEVICE ("7SERIES"), 38 .BUFR_DIVIDE("4")) 39 clkout_buf_inst 40 (.O ( Bufd_Slow_Clk ), 41 .CE ( 1'b1 ), 42 .CLR ( !Rst_n ), 43 .I ( Bufd_CLK )); 44 45 assign O_Mipi_CSI_Byte_CLK = Bufd_Slow_Clk ;//Output Slow Clk 46 assign Buff_Clk_inv = ~ Buff_Clk ; 47 assign clock_enable = 1'b1; 48 //data 49 wire [1:0] Mipi_IBUFD_Data ;//Diff data to Single data 50 wire [1:0] Mipi_IBUFD_Data_delay ; 51 wire [7:0] iserdes_q [1:0] ; 52 wire [1:0] Bitslip ; 53 assign Bitslip = 2'b00; 54 //lane0 55 //diff to single:data 56 IBUFDS 57 #(.DIFF_TERM ("FALSE"), // Differential termination 58 .IOSTANDARD ("LVDS_25")) 59 ibufds_inst_0 60 (.I ( I_Mipi_phy_lane_p[0] ), 61 .IB ( I_Mipi_phy_lane_n[0] ), 62 .O ( Mipi_IBUFD_Data[0] )); 63 64 assign Mipi_IBUFD_Data_delay = Mipi_IBUFD_Data; 65 66 ISERDESE2 67 # ( 68 .DATA_RATE ("DDR"), 69 .DATA_WIDTH (8), 70 .INTERFACE_TYPE ("NETWORKING"), 71 .DYN_CLKDIV_INV_EN ("FALSE"), 72 .DYN_CLK_INV_EN ("FALSE"), 73 .NUM_CE (2), 74 .OFB_USED ("FALSE"), 75 .IOBDELAY ("NONE"), // Use input at D to output the data on Q 76 .SERDES_MODE ("MASTER")) 77 iserdese2_master_lane0 ( 78 .Q1 ( iserdes_q [0][7] ), 79 .Q2 ( iserdes_q [0][6] ), 80 .Q3 ( iserdes_q [0][5] ), 81 .Q4 ( iserdes_q [0][4] ), 82 .Q5 ( iserdes_q [0][3] ), 83 .Q6 ( iserdes_q [0][2] ), 84 .Q7 ( iserdes_q [0][1] ), 85 .Q8 ( iserdes_q [0][0] ), 86 .SHIFTOUT1 ( ), 87 .SHIFTOUT2 ( ), 88 .BITSLIP ( Bitslip[0]), // 1-bit Invoke Bitslip. This can be used with any DATA_WIDTH, cascaded or not. 89 // The amount of BITSLIP is fixed by the DATA_WIDTH selection. 90 .CE1 ( clock_enable ), // 1-bit Clock enable input 91 .CE2 ( clock_enable ), // 1-bit Clock enable input 92 .CLK ( Buff_Clk ), // Fast source synchronous clock driven by BUFIO 93 .CLKB ( Buff_Clk_inv ), // Locally inverted fast 94 .CLKDIV ( Bufd_Slow_Clk ), // Slow clock from BUFR. 95 .CLKDIVP ( 1'b0 ), 96 .D ( Mipi_IBUFD_Data_delay[0]), // 1-bit Input signal from IOB 97 .DDLY ( 1'b0 ), // 1-bit Input from Input Delay component 98 .RST ( !Rst_n ), // 1-bit Asynchronous reset only. 99 .SHIFTIN1 ( 1'b0 ), 100 .SHIFTIN2 ( 1'b0 ), 101 // unused connections 102 .DYNCLKDIVSEL ( 1'b0 ), 103 .DYNCLKSEL ( 1'b0 ), 104 .OFB ( 1'b0 ), 105 .OCLK ( 1'b0 ), 106 .OCLKB ( 1'b0 ), 107 .O ( )); // unregistered output of ISERDESE1 108 109 //lane1 110 IBUFDS 111 #(.DIFF_TERM ("FALSE"), // Differential termination 112 .IOSTANDARD ("LVDS_25")) 113 ibufds_inst_1 114 (.I ( I_Mipi_phy_lane_p[1] ), 115 .IB ( I_Mipi_phy_lane_n[1] ), 116 .O ( Mipi_IBUFD_Data[1] )); 117 118 ISERDESE2 119 # ( 120 .DATA_RATE ("DDR"), 121 .DATA_WIDTH (8), 122 .INTERFACE_TYPE ("NETWORKING"), 123 .DYN_CLKDIV_INV_EN ("FALSE"), 124 .DYN_CLK_INV_EN ("FALSE"), 125 .NUM_CE (2), 126 .OFB_USED ("FALSE"), 127 .IOBDELAY ("NONE"), // Use input at D to output the data on Q 128 .SERDES_MODE ("MASTER")) 129 iserdese2_master_lane1 ( 130 .Q1 ( iserdes_q [1][7] ), 131 .Q2 ( iserdes_q [1][6] ), 132 .Q3 ( iserdes_q [1][5] ), 133 .Q4 ( iserdes_q [1][4] ), 134 .Q5 ( iserdes_q [1][3] ), 135 .Q6 ( iserdes_q [1][2] ), 136 .Q7 ( iserdes_q [1][1] ), 137 .Q8 ( iserdes_q [1][0] ), 138 .SHIFTOUT1 ( ), 139 .SHIFTOUT2 ( ), 140 .BITSLIP ( Bitslip[1]), // 1-bit Invoke Bitslip. This can be used with any DATA_WIDTH, cascaded or not. 141 // The amount of BITSLIP is fixed by the DATA_WIDTH selection. 142 .CE1 ( clock_enable ), // 1-bit Clock enable input 143 .CE2 ( clock_enable ), // 1-bit Clock enable input 144 .CLK ( Buff_Clk ), // Fast source synchronous clock driven by BUFIO 145 .CLKB ( Buff_Clk_inv ), // Locally inverted fast 146 .CLKDIV ( Bufd_Slow_Clk ), // Slow clock from BUFR. 147 .CLKDIVP ( 1'b0 ), 148 .D ( Mipi_IBUFD_Data_delay[1]), // 1-bit Input signal from IOB 149 .DDLY ( 1'b0 ), // 1-bit Input from Input Delay component 150 .RST ( !Rst_n ), // 1-bit Asynchronous reset only. 151 .SHIFTIN1 ( 1'b0 ), 152 .SHIFTIN2 ( 1'b0 ), 153 // unused connections 154 .DYNCLKDIVSEL ( 1'b0 ), 155 .DYNCLKSEL ( 1'b0 ), 156 .OFB ( 1'b0 ), 157 .OCLK ( 1'b0 ), 158 .OCLKB ( 1'b0 ), 159 .O ( )); // unregistered output of ISERDESE1 160 161 assign O_Mipi_CSI_Byte_Lane0_Data = iserdes_q[0]; 162 assign O_Mipi_CSI_Byte_Lane1_Data = iserdes_q[1]; 163 endmodule
(2):Byte_Align:
通过寻找SoT完成解析字的对齐;
always @(*) begin r_O_Mipi_Byte_Alignment_Data <= Concat_Byte_data_delay[Byte_Offset+:8]; end
(3):Lane_Align:
完成不同Lane之间的对齐:细节:不同Lane之前如果做了等长的PCB处理,此处不应该超过1个时钟周期的延迟,所以如果超过了,及时重新字对齐;
在Byte_Align的模块vaild到来的时候,比较不同模块的vaild先后顺序,完成对齐处理;
module Mipi_Lane_Alignment ( input wire I_CLK , input wire I_Rst_n , //Byte_Alignment_Data input wire [7:0] I_Mipi_Byte_Alignment_Data_0 , input wire I_Mipi_Byte_Alignment_Vaild_0, input wire [7:0] I_Mipi_Byte_Alignment_Data_1 , input wire I_Mipi_Byte_Alignment_Vaild_1, input wire I_Mipi_Unpacket_done , //Lane_Alignment_Data output wire [15:0] O_Mipi_Lane_Alignment_Data , output reg O_ReSearch_Offset_Lane , output wire O_Mipi_Lane_Alignment_Vaild ); //--------------------Port Define-----------------------------------------------// localparam Lane0_First = 2'b10; localparam Lane1_First = 2'b01; localparam Both_timing = 2'b11; wire Vaild_Or ; wire Vaild_And ; reg r_Vaild_Or ; wire Vaild_Or_Posedge ; reg r_Vaild_Or_Posedge; reg [15:0] r_lane0_data; reg [15:0] r_lane1_data; reg [ 1:0] Flag ; //--------------------Port Define-----------------------------------------------// //Vaild_Or assign Vaild_And = (I_Mipi_Byte_Alignment_Vaild_0) & ( I_Mipi_Byte_Alignment_Vaild_1); assign Vaild_Or = (I_Mipi_Byte_Alignment_Vaild_0) | (I_Mipi_Byte_Alignment_Vaild_1); assign Vaild_Or_Posedge = (!r_Vaild_Or) && Vaild_Or; always @(posedge I_CLK) begin r_Vaild_Or <= Vaild_Or ; r_Vaild_Or_Posedge <= Vaild_Or_Posedge; end //Data_in delay always @(posedge I_CLK) begin r_lane0_data <= {r_lane0_data[7:0], I_Mipi_Byte_Alignment_Data_0}; r_lane1_data <= {r_lane1_data[7:0], I_Mipi_Byte_Alignment_Data_1}; end always @(posedge I_CLK or negedge I_Rst_n) begin if(I_Rst_n == 1'b0) begin Flag <= 2'd0; end else if(Vaild_Or_Posedge == 1'b1) begin Flag <= {I_Mipi_Byte_Alignment_Vaild_0,I_Mipi_Byte_Alignment_Vaild_1}; end else begin Flag <= Flag; end end //O_Mipi_Lane_Alignment_Vaild reg r_O_Mipi_Lane_Alignment_Vaild; reg [15:0] r_O_Mipi_Lane_Alignment_Data ; assign O_Mipi_Lane_Alignment_Vaild = r_O_Mipi_Lane_Alignment_Vaild; assign O_Mipi_Lane_Alignment_Data = r_O_Mipi_Lane_Alignment_Data ; always @(posedge I_CLK or negedge I_Rst_n) begin if(I_Rst_n == 1'b0) begin r_O_Mipi_Lane_Alignment_Vaild <= 1'd0; end else if(I_Mipi_Unpacket_done == 1'b1) begin r_O_Mipi_Lane_Alignment_Vaild <= 1'd0; end else if(r_Vaild_Or_Posedge == 1'b1 && Vaild_And == 1'b1) begin r_O_Mipi_Lane_Alignment_Vaild <= 1'b1; end end //O_Mipi_Lane_Alignment_Data always @(*) begin case (Flag) Lane0_First:begin r_O_Mipi_Lane_Alignment_Data <= {r_lane1_data[7:0], r_lane0_data[15:8]}; end Lane1_First:begin r_O_Mipi_Lane_Alignment_Data <= {r_lane1_data[15:8], r_lane0_data[7:0]}; end Both_timing:begin r_O_Mipi_Lane_Alignment_Data <= {r_lane1_data[15:8], r_lane0_data[15:8]}; end default: begin r_O_Mipi_Lane_Alignment_Data <= {r_lane1_data[7:0], r_lane0_data[7:0]}; end endcase end always @(posedge I_CLK or negedge I_Rst_n) begin if(I_Rst_n == 'd0) begin O_ReSearch_Offset_Lane <= 1'b0; end else if(Vaild_Or_Posedge == 1'b1) begin O_ReSearch_Offset_Lane <= 1'b0; end else if(r_Vaild_Or_Posedge == 1'b1 && Vaild_And == 1'b0) begin O_ReSearch_Offset_Lane <= 1'b1; end end endmodule
(4):Unpaket解包模块:
通过ECC校验完成对错误的甄别,同时如果发现错误,重置前两个模块的解析结果;
ECC:
module ECC_Calculate_Haming #( parameter Data_bit_width = 24, parameter Redundant_bit_width = 8 )( input wire [Data_bit_width -1:0] I_Data , output wire [Redundant_bit_width-1:0] O_ECC ); reg [Redundant_bit_width-1:0] r_O_ECC; assign O_ECC = r_O_ECC; always@(*) begin r_O_ECC[7] <= 1'b0; r_O_ECC[6] <= 1'b0; r_O_ECC[5] <= ^{I_Data[10], I_Data[11], I_Data[12], I_Data[13], I_Data[14], I_Data[15], I_Data[16], I_Data[17], I_Data[18], I_Data[19], I_Data[21], I_Data[22], I_Data[23]}; r_O_ECC[4] <= ^{I_Data[ 4], I_Data[ 5], I_Data[ 6], I_Data[ 7], I_Data[ 8], I_Data[ 9], I_Data[16], I_Data[17], I_Data[18], I_Data[19], I_Data[20], I_Data[22], I_Data[23]}; r_O_ECC[3] <= ^{I_Data[ 1], I_Data[ 2], I_Data[ 3], I_Data[ 7], I_Data[ 8], I_Data[ 9], I_Data[13], I_Data[14], I_Data[15], I_Data[19], I_Data[20], I_Data[21], I_Data[23]}; r_O_ECC[2] <= ^{I_Data[ 0], I_Data[ 2], I_Data[ 3], I_Data[ 5], I_Data[ 6], I_Data[ 9], I_Data[11], I_Data[12], I_Data[15], I_Data[18], I_Data[20], I_Data[21], I_Data[22]}; r_O_ECC[1] <= ^{I_Data[ 0], I_Data[ 1], I_Data[ 3], I_Data[ 4], I_Data[ 6], I_Data[ 8], I_Data[10], I_Data[12], I_Data[14], I_Data[17], I_Data[20], I_Data[21], I_Data[22], I_Data[23]}; r_O_ECC[0] <= ^{I_Data[ 0], I_Data[ 1], I_Data[ 2], I_Data[ 4], I_Data[ 5], I_Data[ 7], I_Data[10], I_Data[11], I_Data[13], I_Data[16], I_Data[20], I_Data[21], I_Data[22], I_Data[23]}; end endmodule
(5):数据还原模块:
将打包数据(分多个通道分发的RAW10数据)还原为原始的RAW10格式,此处是2LANE的情况:
4LANE的情况改改也是可以用的,只是那种时候发送速率会更快,拼接的情况会更多一些,此后的RAW10转RGB并不属于MIPI解析内容,放在下面的模块;
//Frame_Begin always @(posedge I_CLK or negedge I_Rst_n) begin if(I_Rst_n == 1'b0) begin Frame_Begin <= 1'b0; end else if(I_Mipi_Sync == 1'b1) begin Frame_Begin <= 1'b1; end end //Pixl_Cnt always @(posedge I_CLK or negedge I_Rst_n) begin if(I_Rst_n == 1'b0) begin Pixl_Cnt <= 3'd0; end else if((Frame_Begin == 1'b1) && (I_Mipi_Unpacket_Vaild == 1'b1)) begin if(Pixl_Cnt == 3'd4) begin Pixl_Cnt <= 3'd0; end else begin Pixl_Cnt <= Pixl_Cnt + 1'b1; end end end //r_Unpacket_Data always @(posedge I_CLK) begin rr_Unpacket_Data <= {I_Mipi_Unpacket_Data,rr_Unpacket_Data[16+:16]}; end //r_O_Mipi_raw10_depacker_Vaild always @(posedge I_CLK or negedge I_Rst_n) begin if(I_Rst_n == 1'b0) begin r_O_Mipi_raw10_depacker_Vaild <= 1'b0; end else if(Frame_Begin == 1'b1 && I_Mipi_Unpacket_Vaild == 1'b1 &&((Pixl_Cnt == 3'd2)|(Pixl_Cnt == 3'd4))) begin r_O_Mipi_raw10_depacker_Vaild <= 1'b1; end else begin r_O_Mipi_raw10_depacker_Vaild <= 1'b0; end end assign O_Mipi_raw10_depacker_Data = {SIGN_A, SIGN_B, SIGN_C, SIGN_D}; assign O_Mipi_raw10_depacker_Vaild = r_O_Mipi_raw10_depacker_Vaild ; always @(posedge I_CLK or negedge I_Rst_n) begin if(I_Rst_n == 1'b0) begin SIGN_A <= 10'd0; SIGN_B <= 10'd0; SIGN_C <= 10'd0; SIGN_D <= 10'd0; end else if(Frame_Begin == 1'b1) begin if((Pixl_Cnt == 3'd2) && (I_Mipi_Unpacket_Vaild == 1'b1)) begin SIGN_A <= {rr_Unpacket_Data[00+:8],I_Mipi_Unpacket_Data[0+:2]}; SIGN_B <= {rr_Unpacket_Data[08+:8],I_Mipi_Unpacket_Data[2+:2]}; SIGN_C <= {rr_Unpacket_Data[16+:8],I_Mipi_Unpacket_Data[4+:2]}; SIGN_D <= {rr_Unpacket_Data[24+:8],I_Mipi_Unpacket_Data[6+:2]}; end else if((Pixl_Cnt == 3'd4) && (I_Mipi_Unpacket_Vaild == 1'b1)) begin SIGN_A <= {rr_Unpacket_Data[08+:8],I_Mipi_Unpacket_Data[8+:2]}; SIGN_B <= {rr_Unpacket_Data[16+:8],I_Mipi_Unpacket_Data[10+:2]}; SIGN_C <= {rr_Unpacket_Data[24+:8],I_Mipi_Unpacket_Data[12+:2]}; SIGN_D <= {I_Mipi_Unpacket_Data[00+:8],I_Mipi_Unpacket_Data[14+:2]}; end end end
解析原理一览:
3.解析信号的处理:bayer2rgb
①应用于卷积的手写FIFO:
参考:手写同步FIFO:用于3X3卷积 - NoNounknow - 博客园 (cnblogs.com)
实际代码实现:(和上文中不是同一个,是项目中实际使用的)
module Line_Shift_RAM #( parameter DATA_WIDTH = 8 , parameter ADDR_WIDTH = 14 , parameter DATA_DEPTH = 2048 )( input wire I_CLK , input wire I_Rst_n , input wire I_Wr_en , input wire I_Rd_en , input wire [DATA_WIDTH-1:0] I_din , output wire [DATA_WIDTH-1:0] O_dout , output wire full , output wire empty ); //---------------------------------------------------------------------- localparam ADDR_MSB = 2 ** ADDR_WIDTH - 1; //---------------------------------------------------------------------- reg [ADDR_WIDTH-1:0] bram_waddr; reg [ADDR_WIDTH-1:0] bram_raddr; reg [DATA_WIDTH-1:0] r_ram[ADDR_MSB:0]; wire [DATA_WIDTH-1:0] bram_wdata; reg [DATA_WIDTH-1:0] bram_rdata; //WR-------------------------------------------------------------------- assign bram_wdata = I_din; always @(posedge I_CLK or negedge I_Rst_n) begin if(I_Rst_n == 1'b0) begin bram_waddr <= 'd0; end else if(I_Wr_en == 1'b1) begin if(bram_waddr == DATA_DEPTH - 1'b1) begin bram_waddr <= 'd0; end else begin bram_waddr <= bram_waddr + 1'b1; end end else begin bram_waddr <= bram_waddr; end end always @(posedge I_CLK) begin:RAM_Define if(I_Wr_en) begin r_ram[bram_waddr] <= bram_wdata; end else begin end end //WR-------------------------------------------------------------------- //RD-------------------------------------------------------------------- always @(posedge I_CLK or negedge I_Rst_n) begin if(I_Rst_n == 1'b0) begin bram_raddr <= 0; end else if(I_Rd_en == 1'b1) begin if(bram_raddr == DATA_DEPTH - 1'b1) begin bram_raddr <= 'd0; end else begin bram_raddr <= bram_raddr + 1'b1; end end else begin bram_raddr <= bram_raddr; end end always @(*) begin bram_rdata <= r_ram[bram_raddr]; end assign O_dout = bram_rdata; //RD-------------------------------------------------------------------- //Check----------------------------------------------------------------- reg [ADDR_WIDTH-1:0] Check_Cnt ; always @(posedge I_CLK or negedge I_Rst_n) begin if(I_Rst_n == 1'b0) begin Check_Cnt <= 'd0; end else if(I_Wr_en|I_Rd_en) begin if(I_Wr_en == 1'b1 && I_Rd_en == 1'b1)begin Check_Cnt <= Check_Cnt; end else if(I_Wr_en == 1'b1 && Check_Cnt != DATA_DEPTH-1 && I_Rd_en == 1'b0) begin Check_Cnt <= Check_Cnt + 1'b1; end else if(I_Rd_en == 1'b1 && Check_Cnt != 'd0 && I_Wr_en == 1'b0) begin Check_Cnt <= Check_Cnt - 1'b1; end else begin Check_Cnt <= Check_Cnt; end end else begin Check_Cnt <= Check_Cnt; end end assign empty = (Check_Cnt == 'd0 )?1'b1:1'b0; assign full = (Check_Cnt == DATA_DEPTH-1)?1'b1:1'b0 ; //Check----------------------------------------------------------------- endmodule
②bayer2rgb:3X3卷积:RG/GB格式
module bayer2rgb_3x3 #( parameter DATA_WIDTH = 8 , parameter I_W = 1922, parameter I_H = 1082 )( input wire I_Clk , input wire I_Rst , // input wire I_H_Sync , input wire [DATA_WIDTH-1:0] I_Raw_Data , input wire I_Raw_Vaild , input wire I_V_Sync , // output wire O_V_Sync , // output wire O_H_Sync , output wire O_RGB_Vaild , output wire [DATA_WIDTH-1:0] O_RGB_Data_r , output wire [DATA_WIDTH-1:0] O_RGB_Data_g , output wire [DATA_WIDTH-1:0] O_RGB_Data_b , output wire [23:0] O_RGB_Concat ); //--------------------------Define Port---------------------------// localparam H_cnt_w = $clog2(I_W - 1'b1); localparam V_cnt_w = $clog2(I_H - 1'b1); reg r1_V_Sync ; wire Pose_V_Sync ; reg r1_Raw_Vaild ; wire Nege_Raw_Vaild ; reg [H_cnt_w-1:0] H_cnt ; reg [V_cnt_w-1:0] V_cnt ; reg [DATA_WIDTH-1:0] r1_Raw_Data ; reg [DATA_WIDTH-1:0] r2_Raw_Data ; wire [DATA_WIDTH-1:0] Rd0_Data ; reg [DATA_WIDTH-1:0] r1_Rd0_Data ; reg [DATA_WIDTH-1:0] r2_Rd0_Data ; wire [DATA_WIDTH-1:0] Rd1_Data ; reg [DATA_WIDTH-1:0] r1_Rd1_Data ; reg [DATA_WIDTH-1:0] r2_Rd1_Data ; reg wr_en_0 ; reg [DATA_WIDTH-1:0] wr_data_0 ; reg rd_en_0 ; reg wr_en_1 ; reg [DATA_WIDTH-1:0] wr_data_1 ; reg rd_en_1 ; reg [DATA_WIDTH+2:0] RGB_Data_r ; reg [DATA_WIDTH+2:0] RGB_Data_g ; reg [DATA_WIDTH+2:0] RGB_Data_b ; reg RGB_vaild ; reg r1_RGB_vaild ; reg [H_cnt_w-1:0] H_Addr ; reg [V_cnt_w-1:0] V_Addr ; //--------------------------Define Port---------------------------// //--------------------------Main Code---------------------------// always @(posedge I_Clk) begin H_Addr <= (H_cnt >1)?(H_cnt - 2):0; V_Addr <= (V_cnt >1)?(V_cnt - 2):0; end always @(posedge I_Clk) begin r1_V_Sync <= I_V_Sync ; r1_Raw_Vaild <= I_Raw_Vaild ; {r1_Raw_Data, r2_Raw_Data} <= { I_Raw_Data, r1_Raw_Data }; {r1_Rd0_Data, r2_Rd0_Data} <= { Rd0_Data , r1_Rd0_Data }; {r1_Rd1_Data, r2_Rd1_Data} <= { Rd1_Data , r1_Rd1_Data }; r1_RGB_vaild <= RGB_vaild; end assign Pose_V_Sync = (I_V_Sync == 1'b1)&&(r1_V_Sync == 1'b0); assign Nege_Raw_Vaild = (I_Raw_Vaild == 1'b0)&&(r1_Raw_Vaild==1'b1); //H_cnt always @(posedge I_Clk or posedge I_Rst) begin if(I_Rst == 1'b1) begin H_cnt <= 'd0; end else if(Pose_V_Sync == 1'b1|Nege_Raw_Vaild) begin H_cnt <= 'd0; end else if(I_Raw_Vaild == 1'b1) begin if(H_cnt == I_W - 1'b1) begin H_cnt <= 'd0; end else begin H_cnt <= H_cnt + 1'b1; end end end always @(posedge I_Clk or posedge I_Rst) begin if(I_Rst == 1'b1) begin V_cnt <= 'd0; end else if(Pose_V_Sync == 1'b1) begin V_cnt <= 'd0; end else if(Nege_Raw_Vaild == 1'b1) begin if(V_cnt == I_H - 1'b1) begin V_cnt <= 'd0; end else begin V_cnt <= V_cnt + 1'b1; end end else begin V_cnt <= V_cnt; end end //wr //delay_0 always @(*) begin if(V_cnt == 0) begin wr_en_0 <= I_Raw_Vaild; end else if(V_cnt >= 2 && V_cnt < I_H - 1'b1) begin wr_en_0 <= I_Raw_Vaild; end else begin wr_en_0 <= 1'b0; end end always @(*) begin if(V_cnt == 0) begin wr_data_0 <= I_Raw_Data; end else if(V_cnt != 0)begin wr_data_0 <= Rd1_Data ; end end //delay_1 always @(*) begin if(V_cnt >= 1 && V_cnt < I_H - 1'b1) begin wr_en_1 <= I_Raw_Vaild; end else begin wr_en_1 <= 1'b0; end end always @(*) begin if(V_cnt >= 1) begin wr_data_1 <= I_Raw_Data; end else begin wr_data_1 <= 'd0; end end //rd //delay_0 always @(*) begin if(V_cnt >= 2 && V_cnt <= I_H - 1'b1) begin rd_en_0 <= I_Raw_Vaild; end else begin rd_en_0 <= 0; end end //delay_1 always @(*) begin if(V_cnt >= 2 && V_cnt <= I_H - 1'b1) begin rd_en_1 <= I_Raw_Vaild; end else begin rd_en_1 <= 0; end end // RGB_vaild assign O_RGB_Vaild = r1_RGB_vaild; assign O_V_Sync = I_V_Sync ; // assign O_H_Sync = I_H_Sync ; always @(posedge I_Clk or posedge I_Rst) begin if(I_Rst == 1'b1) begin RGB_vaild <= 1'b0; end else if(V_cnt >= 2 && H_cnt >= 1 && V_cnt <= I_H - 1'b1 && H_cnt < I_W - 1'b1) begin RGB_vaild <= I_Raw_Vaild; end else begin RGB_vaild <= 1'b0; end end //RGB assign O_RGB_Concat = {O_RGB_Data_r,O_RGB_Data_g,O_RGB_Data_b}; assign O_RGB_Data_r = (O_RGB_Vaild)?(RGB_Data_r[DATA_WIDTH-1:0]):8'd0; assign O_RGB_Data_g = (O_RGB_Vaild)?(RGB_Data_g[DATA_WIDTH-1:0]):8'd0; assign O_RGB_Data_b = (O_RGB_Vaild)?(RGB_Data_b[DATA_WIDTH-1:0]):8'd0; always @(posedge I_Clk or posedge I_Rst) begin if(I_Rst == 1'b1) begin RGB_Data_r <= 'd0; RGB_Data_g <= 'd0; RGB_Data_b <= 'd0; end else if(RGB_vaild == 1'b1) begin case({V_cnt[0],H_cnt[0]}) 2'b00:begin RGB_Data_r <= (I_Raw_Data + r2_Raw_Data + Rd0_Data + r2_Rd0_Data)>>2; RGB_Data_g <= (r1_Raw_Data + Rd1_Data + r2_Rd1_Data + r1_Rd0_Data)>>2; RGB_Data_b <= r1_Rd1_Data; end 2'b01:begin RGB_Data_r <= (r1_Raw_Data + r1_Rd0_Data)>>1; RGB_Data_g <= (((I_Raw_Data + r2_Raw_Data + Rd0_Data + r2_Rd0_Data)>>2) + r1_Rd1_Data)>>1; RGB_Data_b <= (Rd1_Data + r2_Rd1_Data)>>1; end 2'b10:begin RGB_Data_r <= (Rd1_Data + r2_Rd1_Data)>>1; RGB_Data_g <= ((I_Raw_Data + r2_Raw_Data + Rd0_Data + r2_Rd0_Data)>>2 + r1_Rd1_Data)>>1; RGB_Data_b <= (r1_Raw_Data + r1_Rd0_Data)>>1; end 2'b11:begin RGB_Data_r <= r1_Rd1_Data; RGB_Data_g <= (r1_Raw_Data + Rd1_Data + r2_Rd1_Data + r1_Rd0_Data)>>2; RGB_Data_b <= (I_Raw_Data + r2_Raw_Data + Rd0_Data + r2_Rd0_Data)>>2; end endcase end else begin RGB_Data_r <= 'd0; RGB_Data_g <= 'd0; RGB_Data_b <= 'd0; end end //--------------------------Main Code---------------------------// wire full_0 ; wire empty_0 ; wire full_1 ; wire empty_1 ; Line_Shift_RAM #( .DATA_WIDTH ( 8 ), .ADDR_WIDTH ( 11 ), .DATA_DEPTH ( 2048 )) u0_Line_Shift_RAM ( .I_CLK ( I_Clk ), .I_Rst_n ( !Pose_V_Sync & !I_Rst), .I_Wr_en ( wr_en_0 ), .I_Rd_en ( rd_en_0 ), .I_din ( wr_data_0 ), .O_dout ( Rd0_Data ), .full ( full_0 ), .empty ( empty_0 ) ); Line_Shift_RAM #( .DATA_WIDTH ( 8 ), .ADDR_WIDTH ( 11 ), .DATA_DEPTH ( 2048 )) u1_Line_Shift_RAM ( .I_CLK ( I_Clk ), .I_Rst_n ( !Pose_V_Sync & !I_Rst ), .I_Wr_en ( wr_en_1 ), .I_Rd_en ( rd_en_1 ), .I_din ( wr_data_1 ), .O_dout ( Rd1_Data ), .full ( full_1 ), .empty ( empty_1 ) ); ila_0 ila_1 ( .clk(I_Clk), // input wire clk .probe0 ( I_V_Sync ), // input wire [0:0] probe0 .probe1 ( I_Raw_Vaild ), // input wire [0:0] probe1 .probe2 ( I_Raw_Data ), // input wire [7:0] probe2 .probe3 ( r1_Raw_Data ), // input wire [7:0] probe3 .probe4 ( r2_Raw_Data ), // input wire [7:0] probe4 .probe5 ( Rd0_Data ), // input wire [7:0] probe5 .probe6 ( r1_Rd0_Data ), // input wire [7:0] probe6 .probe7 ( r2_Rd0_Data ), // input wire [7:0] probe7 .probe8 ( Rd1_Data ), // input wire [7:0] probe8 .probe9 ( r1_Rd1_Data ), // input wire [7:0] probe9 .probe10( r2_Rd1_Data ), // input wire [7:0] probe10 .probe11( H_cnt ), // input wire [11:0] probe11 .probe12( V_cnt ), // input wire [11:0] probe12 .probe13( wr_en_0 ), // input wire [0:0] probe13 .probe14( rd_en_0 ), // input wire [0:0] probe14 .probe15( wr_en_1 ), // input wire [0:0] probe15 .probe16( rd_en_1 ), // input wire [0:0] probe16 .probe17( O_RGB_Vaild ), // input wire [0:0] probe17 .probe18( H_Addr ), // input wire [11:0] probe18 .probe19( V_Addr ), // input wire [11:0] probe19 .probe20( RGB_Data_r ), // input wire [0:0] probe17 .probe21( RGB_Data_g ), // input wire [11:0] probe18 .probe22( RGB_Data_b ), // input wire [11:0] probe19 .probe23( I_Rst ) // input wire [11:0] probe19 ); endmodule
③bayer2rgb:2X2卷积:BG/GR格式
module Post_Raw2Rgb ( input wire I_Clk , input wire I_Rsy_n , input wire I_V_Sync , input wire I_H_Sync , input wire I_Raw_Vaild , input wire [7:0] I_Raw_Data , // output wire O_V_Sync , output wire O_H_Sync , output wire O_RGB_Vaild , output wire [7:0] O_RGB_Data_r , output wire [7:0] O_RGB_Data_g , output wire [7:0] O_RGB_Data_b ); reg [15:0] Row_Cnt ; reg [15:0] Col_Cnt ; //FIFO wire FIFO_Wr_en ; wire [7:0] FIFO_Wr_Data ; wire FIFO_Rd_en ; wire [7:0] FIFO_Rd_data ; reg r1_FIFO_Wr_en ; reg [7:0] r1_FIFO_Wr_Data ; reg r1_FIFO_Rd_en ; reg [7:0] r1_FIFO_Rd_data ; wire full ; wire empty ; wire wr_rst_busy ; wire rd_rst_busy ; //Pose reg r1_I_V_Sync ; wire Pose_I_V_Sync ; wire Ext_Pose_V_Sync ; reg r1_I_H_Sync ; wire Pose_I_H_Sync ; //Pixel reg [8:0] RGB_Data_r; reg [8:0] RGB_Data_g; reg [8:0] RGB_Data_b; //FIFO assign FIFO_Wr_en = I_Raw_Vaild; assign FIFO_Wr_Data = I_Raw_Data ; assign FIFO_Rd_en = (Row_Cnt >= 1)?(FIFO_Wr_en):(1'b0); always @(posedge I_Clk) begin r1_I_V_Sync <= I_V_Sync ; r1_I_H_Sync <= I_H_Sync ; r1_FIFO_Wr_en <= FIFO_Wr_en ; r1_FIFO_Wr_Data <= FIFO_Wr_Data; r1_FIFO_Rd_en <= FIFO_Rd_en ; r1_FIFO_Rd_data <= FIFO_Rd_data; end assign Pose_I_V_Sync = (I_V_Sync == 1'b1)&&(r1_I_V_Sync == 1'b0); assign Pose_I_H_Sync = (I_H_Sync == 1'b1)&&(r1_I_H_Sync == 1'b0); //Col_Cnt always @(posedge I_Clk or negedge I_Rsy_n) begin if(I_Rsy_n == 1'b0) begin Col_Cnt <= 'd0; end else if(FIFO_Wr_en == 1'b1) begin Col_Cnt <= Col_Cnt + 1'b1; end else begin Col_Cnt <= 'd0; end end //Row_Cnt always @(posedge I_Clk or negedge I_Rsy_n) begin if(I_Rsy_n == 1'b0) begin Row_Cnt <= 'd0; end else if(Pose_I_V_Sync) begin Row_Cnt <= 'd0; end else if(Pose_I_H_Sync == 1'b1) begin Row_Cnt <= Row_Cnt + 1'b1; end else begin Row_Cnt <= Row_Cnt; end end assign O_RGB_Vaild = r1_FIFO_Wr_en ; assign O_RGB_Data_r = RGB_Data_r[7:0] ; assign O_RGB_Data_g = RGB_Data_g[7:0] ; assign O_RGB_Data_b = RGB_Data_b[7:0] ; assign O_V_Sync = r1_I_V_Sync ; assign O_H_Sync = r1_I_H_Sync ; //BGBG //GRGR always @(posedge I_Clk or negedge I_Rsy_n) begin if(I_Rsy_n == 1'b0) begin RGB_Data_r <= 'd0; RGB_Data_g <= 'd0; RGB_Data_b <= 'd0; end else if(FIFO_Wr_en == 1'b1) begin case({Row_Cnt[0],Col_Cnt[0]}) 2'b00:begin RGB_Data_r <= r1_FIFO_Rd_data; RGB_Data_g <=(FIFO_Rd_data + r1_FIFO_Wr_Data)>>1'b1; RGB_Data_b <= FIFO_Wr_Data; end 2'b10:begin RGB_Data_r <= r1_FIFO_Wr_Data; RGB_Data_g <=(FIFO_Wr_Data + r1_FIFO_Rd_data)>>1'b1; RGB_Data_b <= FIFO_Rd_data; end 2'b01:begin RGB_Data_r <= FIFO_Rd_data; RGB_Data_g <=(FIFO_Wr_Data + r1_FIFO_Rd_data)>>1'b1; RGB_Data_b <= r1_FIFO_Wr_Data; end 2'b11:begin RGB_Data_r <= FIFO_Wr_Data; RGB_Data_g <=(FIFO_Rd_data + r1_FIFO_Wr_Data)>>1'b1; RGB_Data_b <= r1_FIFO_Wr_Data; end endcase end else begin RGB_Data_r <= 'd0; RGB_Data_g <= 'd0; RGB_Data_b <= 'd0; end end data_sync_ext Post_Raw2Rgb_FIFO_Rst( .clka (I_Clk ), .rst_n (I_Rsy_n ), .pulse_a (Pose_I_V_Sync ), .ext_pulse_a (Ext_Pose_V_Sync ) ); S_fifo_w16x2048_r16x2048 S_fifo_w16x2048_r16x2048 ( .rst ( Ext_Pose_V_Sync ), // input wire rst .wr_clk ( I_Clk ), // input wire wr_clk .rd_clk ( I_Clk ), // input wire rd_clk .din ( FIFO_Wr_Data ), // input wire [15 : 0] din .wr_en ( FIFO_Wr_en ), // input wire wr_en .rd_en ( FIFO_Rd_en ), // input wire rd_en .dout ( FIFO_Rd_data ), // output wire [15 : 0] dout .full ( full ), // output wire full .empty ( empty ), // output wire empty .wr_rst_busy( wr_rst_busy ), // output wire wr_rst_busy .rd_rst_busy( rd_rst_busy ) // output wire rd_rst_busy ); endmodule
4.处理后信号的存储:
①:写入FIFO;
②:写入DDR的请求:
(此处如果不考虑平台移植可以使用Axi interconnect ip)
③:帧同步和撕裂防止:
帧同步:利用输入信号的同步信号同步写入地址和清空写入FIFO,输出信号的同步信号同步读出地址和清空读出FIFO;
帧同步的思想与异步FIFO复位_异步fifo怎么复位-CSDN博客
撕裂防止措施:
【1】:乒乓操作;
【2】:帧缓存架构:永远读刚读取完的那一帧;
魔改自: 02基于FDMA三缓存构架_哔哩哔哩_bilibili
代码来自:NoNounknow/DMA: DMA仓库,主要包含了各种操作场景下用的DMA,细节在博客园。 (github.com)
其中之一:
`timescale 1 ns / 1 ps module DMA_Custom # ( parameter C_M_TARGET_SLAVE_BASE_ADDR = 32'h2000000, parameter integer C_M_AXI_BURST_LEN = 256 , parameter integer C_M_AXI_ID_WIDTH = 1 , parameter integer C_M_AXI_ADDR_WIDTH = 32 , parameter integer C_M_AXI_DATA_WIDTH = 64 , parameter integer C_M_AXI_AWUSER_WIDTH = 0 , parameter integer C_M_AXI_ARUSER_WIDTH = 0 , parameter integer C_M_AXI_WUSER_WIDTH = 0 , parameter integer C_M_AXI_RUSER_WIDTH = 0 , parameter integer C_M_AXI_BUSER_WIDTH = 0 , parameter I_image_w = 1920 , parameter I_image_h = 1080 , parameter Pixel_byte_num = 4 , parameter AXI_Buff_NUM = 3 , parameter Input_Data_width = 24 ) ( input wire M_AXI_ACLK , input wire M_AXI_ARESETN , output wire [C_M_AXI_ID_WIDTH-1 : 0] M_AXI_AWID , output wire [C_M_AXI_ADDR_WIDTH-1 : 0] M_AXI_AWADDR , output wire [7 : 0] M_AXI_AWLEN , output wire [2 : 0] M_AXI_AWSIZE , output wire [1 : 0] M_AXI_AWBURST , output wire M_AXI_AWLOCK , output wire [3 : 0] M_AXI_AWCACHE , output wire [2 : 0] M_AXI_AWPROT , output wire [3 : 0] M_AXI_AWQOS , output wire [C_M_AXI_AWUSER_WIDTH-1 : 0] M_AXI_AWUSER , output wire M_AXI_AWVALID , input wire M_AXI_AWREADY , output wire [C_M_AXI_DATA_WIDTH-1 : 0] M_AXI_WDATA , output wire [C_M_AXI_DATA_WIDTH/8-1 : 0] M_AXI_WSTRB , output wire M_AXI_WLAST , output wire [C_M_AXI_WUSER_WIDTH-1 : 0] M_AXI_WUSER , output wire M_AXI_WVALID , input wire M_AXI_WREADY , input wire [C_M_AXI_ID_WIDTH-1 : 0] M_AXI_BID, input wire [1 : 0] M_AXI_BRESP , input wire [C_M_AXI_BUSER_WIDTH-1 : 0] M_AXI_BUSER , input wire M_AXI_BVALID , output wire M_AXI_BREADY , output wire [C_M_AXI_ID_WIDTH-1 : 0] M_AXI_ARID , output wire [C_M_AXI_ADDR_WIDTH-1 : 0] M_AXI_ARADDR , output wire [7 : 0] M_AXI_ARLEN , output wire [2 : 0] M_AXI_ARSIZE , output wire [1 : 0] M_AXI_ARBURST , output wire M_AXI_ARLOCK , output wire [3 : 0] M_AXI_ARCACHE , output wire [2 : 0] M_AXI_ARPROT , output wire [3 : 0] M_AXI_ARQOS , output wire [C_M_AXI_ARUSER_WIDTH-1 : 0] M_AXI_ARUSER , output wire M_AXI_ARVALID , input wire M_AXI_ARREADY , input wire [C_M_AXI_ID_WIDTH-1 : 0] M_AXI_RID , input wire [C_M_AXI_DATA_WIDTH-1 : 0] M_AXI_RDATA , input wire [1 : 0] M_AXI_RRESP , input wire M_AXI_RLAST , input wire [C_M_AXI_RUSER_WIDTH-1 : 0] M_AXI_RUSER , input wire M_AXI_RVALID , output wire M_AXI_RREADY , //Custom input wire I_Pre_clk , input wire I_Pre_vs , input wire [Input_Data_width-1:0] I_Pre_data , input wire I_Pre_de , input wire I_Post_clk , output wire O_Post_Start , output wire [Input_Data_width-1:0] O_Post_data , input wire I_Post_de , input wire I_Post_vs ); function integer clogb2 (input integer bit_depth); begin for(clogb2=0; bit_depth>0; clogb2=clogb2+1) bit_depth = bit_depth >> 1; end endfunction //========================================= Define Ports =========================================// localparam integer C_TRANSACTIONS_NUM = clogb2(C_M_AXI_BURST_LEN-1) ; localparam Awaddr_Brust_Offset = (C_M_AXI_DATA_WIDTH)*(C_M_AXI_BURST_LEN)/8 ; localparam Araddr_Brust_Offset = (C_M_AXI_DATA_WIDTH)*(C_M_AXI_BURST_LEN)/8 ; localparam Total_Frame_Offset = I_image_w*I_image_h*Pixel_byte_num ; localparam RAM_1_start_addr = 0 ; localparam RAM_2_start_addr = Total_Frame_Offset ; localparam RAM_3_start_addr = Total_Frame_Offset*2 ; localparam wr_burst_times = I_image_w*I_image_h*Pixel_byte_num /Awaddr_Brust_Offset ; localparam rd_burst_times = I_image_w*I_image_h*Pixel_byte_num /Araddr_Brust_Offset ; //========================================= Define Ports =========================================// // AXI4LITE signals //AXI4 internal temp signals reg [C_M_AXI_ADDR_WIDTH-1 : 0] axi_awaddr ; reg axi_awvalid ; reg axi_wlast ; reg axi_wvalid ; reg [C_TRANSACTIONS_NUM-1:0] wr_burst_cnt ; reg axi_bready ; reg [C_M_AXI_ADDR_WIDTH-1 : 0] axi_araddr ; reg axi_arvalid ; reg axi_rready ; //W_FIFO wire wr_fifo_wr_en ; wire [C_M_AXI_DATA_WIDTH-1 : 0] wr_fifo_wr_data ; wire wr_fifo_rd_en ; wire [C_M_AXI_DATA_WIDTH-1 : 0] wr_fifo_rd_data ; wire full_w ; wire empty_w ; wire [15 : 0] w_rd_data_count ; wire [15 : 0] w_wr_data_count ; //r_FIFO wire rd_fifo_wr_en ; wire [C_M_AXI_DATA_WIDTH-1 : 0] rd_fifo_wr_data ; wire rd_fifo_rd_en ; wire [31 : 0] rd_fifo_rd_data ; wire [12 : 0] r_rd_data_count ; wire [11 : 0] r_wr_data_count ; wire full_r ; wire empty_r ; reg [15:0] rd_hcnt ; reg [15:0] rd_vcnt ; //I/O Connections. Write Address (AW) assign M_AXI_AWID = 'b0; assign M_AXI_AWADDR = C_M_TARGET_SLAVE_BASE_ADDR + axi_awaddr; assign M_AXI_AWLEN = C_M_AXI_BURST_LEN - 1; assign M_AXI_AWSIZE = clogb2((C_M_AXI_DATA_WIDTH/8)-1); assign M_AXI_AWBURST = 2'b01; assign M_AXI_AWLOCK = 1'b0; assign M_AXI_AWCACHE = 4'b0010; assign M_AXI_AWPROT = 3'h0; assign M_AXI_AWQOS = 4'h0; assign M_AXI_AWUSER = 'b1; assign M_AXI_AWVALID = axi_awvalid; //Write Data(W) assign wr_fifo_rd_en = (axi_wvalid == 1'b1)&&(M_AXI_WREADY == 1'b1); assign M_AXI_WDATA = wr_fifo_rd_data; //All bursts are complete and aligned in this example assign M_AXI_WSTRB = {(C_M_AXI_DATA_WIDTH/8){1'b1}}; assign M_AXI_WLAST = axi_wlast; assign M_AXI_WUSER = 'b0; assign M_AXI_WVALID = axi_wvalid; //Write Response (B) assign M_AXI_BREADY = axi_bready; //Read Address (AR) assign M_AXI_ARID = 'b0; assign M_AXI_ARADDR = C_M_TARGET_SLAVE_BASE_ADDR + axi_araddr; assign M_AXI_ARLEN = C_M_AXI_BURST_LEN - 1; assign M_AXI_ARSIZE = clogb2((C_M_AXI_DATA_WIDTH/8)-1); assign M_AXI_ARBURST = 2'b01; assign M_AXI_ARLOCK = 1'b0; assign M_AXI_ARCACHE = 4'b0010; assign M_AXI_ARPROT = 3'h0; assign M_AXI_ARQOS = 4'h0; assign M_AXI_ARUSER = 'b1; assign M_AXI_ARVALID = axi_arvalid; //Read and Read Response (R) assign M_AXI_RREADY = axi_rready; // Wr_Sync------------------------------------------------------------------------------------------// //W Sync Port //wrclk reg r1_pre_vs ; wire Pose_pre_vs ; wire Nege_pre_vs ; wire Ext_Pose_pre_vs ; //sysclk reg sys_pre_vs ; reg r1_sys_pre_vs ; reg sys_Pose_pre_vs ; reg sys_Nege_pre_vs ; reg r_sys_Nege_pre_vs; reg [1:0] wr_index ; reg [C_M_AXI_ADDR_WIDTH-1 : 0] wr_base_addr ; always @(posedge I_Pre_clk) begin r1_pre_vs <= I_Pre_vs; end assign Pose_pre_vs = (I_Pre_vs == 1'b1)&&(r1_pre_vs == 1'b0); assign Nege_pre_vs = (I_Pre_vs == 1'b0)&&(r1_pre_vs == 1'b1); always@(posedge M_AXI_ACLK) begin sys_pre_vs <= I_Pre_vs ; r1_sys_pre_vs <= sys_pre_vs; r_sys_Nege_pre_vs <= sys_Nege_pre_vs; end always @(posedge M_AXI_ACLK) begin if(M_AXI_ARESETN == 1'b0) begin sys_Pose_pre_vs <= 1'b0; sys_Nege_pre_vs <= 1'b0; end else if(sys_pre_vs==1'b1&&r1_sys_pre_vs==1'b0) begin sys_Pose_pre_vs <= 1'b1; sys_Nege_pre_vs <= 1'b0; end else if(sys_pre_vs==1'b0&&r1_sys_pre_vs==1'b1) begin sys_Pose_pre_vs <= 1'b0; sys_Nege_pre_vs <= 1'b1; end else begin sys_Pose_pre_vs <= 1'b0; sys_Nege_pre_vs <= 1'b0; end end Data_sync_ext Data_sync_ext_Inst0( .clka ( I_Pre_clk ), .rst_n ( M_AXI_ARESETN ), .pulse_a ( Pose_pre_vs ), .ext_pulse_a ( Ext_Pose_pre_vs ) ); always@(posedge M_AXI_ACLK) if(M_AXI_ARESETN == 1'b0) begin wr_index <= 'd1; end else if(sys_Nege_pre_vs == 1'b1&&wr_index == AXI_Buff_NUM) begin wr_index <= 'd1; end else if(sys_Nege_pre_vs==1'b1) begin wr_index <= wr_index + 1'b1; end else begin wr_index <= wr_index; end always@(posedge M_AXI_ACLK) if(M_AXI_ARESETN == 1'b0) begin wr_base_addr <= 0; end else if(sys_Nege_pre_vs == 1'b1&&wr_index == AXI_Buff_NUM) begin wr_base_addr <= 0; end else if(sys_Nege_pre_vs == 1'b1) begin wr_base_addr <= wr_base_addr + Total_Frame_Offset; end else begin wr_base_addr <= wr_base_addr; end // Wr_Sync------------------------------------------------------------------------------------------// assign wr_fifo_wr_en = I_Pre_de; assign wr_fifo_wr_data = {8'h0,I_Pre_data}; wdata_w64x1024_r64x1024 wdata_w32x4096_r64x2048 ( .rst ( (!M_AXI_ARESETN)|(Ext_Pose_pre_vs)), // input wire rst .wr_clk ( I_Pre_clk ), // input wire wr_clk .rd_clk ( M_AXI_ACLK ), // input wire rd_clk .din ( wr_fifo_wr_data ), // input wire [63 : 0] din .wr_en ( wr_fifo_wr_en ), // input wire wr_en .rd_en ( wr_fifo_rd_en ), // input wire rd_en .dout ( wr_fifo_rd_data ), // output wire [63 : 0] dout .full ( full_w ), // output wire full .empty ( empty_w ), // output wire empty .rd_data_count(w_rd_data_count ), // output wire [10 : 0] rd_data_count .wr_data_count(w_wr_data_count ), // output wire [10 : 0] wr_data_count .wr_rst_busy(), // output wire wr_rst_busy .rd_rst_busy() // output wire rd_rst_busy ); // w_start_control----------------------------------------------------------------------------------// //Control reg wr_brust_start ; wire wr_brust_Req ; wire wr_brust_end ; reg wr_brust_now ; assign wr_brust_Req = (w_rd_data_count>=C_M_AXI_BURST_LEN); assign wr_brust_end = (axi_wvalid==1'b1&&M_AXI_WREADY==1'b1&&wr_burst_cnt==C_M_AXI_BURST_LEN-1); //多路输入的时候,wr_brust_Req输出到仲裁器中,使用仲裁器输出的aribe_req请求完成此处wr_brust_Req的工作 always@(*) if(wr_brust_Req == 1'b1) begin wr_brust_start <= 1'b1; end else begin wr_brust_start <= 1'b0; end always@(posedge M_AXI_ACLK) if(M_AXI_ARESETN == 1'b0) begin wr_brust_now <= 1'b0; end else if(wr_brust_end == 1'b1 && wr_brust_now == 1'b1) begin wr_brust_now <= 1'b0; end else if(wr_brust_start == 1'b1 && wr_brust_now == 1'b0) begin wr_brust_now <= 1'b1; end else begin wr_brust_now <= wr_brust_now; end // w_start_control----------------------------------------------------------------------------------// // Aw------ --------------------------------------------------------------------------------------// //axi_awvalid always@(posedge M_AXI_ACLK) if(M_AXI_ARESETN == 1'b0) begin axi_awvalid <= 1'b0; end else if(axi_awvalid == 1'b1 && M_AXI_AWREADY == 1'b1) begin axi_awvalid <= 1'b0; end else if(wr_brust_start == 1'b1 && wr_brust_now == 1'b0) begin axi_awvalid <= 1'b1; end else begin axi_awvalid <= axi_awvalid; end //axi_awaddr always@(posedge M_AXI_ACLK) if(M_AXI_ARESETN == 1'b0) begin axi_awaddr <= 'd0; end else if(r_sys_Nege_pre_vs == 1'b1) begin axi_awaddr <= wr_base_addr; // end else if(r_sys_Nege_pre_vs == 1'b1) begin // axi_awaddr <= 0; end else if(axi_awvalid==1'b1 && M_AXI_AWREADY==1'b1) begin axi_awaddr <= axi_awaddr + Awaddr_Brust_Offset ; end else begin axi_awaddr <= axi_awaddr; end // Aw---------------------------------------------------------------------------------------------// // W----------------------------------------------------------------------------------------------// //axi_wvalid always@(posedge M_AXI_ACLK) if(M_AXI_ARESETN == 1'b0) begin axi_wvalid <= 1'b0; end else if(axi_wvalid==1'b1&&M_AXI_WREADY==1'b1&&wr_burst_cnt==C_M_AXI_BURST_LEN-1) begin axi_wvalid <= 1'b0; end else if(axi_awvalid==1'b1&&M_AXI_AWREADY==1'b1) begin axi_wvalid <= 1'b1; end else begin axi_wvalid <= axi_wvalid; end //wr_burst_cnt always@(posedge M_AXI_ACLK) begin if(M_AXI_ARESETN == 1'b0) begin wr_burst_cnt <= 'd0; end else if(axi_wvalid==1'b1&&M_AXI_WREADY==1'b1&&wr_burst_cnt==C_M_AXI_BURST_LEN-1) begin wr_burst_cnt <= 'd0; end else if(axi_wvalid==1'b1&&M_AXI_WREADY==1'b1) begin wr_burst_cnt <= wr_burst_cnt + 1'b1; end else begin wr_burst_cnt <= wr_burst_cnt; end end //axi_wlast always@(posedge M_AXI_ACLK) begin if(M_AXI_ARESETN == 1'b0) begin axi_wlast <= 1'b0; end else if(axi_wvalid==1'b1&&M_AXI_WREADY==1'b1&&wr_burst_cnt==C_M_AXI_BURST_LEN-1'b1) begin axi_wlast <= 1'b0; end else if(axi_wvalid==1'b1&&M_AXI_WREADY==1'b1&&wr_burst_cnt==C_M_AXI_BURST_LEN-2'd2) begin axi_wlast <= 1'b1; end else begin axi_wlast <= axi_wlast; end end // W----------------------------------------------------------------------------------------------// // b----------------------------------------------------------------------------------------------// always @(posedge M_AXI_ACLK) begin if(M_AXI_ARESETN == 0) begin axi_bready <= 'd0; end else begin axi_bready <= 1'b1; end end // b----------------------------------------------------------------------------------------------// // r_start_control----------------------------------------------------------------------------------// //Control reg [7:0] rd_index ; reg [7:0] rd_index_ptr ; reg [C_M_AXI_ADDR_WIDTH-1 : 0] rd_base_addr ; reg rd_start_cycle ; reg [2:0] rd_start_cnt ; reg rd_brust_start ; reg rd_brust_Req ; reg rd_brust_end ; reg rd_brust_now ; reg Post_Start ; always@(posedge M_AXI_ACLK) begin if(M_AXI_ARESETN == 0) begin rd_index <= 0; end else if(wr_index > 1) begin rd_index <= wr_index - 1'b1; end else begin rd_index <= AXI_Buff_NUM; end end always@(posedge M_AXI_ACLK) begin if(M_AXI_ARESETN == 0) begin rd_index_ptr <= 'd0; end else begin rd_index_ptr <= rd_index - 1'b1; end end always@(posedge M_AXI_ACLK) begin if(M_AXI_ARESETN == 0) begin rd_base_addr <= 'd0; end else begin rd_base_addr <= rd_index_ptr*Total_Frame_Offset; end end always@(posedge M_AXI_ACLK) begin if(M_AXI_ARESETN == 0) begin rd_start_cnt <= 'd0; end else if(sys_Nege_pre_vs && rd_start_cnt[2] != 1'b1) begin rd_start_cnt <= rd_start_cnt + 1'b1; end else begin rd_start_cnt <= rd_start_cnt; end end always@(posedge M_AXI_ACLK) begin if(M_AXI_ARESETN == 0) begin rd_start_cycle <= 1'b0; end else if(rd_start_cnt[2] == 1'b1 && full_r == 1'b0) begin rd_start_cycle <= 1'b1; end else begin rd_start_cycle <= rd_start_cycle; end end always@(posedge I_Post_clk) if(M_AXI_ARESETN == 0) begin Post_Start <= 1'b0; end else if(rd_start_cycle == 1'b1 && r_rd_data_count >= C_M_AXI_BURST_LEN) begin Post_Start <= 1'b1; end else begin Post_Start <= Post_Start; end assign O_Post_Start = Post_Start; always @(*) begin if((rd_start_cycle == 1'b1) && (r_wr_data_count < C_M_AXI_BURST_LEN*4)) begin rd_brust_Req <= 1'b1; end else begin rd_brust_Req <= 1'b0; end end always@(*) begin if((M_AXI_RVALID == 1'b1)&&(axi_rready == 1'b1)&&(M_AXI_RLAST == 1'b1)) begin rd_brust_end <= 1'b1; end else begin rd_brust_end <= 1'b0; end end //No aribe always@(*) begin if(rd_brust_Req == 1'b1) begin rd_brust_start <= 1'b1; end else begin rd_brust_start <= 1'b0; end end always@(posedge M_AXI_ACLK) if(M_AXI_ARESETN == 1'b0) begin rd_brust_now <= 1'b0; end else if(rd_brust_end == 1'b1 && rd_brust_now == 1'b1) begin rd_brust_now <= 1'b0; end else if(rd_brust_start == 1'b1 && rd_brust_now == 1'b0) begin rd_brust_now <= 1'b1; end else begin rd_brust_now <= rd_brust_now; end // r_start_control----------------------------------------------------------------------------------// // ar---------------------------------------------------------------------------------------------// always@(posedge M_AXI_ACLK) begin if(M_AXI_ARESETN == 1'b0) begin axi_arvalid <= 1'b0; end else if(axi_arvalid==1'b1&&M_AXI_ARREADY==1'b1) begin axi_arvalid <= 1'b0; end else if(rd_brust_start == 1'b1 && rd_brust_now == 1'b0) begin axi_arvalid <= 1'b1; end else begin axi_arvalid <= axi_arvalid; end end always@(posedge M_AXI_ACLK) begin if(M_AXI_ARESETN == 1'b0) begin axi_araddr <= 'd0; end else if((M_AXI_RVALID == 1'b1)&&(axi_rready == 1'b1)&&(rd_hcnt == C_M_AXI_BURST_LEN - 1)&&(rd_vcnt == rd_burst_times - 1'b1)) begin axi_araddr <= rd_base_addr; // end else if((M_AXI_RVALID == 1'b1)&&(axi_rready == 1'b1)&&(rd_hcnt == C_M_AXI_BURST_LEN - 1)&&(rd_vcnt == rd_burst_times - 1'b1)) begin // axi_araddr <= 0; end else if(axi_arvalid==1'b1&&M_AXI_ARREADY==1'b1) begin axi_araddr <= axi_araddr + Araddr_Brust_Offset; end else begin axi_araddr <= axi_araddr; end end // ar---------------------------------------------------------------------------------------------// // r----------------------------------------------------------------------------------------------// always@(posedge M_AXI_ACLK) begin if(M_AXI_ARESETN == 1'b0) begin axi_rready <= 1'b0; end else if((M_AXI_RVALID == 1'b1)&&(axi_rready == 1'b1)&&(M_AXI_RLAST == 1'b1)) begin axi_rready <= 1'b0; end else if(axi_arvalid==1'b1&&M_AXI_ARREADY==1'b1) begin axi_rready <= 1'b1; end else begin axi_rready <= axi_rready; end end // r----------------------------------------------------------------------------------------------// // r_Sync-----------------------------------------------------------------------------------------// assign rd_fifo_wr_en = (M_AXI_RVALID == 1'b1)&&(axi_rready == 1'b1); assign rd_fifo_wr_data = M_AXI_RDATA; assign rd_fifo_rd_en = I_Post_de && Post_Start; assign O_Post_data = rd_fifo_rd_data[23:0]; rdata_w64x2048_r32x4096 rdata_w64x2048_r32x4096 ( .rst ( (!M_AXI_ARESETN)&&(!rd_start_cnt[2])), // input wire rst .wr_clk ( M_AXI_ACLK ), // input wire wr_clk .rd_clk ( I_Post_clk ), // input wire rd_clk .din ( rd_fifo_wr_data ), // input wire [63 : 0] din .wr_en ( rd_fifo_wr_en ), // input wire wr_en .rd_en ( rd_fifo_rd_en ), // input wire rd_en .dout ( rd_fifo_rd_data ), // output wire [31 : 0] dout .full ( full_r ), // output wire full .empty ( empty_r ), // output wire empty .rd_data_count( r_rd_data_count ), // output wire [12 : 0] rd_data_count .wr_data_count( r_wr_data_count ), // output wire [11 : 0] wr_data_count .wr_rst_busy(), // output wire wr_rst_busy .rd_rst_busy() // output wire rd_rst_busy ); //hcnt always@(posedge M_AXI_ACLK)begin if(M_AXI_ARESETN == 1'b0) begin rd_hcnt <= 'd0; end else if((M_AXI_RVALID == 1'b1)&&(axi_rready == 1'b1)&&(rd_hcnt == C_M_AXI_BURST_LEN - 1)) begin rd_hcnt <= 'd0; end else if((M_AXI_RVALID == 1'b1)&&(axi_rready == 1'b1)) begin rd_hcnt <= rd_hcnt + 1'b1; end else begin rd_hcnt <= rd_hcnt; end end //vcnt always@(posedge M_AXI_ACLK)begin if(M_AXI_ARESETN == 1'b0) begin rd_vcnt <= 'd0; end else if((M_AXI_RVALID == 1'b1)&&(axi_rready == 1'b1)&&(rd_hcnt == C_M_AXI_BURST_LEN - 1)&&(rd_vcnt == rd_burst_times - 1'b1)) begin rd_vcnt <= 'd0; end else if((M_AXI_RVALID == 1'b1)&&(axi_rready == 1'b1)&&(rd_hcnt == C_M_AXI_BURST_LEN - 1)) begin rd_vcnt <= rd_vcnt + 1'b1; end else begin rd_vcnt <= rd_vcnt; end end // r_Sync-----------------------------------------------------------------------------------------// //Test reg [15:0] Test_wr_hcnt; reg [15:0] Test_wr_vcnt; reg r_I_Pre_de; always @(posedge I_Pre_clk) begin r_I_Pre_de <= I_Pre_de; end always @(posedge I_Pre_clk) begin if(M_AXI_ARESETN == 1'b0) begin Test_wr_hcnt <= 'd0; end else if(I_Pre_de == 1'b1 && Test_wr_hcnt == 1920-1) begin Test_wr_hcnt <= 'd0; end else if(I_Pre_de == 1'b1) begin Test_wr_hcnt <= Test_wr_hcnt + 1'b1; end else begin Test_wr_hcnt <= Test_wr_hcnt; end end always @(posedge I_Pre_clk) begin if(M_AXI_ARESETN == 1'b0) begin Test_wr_vcnt <= 'd0; end else if(Nege_pre_vs == 1'b1) begin Test_wr_vcnt <= 'd0; end else if(I_Pre_de == 1'b0&&r_I_Pre_de == 1'b1) begin Test_wr_vcnt <= Test_wr_vcnt + 1'b1; end else begin Test_wr_vcnt <= Test_wr_vcnt; end end reg [15:0] Test_rd_hcnt; reg [15:0] Test_rd_vcnt; reg r_I_Post_de ; always @(posedge I_Post_clk) begin r_I_Post_de <= I_Post_de; end always @(posedge I_Post_clk) begin if(M_AXI_ARESETN == 1'b0) begin Test_rd_hcnt <= 'd0; end else if(I_Post_vs == 1'b1) begin Test_rd_hcnt <= 'd0; end else if(I_Post_de == 1'b1 && Test_rd_hcnt == 1920-1) begin Test_rd_hcnt <= 'd0; end else if(I_Post_de == 1'b1) begin Test_rd_hcnt <= Test_rd_hcnt + 1'b1; end else begin Test_rd_hcnt <= Test_rd_hcnt; end end always @(posedge I_Post_clk) begin if(M_AXI_ARESETN == 1'b0) begin Test_rd_vcnt <= 'd0; end else if(I_Post_vs == 1'b1) begin Test_rd_vcnt <= 'd0; end else if(I_Post_de == 1'b1&&r_I_Post_de == 1'b0) begin Test_rd_vcnt <= Test_rd_vcnt + 1'b1; end else begin Test_rd_vcnt <= Test_rd_vcnt; end end AXI_ILA AXI_ILA ( .clk(M_AXI_ACLK), // input wire clk .probe0( I_Pre_de ), //1 .probe1( wr_index ), //2 .probe2( wr_base_addr ), //32 .probe3( w_rd_data_count ), //12 .probe4( full_w ), //1 .probe5( empty_w ), //1 .probe6( wr_brust_Req ), //1 .probe7( wr_brust_end ), //1 .probe8( wr_brust_now ), //1 .probe9( axi_awvalid ), //1 .probe10( axi_awaddr ), //32 .probe11( axi_wvalid ), //1 .probe12( wr_burst_cnt ), //8 .probe13( axi_wlast ), //1 .probe14( I_Post_de ), //1 .probe15( I_Post_vs ), //1 .probe16( I_Pre_vs ), //1 .probe17( O_Post_data ), //24 .probe18( rd_index_ptr ), //8 .probe19( rd_base_addr ), //32 .probe20( rd_start_cnt ), //2 .probe21( rd_brust_Req ), //1 .probe22( r_wr_data_count ), //12 .probe23( axi_arvalid ), //1 .probe24( axi_araddr ), //32 .probe25( axi_rready ), //1 .probe26( rd_fifo_wr_en ),//1 .probe27( rd_hcnt ), //16 .probe28( rd_vcnt ), //16 .probe29( Test_wr_hcnt ), //16 .probe30( Test_wr_vcnt ), //16 .probe31( Test_rd_hcnt ), //16 .probe32( Test_rd_vcnt ), //16 .probe33( full_r ), //16 .probe34( empty_r ) //16 ); endmodule
【3】:Three-two-pull-down:与帧缓存架构类似;
3:2 pulldown_3:2 pull down-CSDN博客
(2)HDMI输入通道
(3)以太网输入通道:Ps以太网输入:TCP/IP
1.实现方法:
lwip实现TCP/IP格式的上位机视频收发。
以太网学习之TCP/IP:PC上位机通过Socket连接下发视频至FPGA的若干总结 - NoNounknow - 博客园 (cnblogs.com)
2.实现原理:
3.测试手段:自建matlab上位机
其中一部分比较重要的
pause(0.0001); write(Client_1,framehead); pause(0.0001); for n = 1:image_h for m = 1:image_w Data_Line_Buf(2 * m -1) = 0; if n < image_h/4 Data_Line_Buf(2 * m) = 64; elseif n < image_h/2 Data_Line_Buf(2 * m) = 128; elseif n < image_h/2 + image_h/4 Data_Line_Buf(2 * m) = 192; else Data_Line_Buf(2 * m) = 255; end end write(Client_1,Data_Line_Buf) pause(0.000001); end readreq = read(Client_1, 8, "uint8");
4.代码:
使用了NoNounknow/DMA: DMA仓库,主要包含了各种操作场景下用的DMA,细节在博客园。 (github.com)的DMA模块;
使用了HDMI等模块;
C代码用的是官方例程稍作修改后的,通过把接受区的地址直接设置为指定的DMA读取地址,可以实现低延迟访问;
一定记得DCACHE刷新数据!
(3)以太网输入通道:PL以太网输入:UDP
解帧:
以太网:UDP包结构 - NoNounknow - 博客园 (cnblogs.com)
CRC:
【CRC校验方法】+【FPGA实现(接收端)】 - NoNounknow - 博客园 (cnblogs.com)
上位机:
Matlab构建上位机:UDP测试 - NoNounknow - 博客园 (cnblogs.com)
防丢包:
UDP接收PC发送数据的丢包处理:同步头 - NoNounknow - 博客园 (cnblogs.com)