基本原理
使用两片SRAM,一片读,一片写,下个周期两片读写翻转。
SRAM
IS61WV102416BLL的控制时序如下:
FPGA代码
`timescale 1ns / 1ps
module top(
input CLK50M,
input CLK27M,
output LED,
input[19:0] GS2971_DI,
input[2:0] GS2971_STAT, // H V DE
input GS2971_CLKI,
output GS2971_RESET,
output GS2971_XTALL1,
output[19:0] GS2972_DO,
output GS2972_PCLK,
output GS2972_FDE,
output GS2972_HSVNC,
output GS2972_VSYNC,
output GS2972_RESET,
output GS2972_RATESEL0,
output GS2972_RATESEL1,
output GS2972_SDOEN,
output[19:0] SRAM1_A,
inout wire[15:0] SRAM1_D,
output SRAM1_CE,
output SRAM1_OE,
output SRAM1_WE,
output[19:0] SRAM2_A,
inout wire[15:0] SRAM2_D,
output SRAM2_CE,
output SRAM2_OE,
output SRAM2_WE
);
/***1280x720***/
parameter LinePeriod = 1650;//总的周期
parameter H_SyncPluse = 40;//HSYNC的时钟数
parameter H_BackPorch = 220;//前消隐
parameter H_ActivePix = 1280;//有效像素值
parameter H_FrontPorch = 110;//后消隐
parameter Hde_start = 260;//开始的时钟
parameter Hde_end = 1540;//结束的时钟
parameter FramePeriod = 750;//总的周期
parameter V_SyncPluse = 5;//VSYNC的时钟数
parameter V_BackPorch = 20;//
parameter V_ActivePix = 720;
parameter V_FrontPorch = 5;
parameter Vde_start = 25;
parameter Vde_end = 745;
reg GS2972_VSYNC_creat;
reg GS2972_HSVNC_creat;
reg vsync_de;
reg hsync_de;
reg HSYNC_delay;
reg VSYNC_delay;
reg[10:0] x_cnt = 0;
reg[10:0] y_cnt = 0;
/*
reg[10:0] H_delay = 1;
//reg[10:0] V_delay = 749;
reg[10:0] V_delay = 0;
*/
parameter H_delay = 1; //时序问题调整 因人而异
parameter V_delay = 749;
reg[15:0] DATA_DI_reg;
reg[15:0] DATA_DO_reg;
//reg[15:0] DATA_DO_reg_deley;
reg[15:0] SRAM1_D_reg;
reg[15:0] SRAM1_D_reg_delay;
reg[15:0] SRAM2_D_reg;
reg[15:0] SRAM2_D_reg_delay;
reg[19:0] SRAM1_A_reg = 0;
reg[19:0] SRAM2_A_reg = 0;
reg SRAM1_OE_reg;
reg SRAM1_WE_reg;
reg SRAM2_OE_reg;
reg SRAM2_WE_reg;
reg SRAM1_WR_reg = 0;
reg SRAM2_WR_reg = 1;
reg LED_reg = 0;
reg[6:0] LED_count;
wire fPowerUp_Rst; // 得到复位波形 刚开始低,后面高
sSystemReset # (.MAX_COUNT(500000))
SystemReset
(
.iClk(CLK50M),
.iRst(1'b1),
.oRst(fPowerUp_Rst)
);
/*
//水平扫描计数
always @(posedge GS2971_CLKI)
if(!fPowerUp_Rst) x_cnt <= 1; // 0还是 1
else if(x_cnt == LinePeriod) x_cnt <= 1;
else x_cnt <= x_cnt + 1;
//垂直扫描计数
always @(posedge GS2971_CLKI)
if(!fPowerUp_Rst) y_cnt <= 1;
else if(y_cnt == FramePeriod) y_cnt <= 1;
else if(x_cnt == LinePeriod) y_cnt <= y_cnt + 1;
*/
always @(posedge GS2971_CLKI)
begin
HSYNC_delay <= GS2971_STAT[0];
VSYNC_delay <= GS2971_STAT[1];
if(~HSYNC_delay && GS2971_STAT[0])
x_cnt <= 1;
else
x_cnt <= x_cnt + 1;
if(~VSYNC_delay && GS2971_STAT[1])
y_cnt <= 1;
else if(x_cnt == LinePeriod)
y_cnt <= y_cnt + 1;
end
always @(posedge GS2971_CLKI)
begin
if(x_cnt == (1+H_delay)) GS2972_HSVNC_creat <= 1'b1;
else if(x_cnt == (H_SyncPluse + H_delay)) GS2972_HSVNC_creat <=1'b0;
/*
if(y_cnt >= (1+V_delay)%FramePeriod) GS2972_VSYNC_creat <= 1'b1;
else if(y_cnt <= (V_SyncPluse + V_delay)%FramePeriod) GS2972_VSYNC_creat <= 1'b0;
if(y_cnt >= (Vde_start + V_delay)%FramePeriod) vsync_de <= 1'b1;
else if(y_cnt <= (Vde_end + V_delay)%FramePeriod) vsync_de <= 1'b0;
*/
if(y_cnt == 750) GS2972_VSYNC_creat <= 1'b1;
else if(y_cnt == 5) GS2972_VSYNC_creat <= 1'b0;
if(y_cnt == 744) vsync_de <= 1'b0;
else if(y_cnt == 24) vsync_de <= 1'b0;
if(x_cnt == (Hde_start + H_delay)) hsync_de <= 1'b1;
else if(x_cnt == (Hde_end + H_delay)) hsync_de <= 1'b0;
/*
if((x_cnt >= Hde_start) && (x_cnt <= Hde_end))
begin
if((y_cnt >= Vde_start) && (y_cnt <= Vde_end))
begin
*/
if(GS2971_STAT[2])
begin
DATA_DI_reg[15:8] <= GS2971_DI[19:12];
DATA_DI_reg[7:0] <= GS2971_DI[9:2];
if(SRAM1_WR_reg)
begin
SRAM1_WE_reg <= 0;
SRAM1_OE_reg <= 1;
SRAM1_A_reg <= ((x_cnt - Hde_start) + H_ActivePix * (y_cnt - Vde_start));
SRAM1_D_reg <= DATA_DI_reg;
end
else
begin
SRAM1_WE_reg <= 1;
SRAM1_OE_reg <= 0;
SRAM1_A_reg <= ((x_cnt - Hde_start) + H_ActivePix * (Vde_end - y_cnt));
SRAM1_D_reg <= 16'hzzzz;
DATA_DO_reg <= SRAM1_D_reg;
end
if(SRAM2_WR_reg)
begin
SRAM2_WE_reg <= 0;
SRAM2_OE_reg <= 1;
SRAM2_A_reg <= ((x_cnt - Hde_start) + H_ActivePix * (y_cnt - Vde_start));
SRAM2_D_reg <= DATA_DI_reg;
end
else
begin
SRAM2_WE_reg <= 1;
SRAM2_OE_reg <= 0;
SRAM2_A_reg <= ((x_cnt - Hde_start) + H_ActivePix * (Vde_end - y_cnt));
SRAM2_D_reg <= 16'hzzzz;
DATA_DO_reg <= SRAM2_D_reg;
end
end
//end
else
begin
SRAM1_WE_reg <= 1;
SRAM2_WE_reg <= 1;
end
end
always @(posedge GS2971_CLKI)
begin
if((x_cnt == Hde_end) && (y_cnt == Vde_end))
begin
SRAM1_WR_reg <= ~SRAM1_WR_reg;
SRAM2_WR_reg <= ~SRAM2_WR_reg;
/*LED_count <= LED_count + 1;
if(LED_count >= 30)
begin
LED_reg <= 1 - LED_reg;
LED_count <= 0;
end*/
end
end
assign GS2971_RESET = fPowerUp_Rst;
assign GS2971_XTALL1 = CLK27M;
assign GS2972_RESET = fPowerUp_Rst;
assign GS2972_RATESEL0 = 0;
assign GS2972_RATESEL1 = 0;
assign GS2972_SDOEN = 1;
assign GS2972_PCLK = GS2971_CLKI;
/*
//assign GS2972_HSVNC = GS2971_STAT[0];
assign GS2972_HSVNC = HSYNC_delay;
//assign GS2972_VSYNC = GS2971_STAT[1];
assign GS2972_VSYNC = VSYNC_delay;
assign GS2972_FDE = GS2971_STAT[2];
*/
assign GS2972_HSVNC = GS2972_HSVNC_creat;
assign GS2972_VSYNC = GS2972_VSYNC_creat;
assign GS2972_FDE = (hsync_de && vsync_de)? 1 : 0;
assign GS2972_DO[19:12] = DATA_DO_reg[15:8];
assign GS2972_DO[9:2] = DATA_DO_reg[7:0];
assign GS2972_DO[11:10] = 0;
assign GS2972_DO[1:0] = 0;
assign SRAM1_CE = 0;
assign SRAM1_OE = SRAM1_OE_reg;
assign SRAM1_WE = SRAM1_WE_reg;
assign SRAM1_A = SRAM1_A_reg;
assign SRAM1_D = SRAM1_D_reg;
assign SRAM2_CE = 0;
assign SRAM2_OE = SRAM2_OE_reg;
assign SRAM2_WE = SRAM2_WE_reg;
assign SRAM2_A = SRAM2_A_reg;
assign SRAM2_D = SRAM2_D_reg;
assign LED = (y_cnt == (1+V_delay)) ? 1 : 0;
endmodule