RGB接口转LVDS
1;功能:完成RGB接口转换成LVDS接口输出!
2;下图是FITI79001H的 8位LVDS时序图
3;下图是我写出来的模块的仿真结果
4;顶层代码
1 module RGB_LVDS( 2 reset, 3 ttl_clk, 4 ttl_data_in, 5 clkpn, 6 lvds_data 7 ); 8 9 input wire reset; 10 input wire ttl_clk;//50Mhz 11 input wire [27:0] ttl_data_in;//{k,hs,vs,de,r[7:0],g[7:0],b[7:0]} 12 output [7:0] lvds_data; 13 output [1:0] clkpn; 14 15 reg [27:0] ttldata_r; 16 wire lvds_71clk; 17 wire lvds_72clk; 18 wire clk; 19 wire [7:0] lvds_datah; 20 wire [7:0] lvds_datal; 21 reg [2:0] clk_conter; 22 23 wire n_reset; 24 25 reg [1:0] lvdsclkh; 26 reg [1:0] lvdsclkl; 27 28 assign n_reset=!reset; 29 30 always @(negedge ttl_clk or negedge reset ) 31 begin 32 if(!reset) 33 ttldata_r<=28'b0; 34 else 35 ttldata_r<=ttl_data_in; 36 37 end 38 39 40 always @(negedge lvds_71clk or negedge reset ) 41 begin 42 if(!reset) 43 clk_conter<=3'b0; 44 else if(clk_conter>=3'd6) 45 clk_conter<=3'b0; 46 else 47 clk_conter<=clk_conter+3'b1; 48 49 end 50 always @(negedge lvds_71clk or negedge reset ) 51 begin 52 if(!reset) 53 begin 54 lvdsclkh<=2'b0; 55 lvdsclkl<=2'b0; 56 end 57 else if(clk_conter<=3'd1) 58 begin 59 lvdsclkh<=2'b10; 60 lvdsclkl<=2'b10; 61 end 62 else if(clk_conter>3'd1 && clk_conter<5) 63 begin 64 lvdsclkh<=2'b01; 65 lvdsclkl<=2'b01; 66 end 67 else if(clk_conter>=3'd5) 68 begin 69 lvdsclkh<=2'b10; 70 lvdsclkl<=2'b10; 71 end 72 73 end 74 75 PLL7B clk_inst( 76 .areset(n_reset), 77 .inclk0(ttl_clk), 78 .c0(lvds_71clk), 79 .c1(lvds_72clk), 80 .c2(clk), 81 .locked() 82 83 ); 84 85 P28toS7 P28TOS7_INST( 86 .rst(reset), 87 .ttlclk(clk), 88 .lvdsclk71(lvds_71clk), 89 .ttl_dataw(ttldata_r), 90 .lvds_datah(lvds_datah), 91 .lvds_datal(lvds_datal) 92 93 ); 94 95 lvds_data4 LVDS_DATA_INST( 96 .datain_h(lvds_datah), 97 .datain_l(lvds_datal), 98 .outclock(lvds_72clk), 99 .dataout(lvds_data) 100 ); 101 102 LVDSCLK_PN CLKPN_INST( 103 .aclr(), 104 .datain_h(lvdsclkh), 105 .datain_l(lvdsclkl), 106 .outclock(lvds_71clk), 107 .dataout(clkpn) 108 ); 109 110 endmodule
5;顶层仿真代码
`timescale 10ns/1ns module RGB_LVDS_TB; reg reset; reg ttl_clk;//50Mhz reg [27:0] ttl_data;//{k,hs,vs,de,r[7:0],g[7:0],b[7:0]} reg hsync,vsync,enable; reg [7:0] rdata,gdata,bdata; wire [7:0] lvds_data; wire [1:0] clkpn; initial begin reset=0; ttl_clk=0; hsync=1; vsync=1; enable=1; rdata=8'b1111_1111; gdata=8'b0000_0000; bdata=8'b0000_0000; ttl_data<=28'b0; #120; reset=1; ttl_data={0,hsync,vsync,enable,rdata,gdata,bdata}; #160; $stop; end always #1 ttl_clk<=!ttl_clk; RGB_LVDS RGB_LVDS_INST( .reset(reset), .ttl_clk(ttl_clk), .ttl_data_in(ttl_data), .clkpn(clkpn), .lvds_data(lvds_data) ); endmodule
6;时钟锁向环设置
7;4通道的差分数据线输出IP(ALTDDIO_OUT)
8;由于LVDS差分时钟信号的频率与LVDS差分数据信号的频率不一样,所以不能共用一个IP
9;28位并行数据转串行数据模块代码
// Convert 28BIT parallel data to serial data module P28toS7( rst, ttlclk, lvdsclk71, ttl_dataw, lvds_datah, lvds_datal ); input rst; input ttlclk; input lvdsclk71; input [27:0] ttl_dataw; reg [27:0] ttl_data;//{k,hs,vs,de,r[7:0],g[7:0],b[7:0]} output reg [7:0] lvds_datah; output reg [7:0] lvds_datal; reg [7:0] ttl_data8; reg [3:0] lvds_data4; reg [3:0] temp_data0; reg [3:0] temp_data1; reg [3:0] temp_data2; reg [3:0] temp_data3; reg [3:0] temp_data4; reg [3:0] temp_data5; reg [3:0] temp_data6; reg [2:0] conter; reg start_sig1,start_sig2,start_sig3; wire pclk_sig; reg [0:0] hl_conter; always @(negedge ttlclk or negedge rst) begin if(!rst) ttl_data<=8'b0; else ttl_data<=ttl_dataw; end always @(negedge ttlclk or negedge rst) begin if(!rst) begin temp_data0<=4'b0; temp_data1<=4'b0; temp_data2<=4'b0; temp_data3<=4'b0; temp_data4<=4'b0; temp_data5<=4'b0; temp_data6<=4'b0; end else begin temp_data0 <= {ttl_data[16],ttl_data[9],ttl_data[2],ttl_data[22]}; //R0 G1 B2 R6 temp_data1 <= {ttl_data[17],ttl_data[10],ttl_data[3],ttl_data[23]};// R1 G2 B3 R7 temp_data2 <= {ttl_data[18],ttl_data[11],ttl_data[4],ttl_data[14]};//R2 G3 B4 G6 temp_data3 <= {ttl_data[19],ttl_data[12],ttl_data[5],ttl_data[15]};//R3 G4 B5 G7 temp_data4 <= {ttl_data[20],ttl_data[13],ttl_data[26],ttl_data[6]};//R4 G5 HS B6 temp_data5 <= {ttl_data[21],ttl_data[0],ttl_data[25],ttl_data[7]};//R5 B0 VS B7 temp_data6 <= {ttl_data[8],ttl_data[1],ttl_data[24],ttl_data[27]};//G0 B1 DE end end assign pclk_sig= start_sig3 && start_sig2 && start_sig1; always @(negedge lvdsclk71 or negedge rst ) begin if(!rst) begin start_sig1<=1'b0; start_sig2<=1'b0; start_sig3<=1'b0; end else begin start_sig1<=ttlclk; start_sig2<=start_sig1; start_sig3<=start_sig2; end end always @(negedge lvdsclk71 or negedge rst ) begin if(rst==1'b0 ) conter<=3'b0; else if(pclk_sig) conter<=3'b0; else conter<=conter+3'b1; end always @(negedge lvdsclk71 or negedge rst) begin if(!rst) lvds_data4<=3'b0; else begin case(conter) 3'b000 : lvds_data4<=temp_data0; 3'b001 : lvds_data4<=temp_data1; 3'b010 : lvds_data4<=temp_data2; 3'b011 : lvds_data4<=temp_data3; 3'b100 : lvds_data4<=temp_data4; 3'b101 : lvds_data4<=temp_data5; 3'b110 : lvds_data4<=temp_data6; default : lvds_data4<=temp_data0; endcase end end always @ (negedge lvdsclk71 or negedge rst) begin if(!rst) ttl_data8<=8'b0; else begin case(lvds_data4) 4'B0000 : ttl_data8<=8'b01_01_01_01;//0123 4'B0001 : ttl_data8<=8'b01_01_01_10;//0123 4'B0010 : ttl_data8<=8'b01_01_10_01;//0123 4'B0011 : ttl_data8<=8'b01_01_10_10;//0123 4'B0100 : ttl_data8<=8'b01_10_01_01;//0123 4'B0101 : ttl_data8<=8'b01_10_01_10;//0123 4'B0110 : ttl_data8<=8'b01_10_10_01;//0123 4'B0111 : ttl_data8<=8'b01_10_10_10;//0123 4'B1000 : ttl_data8<=8'b10_01_01_01;//0123 4'B1001 : ttl_data8<=8'b10_01_01_10;//0123 4'B1010 : ttl_data8<=8'b10_01_10_01;//0123 4'B1011 : ttl_data8<=8'b10_01_10_10;//0123 4'B1100 : ttl_data8<=8'b10_10_01_01;//0123 4'B1101 : ttl_data8<=8'b10_10_01_10;//0123 4'B1110 : ttl_data8<=8'b10_10_10_01;//0123 4'B1111 : ttl_data8<=8'b10_10_10_10;//0123 default : ttl_data8<=8'b01_01_01_01;//0123 endcase end end always @(negedge lvdsclk71 or negedge rst) begin if(!rst) hl_conter<=1'b0; else hl_conter<=!hl_conter; end always @(negedge lvdsclk71 or negedge rst) begin if(!rst) begin lvds_datah<=8'b0; lvds_datal<=8'b0; end else begin if(!hl_conter) lvds_datah<=ttl_data8; else lvds_datal<=ttl_data8; end end endmodule