Studied the two-day BT1120 specifications, and CEA-861-D video timing, we found some correspondence between (see my other article "relationship with the BT1120 the video timing" ). So I wrote the following verilog code which can be connected sii9134 chip row inline field, wherein the configuration sii9134 C code as follows:
void sii9134_init(void)
{
u8 u8Data = 0;
I2C_WriteByte(0x05, 0x08, 0x72); //value reg_addr device_addr
I2C_ReadByte(&u8Data, sizeof(u8), 0x33, 0x72);
I2C_WriteByte(u8Data & 0x8f, 0x33, 0x72);
I2C_WriteByte(0x6e, 0x40, 0x72);
I2C_WriteByte(0x28, 0x44, 0x72);
I2C_WriteByte(0x00, 0x45, 0x72);
I2C_WriteByte(0x05, 0x46, 0x72);
I2C_WriteByte(0x05, 0x47, 0x72);
I2C_WriteByte(0x30, 0x48, 0x72);
I2C_WriteByte(0x3d, 0x4a, 0x72);
}
Breadboard using the FPGA AV6045 development board black gold.
FPGA end bt1120 verilog code is as follows (horizontal and vertical sync signal is active high hsync and vsync):
Further, if it is found the pixel data is 0x00 or 0xff 0xfe and 0x01 need to be replaced, to prevent misjudgment end. (This article does not do this step)
/ **
* author: [email protected]
* Time: 2017/8/28
* function: YCbCr 4: 2: 2 embed_hs_vs Encoder Module1, compatible BT.1120
*
* timing reference codes <0xFF 0x00 0x00 xxx>
* where xxx is the following range:
* 0. 1. 1. 1. 1 0 0 0 0. 1 0xAB (vertical blanking period, within the SAV)
(vertical blanking period, within the EAV) * 0. 1. 1. 1. 1. 1 0 0 0 0 0xB6
*. 1 0 0 0 0 0 0 0 0 0 0x80 ( video active region of time, within the SAV)
*. 1 0 0. 1. 1. 1 0. 1 0 0 0x9d (video active region of time, within the EAV)
* /
`timescale 1ns / 100ps
Module1 embed_hs_vs_enc (
RST INPUT,
INPUT yc422_pclk_i,
INPUT [15: 0] yc422_data_i,
INPUT yc422_de_i,
INPUT yc422_vs_i,
INPUT yc422_hs_i,
// ------------------------------------------------ --------
// video timing parameters, obtained by the CPU through i2c arranged
INPUT [. 11: 0] width_i, // L
INPUT [. 11: 0] height_i, //
INPUT [. 11: 0] hs_rising_to_de_i,
INPUT [. 11: 0] hor_total_g_i,
INPUT [. 11: 0] vs_rising_to_de_i, // L2 of
INPUT [. 11: 0] ver_total_g_i, L6 of //
// ------------------- ---------------------------------------
the INPUT video_pararm_enable_i,
// ------ -------------------------------------------------- -
//bt.1120 Interface
Output embed_hs_vs_pclk_o,
Output REG [15: 0] embed_hs_vs_yc422_o
);
// state machine
localparam INVAILD_BLANKING = 4'd0;
localparam VAILD_VIDEO = 4'd1;
localparam SYNC1_SAV = 4'd2;
localparam SYNC2_SAV = 4'd3;
localparam SYNC3_SAV = 4'd4;
localparam SYNC1_EAV = 4'd5;
localparam SYNC2_EAV = 4'd6;
localparam SYNC3_EAV = 4'd7;
localparam SAV_BKANKING = 4'd8;
localparam EAV_BKANKING = 4'd9;
localparam SAV_VIDEO = 4'd10;
localparam EAV_VIDEO = 4'd11;
//在行场消隐区填充STUFF
localparam STUFF = 16'h8010;
wire hs_rising; //rising or falling
wire vs_rising;
reg [11:0] vs_cnt;//场计数器
reg [11:0] hs_cnt;Line counter //
// properly handle the reset signal, the register value is not initialized or
REG [. 11: 0] width_g;
REG [. 11: 0] height_g;
REG [. 11: 0] hs_rising_to_de_g;
REG [. 11: 0] hor_total_g;
REG [. 11: 0] vs_rising_to_de_g;
REG [. 11: 0] ver_total_g;
REG [ 3: 0] state_cs; // should be noted that the current state variable register bit width, prevent overflow
reg [3: 0] state_ns; // next state
// to delay the operation of the signal, playing a beat
// reg [15 : 0] yc422_data_d1;
REG yc422_de_d1;
REG yc422_vs_d1;
REG yc422_hs_d1;
Always @ (posedge yc422_pclk_i)
the begin
IF (RST) the begin
// yc422_data_d1 <= 16'h00;
yc422_de_d1 <= 1'b0;
yc422_vs_d1 <= 1'b0;
yc422_hs_d1 <= 1'b0;
End the else the begin
//yc422_data_d1 <= yc422_data_i;
yc422_de_d1 <= yc422_de_i;
yc422_vs_d1 <= yc422_vs_i;
yc422_hs_d1 <= yc422_hs_i;
end
end
assign embed_hs_vs_pclk_o = yc422_pclk_i;
assign hs_rising = ~yc422_hs_d1 & yc422_hs_i;
assign vs_rising = ~yc422_vs_d1 & yc422_vs_i;
always @(posedge yc422_pclk_i)
begin
if(rst) begin
width_g <= 12'd1920;
height_g <= 12'd1080;
hs_rising_to_de_g <= 12'd192;
hor_total_g <= 12'd2200;
vs_rising_to_de_g <= 12'd41;
ver_total_g <= 12'd1125;
end else if(video_pararm_enable_i)begin
width_g <= width_i;
height_g <= height_i;
hs_rising_to_de_g <= hs_rising_to_de_i;
hor_total_g <= hor_total_g_i;
vs_rising_to_de_g <= vs_rising_to_de_i;
ver_total_g <= ver_total_g_i;
end
end
//行计数
always @(posedge yc422_pclk_i)
begin
if(rst)
hs_cnt <= 0;
else if(hs_rising || video_pararm_enable_i)
hs_cnt <= 0;
else if(hs_cnt == hor_total_g - 1'b1)
hs_cnt <= 0;
else
hs_cnt <= hs_cnt + 1'b1; always @ (posedge yc422_pclk_i) // frame count
End
begin
if(rst)
vs_cnt <= 0;
else if(vs_rising || video_pararm_enable_i)
vs_cnt <= 0;
else if(hs_cnt == hor_total_g - 1'b1)
if(vs_cnt == ver_total_g - 1'b1)
vs_cnt <= 0;
else
vs_cnt <= vs_cnt + 1'b1;
else
vs_cnt <= vs_cnt;
end
always @(posedge yc422_pclk_i)
begin
if(rst)
state_cs <= INVAILD_BLANKING;
else
state_cs <= state_ns;
end
always @(*)
begin
case(state_cs)
INVAILD_BLANKING :
begin
if (hs_cnt == hs_rising_to_de_g - 3'd6) // SAV four clock cycles earlier, to include SAV and EAV as 4 clock cycles, and third and compensation state_cs brought 2-timer
state_ns = SYNC1_SAV;
the else IF (hs_cnt == hs_rising_to_de_g + width_g - 3'd2 ) // EAV does not require four clock cycles earlier, but requires compensation and third state_cs brought 2-timer
state_ns = SYNC1_EAV;
the else
state_ns = INVAILD_BLANKING;
End
// the SAV part
SYNC1_SAV: state_ns = SYNC2_SAV;
SYNC2_SAV: state_ns = SYNC3_SAV;
SYNC3_SAV:
IF ((vs_cnt> = vs_rising_to_de_g - 1'b1) && (vs_cnt <+ = height_g vs_rising_to_de_g - 1'b1)) // VILD_VIDEO
state_ns = SAV_VIDEO;
the else
state_ns SAV_BKANKING =;
// portion of the EAV
SYNC1_EAV : state_ns = SYNC2_EAV;
SYNC2_EAV : state_ns = SYNC3_EAV;
SYNC3_EAV :
if((vs_cnt >= vs_rising_to_de_g - 1'b1) && (vs_cnt <= height_g + vs_rising_to_de_g - 1'b1))//VILD_VIDEO
state_ns = EAV_VIDEO;
else
state_ns = EAV_BKANKING;
SAV_BKANKING : state_ns = INVAILD_BLANKING;
EAV_BKANKING : state_ns = INVAILD_BLANKING;
SAV_VIDEO : state_ns = VAILD_VIDEO;
EAV_VIDEO : state_ns = INVAILD_BLANKING;
VAILD_VIDEO :
if(hs_cnt == hs_rising_to_de_g + width_g - 1'b1 - 1'b1)
state_ns = SYNC1_EAV;//去EAV部分
else
state_ns = VAILD_VIDEO;
default :
state_ns = INVAILD_BLANKING;
endcase
end
always @(posedge yc422_pclk_i)
begin
if(rst)
embed_hs_vs_yc422_o <= STUFF;
else begin
if(state_cs == INVAILD_BLANKING)
embed_hs_vs_yc422_o <= STUFF;
else if(state_cs == VAILD_VIDEO)
embed_hs_vs_yc422_o <= yc422_data_i; //yc422_data_d1
else if((state_cs == SYNC1_SAV) || (state_cs == SYNC1_EAV))
embed_hs_vs_yc422_o <= 16'hffff;
else if((state_cs == SYNC2_SAV) || (state_cs == SYNC2_EAV))
embed_hs_vs_yc422_o <= 16'h0000;
else if((state_cs == SYNC3_SAV) || (state_cs == SYNC3_EAV))
embed_hs_vs_yc422_o <= 16'h0000;
else if(state_cs == SAV_BKANKING)
embed_hs_vs_yc422_o <= 16'habab;
else if(state_cs == EAV_BKANKING)
embed_hs_vs_yc422_o <= 16'hb6b6;
else if(state_cs == SAV_VIDEO)
embed_hs_vs_yc422_o <= 16'h8080;
else if(state_cs == EAV_VIDEO)
embed_hs_vs_yc422_o <= 16'h9d9d;
else
embed_hs_vs_yc422_o <= STUFF;
end
end
endmodule
U_embed_hs_vs_enc_0 embed_hs_vs_enc (
. RST (RST),
. yc422_pclk_i (video_clk_148m5),
. yc422_data_i ({yc_c, yc_y}),
. yc422_de_i (yc_de),
. yc422_vs_i (yc_vs),
. yc422_hs_i (yc_hs),
// ----- -------------------------------------------------- -
// video timing parameters, obtained from the CPU through the I2C configuration
width_i (12'd1920), // L.
height_i (12'd1080), //.
hs_rising_to_de_i (12'd192),.
hor_total_g_i (12'd2200),.
. vs_rising_to_de_i (12'd41), L2 of //
. ver_total_g_i (12'd1125), L6 of //
// -------------------------- --------------------------------
. video_pararm_enable_i(video_pararm_enable),
//----------------------------------------------------------
//bt.1120接口
. embed_hs_vs_pclk_o(bt1120_clk),
. embed_hs_vs_yc422_o(bt1120_yc)
);