使用两片BRAM,进行缓存,一片写入,一片读取,交替进行,通过地址的加减实现左右翻转。
所以图像会有一行的延时,通过自己生成时钟来解决,但是发现在列还有5个像素的延时,所以在生成H信号的时候延时了5个时钟周期。
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 20:22:03 11/11/2021
// Design Name:
// Module Name: top
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module top(
input CLK50M,
input CLK27M,
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
);
/***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 GS2972_FDE_creat;
reg vsync_de;
reg hsync_de;
reg GS2971_H = 0;
reg GS2971_V = 0;
reg GS2971_DE = 0;
reg GS2971_H_delay = 0;
reg GS2971_V_delay = 0;
reg BRAM_EN_delay = 0;
reg[10:0] x_cnt = 0;
reg[10:0] y_cnt = 0;
reg BRAM_EN = 0;
// reg BRAM_START = 0;
reg[19:0] GS2972_DO_reg = 0;
// reg[10:0] ADDR_WR1, ADDR_WR2;
reg[10:0] ADDR_RE1 = 1280;
reg[10:0] ADDR_RE2 = 0;
reg[15:0] DATA_WR1, DATA_WR2;
wire[15:0] DATA_RE1, DATA_RE2;
reg BRAM1_READ = 0;
reg BRAM2_READ = 1;
// reg BRAM1_READ_past = 1;
// reg BRAM2_READ_past = 0;
reg BRAM1_WR = 1;
reg BRAM2_WR = 0;
wire fPowerUp_Rst; // 得到复位波形 刚开始低,后面高
sSystemReset # (.MAX_COUNT(500000))
SystemReset
(
.iClk(CLK50M),
.iRst(1'b1),
.oRst(fPowerUp_Rst)
);
BRAM sBRAM1(
.clka(GS2971_CLKI), // input clka
.wea((~BRAM1_READ) & BRAM_EN), // input [0 : 0] wea
.addra(ADDR_RE1), // input [10 : 0] addra
.dina(DATA_WR1), // input [15 : 0] dina
.clkb(GS2971_CLKI), // input clkb
.addrb(ADDR_RE1), // input [10 : 0] addrb
.doutb(DATA_RE1) // output [15 : 0] doutb
);
BRAM sBRAM2(
.clka(GS2971_CLKI), // input clka
.wea((~BRAM2_READ) & BRAM_EN), // input [0 : 0] wea
.addra(ADDR_RE2), // input [10 : 0] addra
.dina(DATA_WR2), // input [15 : 0] dina
.clkb(GS2971_CLKI), // input clkb
.addrb(ADDR_RE2), // input [10 : 0] addrb
.doutb(DATA_RE2) // output [15 : 0] doutb
);
always @(posedge GS2971_CLKI)
begin
GS2971_H_delay <= GS2971_H;
end
always @(posedge GS2971_CLKI)
begin
GS2971_V_delay <= GS2971_V;
end
always @(posedge GS2971_CLKI)
begin
BRAM_EN_delay <= BRAM_EN;
end
//水平扫描计数
always @(posedge GS2971_CLKI)
if(!fPowerUp_Rst) x_cnt <= 1; // 0还是 1
else if((~GS2971_H_delay) & (GS2971_H)) x_cnt <= 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((~GS2971_V_delay) & (GS2971_V)) 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
if(x_cnt == 6) GS2972_HSVNC_creat <= 1'b1; //延时1650个时钟周期
else if(x_cnt == (H_SyncPluse + 5)) GS2972_HSVNC_creat <=1'b0;
if(y_cnt == 2) GS2972_VSYNC_creat <= 1'b1;
else if(y_cnt == (V_SyncPluse + 1)) GS2972_VSYNC_creat <= 1'b0;
if(y_cnt == (Vde_start + 1)) vsync_de <= 1'b1;
else if(y_cnt == (Vde_end + 1)) vsync_de <= 1'b0;
if(x_cnt == (Hde_start + 5)) hsync_de <= 1'b1;//延时5个时钟周期
else if(x_cnt == (Hde_end + 5)) hsync_de <= 1'b0;
end
//存储使能
always @(posedge GS2971_CLKI)
begin
GS2971_H <= GS2971_STAT[0];
GS2971_V <= GS2971_STAT[1];
GS2971_DE <= GS2971_STAT[2];
if((x_cnt >= Hde_start) & (x_cnt <= Hde_end))
begin
if((y_cnt >= Vde_start) & (y_cnt <= Vde_end))
begin
BRAM_EN <= 1;
DATA_WR1[15:8] <= GS2971_DI[19:12];
DATA_WR1[7:0] <= GS2971_DI[9:2];
DATA_WR2[15:8] <= GS2971_DI[19:12];
DATA_WR2[7:0] <= GS2971_DI[9:2];
end
else
BRAM_EN <= 0;
end
else
BRAM_EN <= 0;
end
always @(posedge BRAM_EN)
begin
BRAM1_READ <= 1 - BRAM1_READ;
BRAM2_READ <= 1 - BRAM2_READ;
end
// 写入
always @(posedge GS2971_CLKI)
begin
if(BRAM_EN)
begin
if(BRAM1_READ)
ADDR_RE1 <= ADDR_RE1 - 1;
else
ADDR_RE1 <= ADDR_RE1 + 1;
if(BRAM2_READ)
ADDR_RE2 <= ADDR_RE2 - 1;
else
ADDR_RE2 <= ADDR_RE2 + 1;
end
if(BRAM_EN)
begin
if(BRAM1_READ)
begin
GS2972_DO_reg[19:12] <= DATA_RE1[15:8];
GS2972_DO_reg[9:2] <= DATA_RE1[7:0];
end
if(BRAM2_READ)
begin
GS2972_DO_reg[19:12] <= DATA_RE2[15:8];
GS2972_DO_reg[9:2] <= DATA_RE2[7: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 = GS2972_HSVNC_creat;
assign GS2972_VSYNC = GS2972_VSYNC_creat;
// assign GS2972_FDE = GS2971_DE;
assign GS2972_FDE = (hsync_de & vsync_de)? 1 : 0;
assign GS2972_DO = GS2972_DO_reg;
endmodule
最终效果: