VIDEO视频OSD输出模块的理解

这里的OSD是通过I2C命令,把点阵字模一个点定义为一个字节,送到FPGA的RAM中,再由FPGA根据输出时序进行显示。字符OSD显示在最上面层上。


module osd(
	input vin_clk,
	input vin_hs,
	input vin_vs,
	input vin_de,
	input vin_f,
	input[7:0] vin_r,
	input[7:0] vin_g,
	input[7:0] vin_b,
	output vout_hs,
	output vout_vs,
	output vout_de,
	output vout_f,
	output[7:0] vout_r,
	output[7:0] vout_g,
	output[7:0] vout_b,
	
	input[11:0] osd_wr_addr,
	input[1:0] osd_wr_data,
	input osd_wren,
	input osd_wrclk,
	
	input[11 : 0] top,
	input[11 : 0] left
	
);

/*以下的操作琢磨了一阵,终于明白了用意。ASCII还是16X8的点阵,用0表示不显象素点,用1表示显示像素点。
,在STM32程序中,用一个I2C写一次来表示一个像素,例如:一个H字符,有128个像素点,需要写128次I2C,写的
结果存到ALTER定义的RAM(4096X2),也就是说,一共可以显示4096/128=32个字符。
这样做的结果是,可以用2位表示4种颜色,除去一个背景,还有3种颜色。*/

parameter R0 = 8'd0;
parameter G0 = 8'd0;
parameter B0 = 8'd0;		// BLACK
parameter R1 = 8'd255;
parameter G1 = 8'd255;
parameter B1 = 8'd255;		// WHITE
parameter R2 = 8'd0;
parameter G2 = 8'd0;
parameter B2 = 8'd255;		// BLUE
reg[11:0] rdaddr;
wire[1:0] osd_rd_data;
ram_osd ram_osd_m0(
	.data(osd_wr_data),
	.rdaddress(rdaddr),
	.rdclock(vin_clk),
	.wraddress(osd_wr_addr),
	.wrclock(osd_wrclk),
	.wren(osd_wren),
	.q(osd_rd_data));
wire xy_gen_hs;
wire xy_gen_vs;
wire xy_gen_de;
reg xy_gen_hs_d0;
reg xy_gen_vs_d0;
reg xy_gen_de_d0;
reg xy_gen_hs_d1;
reg xy_gen_vs_d1;
reg xy_gen_de_d1;
reg xy_gen_hs_d2;
reg xy_gen_vs_d2;
reg xy_gen_de_d2;
wire[11:0] xy_gen_x;
wire[11:0] xy_gen_y;
wire[11:0] osd_y;
wire[11:0] osd_x;
reg rdreq;
reg rdreq_d0;
wire[11:0] rec_y;
reg[7:0] rgb_r,rgb_g,rgb_b;
reg[7:0] rgb_r_d0,rgb_g_d0,rgb_b_d0;
wire[7:0] r,g,b;
assign rec_y = xy_gen_y[11:0];
assign osd_y = rec_y - top;
assign osd_x = xy_gen_x - left;
assign vout_hs = xy_gen_hs_d2;
assign vout_vs = xy_gen_vs_d2;
assign vout_de = xy_gen_de_d2;
assign vout_f = vin_f;
assign vout_r = rgb_r_d0;
assign vout_g = rgb_g_d0;
assign vout_b = rgb_b_d0;
//assign rdreq = (rec_y > top) && (rec_y <= top + 12'd32) && (xy_gen_x > left) && (xy_gen_x <= left + 12'd128);
timing_gen_xy timing_gen_xy_m0(
	.rst_n(1'b1),
	.clk(vin_clk),
	.i_hs(vin_hs),
	.i_vs(vin_vs),
	.i_de(vin_de),
	.i_data({vin_r,vin_g,vin_b}),
	.o_hs(xy_gen_hs),
	.o_vs(xy_gen_vs),
	.o_de(xy_gen_de),
	.o_data({r,g,b}),
	.x(xy_gen_x),
	.y(xy_gen_y)
);

always@(posedge vin_clk)
begin
	rdaddr[11:7] <= osd_y[5:1];
	rdaddr[6:0] <= osd_x[7:1];
	rdreq <= (rec_y > top) && (rec_y <= top + 12'd64) && (xy_gen_x > left) && (xy_gen_x <= left + 12'd256);
	rdreq_d0 <= rdreq;
	xy_gen_hs_d0 <= xy_gen_hs;
	xy_gen_vs_d0 <= xy_gen_vs;
	xy_gen_de_d0 <= xy_gen_de;
	xy_gen_hs_d1 <= xy_gen_hs_d0;
	xy_gen_vs_d1 <= xy_gen_vs_d0;
	xy_gen_de_d1 <= xy_gen_de_d0;	
	xy_gen_hs_d2 <= xy_gen_hs_d1;
	xy_gen_vs_d2 <= xy_gen_vs_d1;
	xy_gen_de_d2 <= xy_gen_de_d1;	
	rgb_r_d0 <= rgb_r;
	rgb_g_d0 <= rgb_g;
	rgb_b_d0 <= rgb_b;
	
end

always@(posedge vin_clk)
begin
	if(rdreq_d0)
		case(osd_rd_data)
			2'd0:
				begin
					rgb_r <= r;
					rgb_g <= g;
					rgb_b <= b;
				end
			2'd1:
				begin
					rgb_r <= R0;
					rgb_g <= G0;
					rgb_b <= B0;
				end
			2'd2:
				begin
					rgb_r <= R1;
					rgb_g <= G1;
					rgb_b <= B1;
				end
			2'd3:
				begin
					rgb_r <= R2;
					rgb_g <= G2;
					rgb_b <= B2;
				end
			default:
				begin
					rgb_r <= r;
					rgb_g <= g;
					rgb_b <= b;
				end
		endcase
	else
		begin
			rgb_r <= r;
			rgb_g <= g;
			rgb_b <= b;
		end
end
endmodule 




wire[7:0] osd_r;
wire[7:0] osd_g;
wire[7:0] osd_b;
wire osd_hs;
wire osd_vs;
wire osd_de;
vout_display_pro vout_display_pro_m0(
	.rst_n(rst_n),
	.dp_clk(vga_out_clk),
	.h_fp(H_FP[11:0]),
	.h_sync(H_SYNC[11:0]),
	.h_bp(H_BP[11:0]),
	.h_active(H_ACTIVE[11:0]),
	.h_total(H_TOTAL[11:0]),
	
	.v_fp(V_FP[11:0]),
	.v_sync(V_SYNC[11:0]),
	.v_bp(V_BP[11:0]), 
	.v_active(V_ACTIVE[11:0]),
	.v_total(V_TOTAL[11:0]),
	
	.hs(osd_hs),				// 输出显示模块的输出不再是直接输出到VGA端口,而是输出到OSD模块
	.vs(osd_vs),
	.de(osd_de),
	
	.rgb_r(osd_r),
	.rgb_g(osd_g),
	.rgb_b(osd_b),
	
	.layer0_top(disp_top[16 * CH0 - 5 : 16 * CH0 - 16]),
	.layer0_left(disp_left[16 * CH0 - 5 : 16 * CH0 - 16]),
	.layer0_width(vout_t_width[16 * CH0 - 5 : 16 * CH0 - 16]),
	.layer0_height(vout_t_height[16 * CH0 - 5 : 16 * CH0 - 16]),
	.layer0_alpha(alpha[8 * CH0 - 1 : 8 * CH0 - 8]),
	.layer0_rdreq(ch0_vout_rd_req),
	.layer0_ycbcr(ch0_vout_ycbcr)
);

osd osd_m0(
	.vin_clk(vga_out_clk),
	.vin_hs(osd_hs),
	.vin_vs(osd_vs),
	.vin_de(osd_de),
	.vin_f(),
	.vin_r(osd_r),
	.vin_g(osd_g),
	.vin_b(osd_b),
	.vout_hs(vga_out_hs),			// 这才是真正的VGA输出,由OSD模块
	.vout_vs(vga_out_vs),
	.vout_de(vga_out_de),
	.vout_f(),
	.vout_r(vga_out_rgb_r),
	.vout_g(vga_out_rgb_g),
	.vout_b(vga_out_rgb_b),
	
	.osd_wr_addr(osd_wr_addr[11:0]),
	.osd_wr_data(osd_wr_data[1:0]),
	.osd_wren(osd_wr_en),
	.osd_wrclk(clk),
	.top(osd_top[11:0]),
	.left(osd_left[11:0])	
);






你可能感兴趣的:(FPGA)