基于NIOS II的液晶显示设计——TFT驱动
本设计的液晶使用的是320*240,采用的DE模式,具体的时序见本博客文章《基于TFT LCD320*240 液晶显示 —— 碰碰球》,设计思想为以SRAM为缓存器,FIFO读SRAM的数据在TFT上显示出来,NIOS II对SRAM进行读写从而对TFT控制,框架图如下:
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1、sync_level异步复位、同步释放
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
module sync_level (
clk,
clk_rst_n,
async_sig,
sync_sig);
parameter SIGNAL_WIDTH = 1;
input clk;
input clk_rst_n;
input [SIGNAL_WIDTH-1:0] async_sig;
output [SIGNAL_WIDTH-1:0] sync_sig;
reg [SIGNAL_WIDTH-1:0] sync_sig_pre, sync_sig;
always @(posedge clk or negedge clk_rst_n)
if (!clk_rst_n)
{sync_sig_pre, sync_sig} <= 2'b00;
else
{sync_sig_pre, sync_sig} <= {async_sig, sync_sig_pre};
endmodule
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2、 DE .v TFT DE model时序
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
module de (
fifo_rclk,
rclk_rst_n,
fifo_empty,
fifo_rdata,
fifo_rd,
lcd_enable,
red, green, blue);
input fifo_rclk;
input rclk_rst_n;
input fifo_empty;
input [15:0] fifo_rdata;
output fifo_rd;
output lcd_enable;
output [5:0] red, green, blue;
wire clr_cnt_h;
reg [8:0] cnt_h;
reg [7:0] cnt_v;
wire lcd_enable_h, lcd_enable_v, lcd_enable_w;
wire fifo_rd_v_en;
reg lcd_enable_w_d, lcd_enable;
reg fifo_rd_d;
reg [5:0] red, green, blue;
/////////////////////////////////////////////////////////////
// TFT LCD DE Mode timing
assign clr_cnt_h = (cnt_h >= 9'd384) ? 1'b1 : 1'b0;
always @(posedge fifo_rclk or negedge rclk_rst_n)
if (!rclk_rst_n)
cnt_h <= 0;
else if(clr_cnt_h)
cnt_h <= 0;
else
cnt_h <= cnt_h + 1'b1;
always @(posedge fifo_rclk or negedge rclk_rst_n)
if (!rclk_rst_n)
cnt_v <= 0;
else if (clr_cnt_h)
cnt_v <= cnt_v + 1'b1;
assign lcd_enable_h = (cnt_h<9'd320) ? 1'b1 : 1'b0;
assign lcd_enable_v = (cnt_v<8'd243) ? 1'b1 : 1'b0;
assign lcd_enable_w = lcd_enable_h & lcd_enable_v;
assign fifo_rd_v_en = (cnt_v<8'd240) ? 1'b1 : 1'b0;
assign fifo_rd = ~fifo_empty & lcd_enable_h & fifo_rd_v_en;
always @(posedge fifo_rclk or negedge rclk_rst_n)
if (!rclk_rst_n)
{lcd_enable, lcd_enable_w_d} <= 1'b0;
else
{lcd_enable, lcd_enable_w_d} <= {lcd_enable_w_d, lcd_enable_w};
always @(posedge fifo_rclk or negedge rclk_rst_n)
if (!rclk_rst_n)
fifo_rd_d <= 1'b0;
else
fifo_rd_d <= fifo_rd;
always @(posedge fifo_rclk or negedge rclk_rst_n)
if (!rclk_rst_n)
{red, green, blue} <= 18'd0;
else if(fifo_rd_d) begin
red <= {fifo_rdata[15:11],fifo_rdata[11]};
green <= fifo_rdata[10:5];
blue <= {fifo_rdata[4:0],fifo_rdata[0]};
end
endmodule
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3、FIFO.v Quartus II里面的FIFO
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
module fifo (
data,
rdclk,
rdreq,
wrclk,
wrreq,
q,
rdempty,
wrfull);
input [15:0] data;
input rdclk;
input rdreq;
input wrclk;
input wrreq;
output [15:0] q;
output rdempty;
output wrfull;
wire sub_wire0;
wire sub_wire1;
wire [15:0] sub_wire2;
wire rdempty = sub_wire0;
wire wrfull = sub_wire1;
wire [15:0] q = sub_wire2[15:0];
dcfifo dcfifo_component (
.wrclk (wrclk),
.rdreq (rdreq),
.rdclk (rdclk),
.wrreq (wrreq),
.data (data),
.rdempty (sub_wire0),
.wrfull (sub_wire1),
.q (sub_wire2)
// synopsys translate_off
,
.aclr (),
.rdfull (),
.rdusedw (),
.wrempty (),
.wrusedw ()
// synopsys translate_on
);
defparam
dcfifo_component.intended_device_family = "Cyclone II",
dcfifo_component.lpm_numwords = 512,
dcfifo_component.lpm_showahead = "OFF",
dcfifo_component.lpm_type = "dcfifo",
dcfifo_component.lpm_width = 16,
dcfifo_component.lpm_widthu = 9,
dcfifo_component.overflow_checking = "ON",
dcfifo_component.rdsync_delaypipe = 4,
dcfifo_component.underflow_checking = "ON",
dcfifo_component.use_eab = "ON",
dcfifo_component.wrsync_delaypipe = 4;
endmodule
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4、wr_fifo.v 产生SRAM读地址
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
module wr_fifo (
clk,
clk_rst_n,
chipselect,
//Write FIFO
fifo_full,
fifo_wr,
fifo_address);
input clk;
input clk_rst_n;
input chipselect;
input fifo_full;
output fifo_wr;
output [17:0] fifo_address;
wire fifo_wr;
reg fifo_wr_en;
reg [17:0] fifo_address;
always @(posedge clk or negedge clk_rst_n)
if(!clk_rst_n)
fifo_wr_en <= 1'b0;
else
fifo_wr_en <= 1'b1;
assign fifo_wr = fifo_wr_en & ~fifo_full & ~chipselect;
always @(posedge clk or negedge clk_rst_n)
if(!clk_rst_n)
fifo_address <=18'd320;
else if (fifo_wr) begin
if(fifo_address == 18'd76799 + 18'd320 )
fifo_address <= 18'd320;
else
fifo_address <= fifo_address + 1'b1;
end
/*
reg [8:0] x_pos,y_pos;
always@(posedge clk or negedge clk_rst_n)
begin
if(!clk_rst_n) begin
x_pos <= 9'd0;
y_pos <= 9'd0;
end
else if (fifo_wr) begin
if( x_pos == 9'd319) x_pos <= 9'd0;
else begin
x_pos <= x_pos + 1'b1;
if(y_pos == 9'd239) y_pos <= 9'd0;
else y_pos <= y_pos + 1'b1;
end
end
end
assign fifo_wdata = (x_pos < 100) ? 16'hf000 : 16'h0fc0;
*/
endmodule
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5、lcd_buffer.v NIOS II IP
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
module lcd_buffer(
clk,
rst_n,
//Avalon BUS for NIOS II
chipselect,
address,
write,
writedata,
byteenable,
read,
readdata,
//TFT LCD 320*240
ENB,
DCLK,
LEDCTRL,
RED, GREEN, BLUE,
//SRAM 256K*16bits
SRAM_ADDR,
SRAM_DQ,
SRAM_WE_N,
SRAM_OE_N,
SRAM_UB_N,
SRAM_LB_N,
SRAM_CE_N);
input clk; //system clock, 50mhz
input rst_n; //system async reset, low active
//Avalon BUS for NIOS II
input chipselect;
input[17:0] address;
input write;
input[15:0] writedata;
input[1:0] byteenable;
input read;
output[15:0] readdata;
//TFT LCD de mode, according to chapter 5.4 in ET0350G0DM6-320-240.pdf
output LEDCTRL;
output ENB; //data enable
output DCLK; //dot data clock
output [5:0] RED, GREEN, BLUE; //rgb data bits
//SRAM 256K*16bits
output[17:0] SRAM_ADDR;
inout[15:0] SRAM_DQ;
output SRAM_WE_N;
output SRAM_OE_N;
output SRAM_UB_N;
output SRAM_LB_N;
output SRAM_CE_N;
wire [17:0] fifo_address;
assign SRAM_ADDR= ( chipselect ) ? address : fifo_address;
assign SRAM_DQ = ( write & chipselect) ? writedata : 16'hzzzz;
assign SRAM_WE_N = ~write;
assign SRAM_OE_N = 1'b0;
assign SRAM_UB_N = ( chipselect ) ? ~byteenable[1] : 1'b0;
assign SRAM_LB_N = ( chipselect ) ? ~byteenable[0] : 1'b0;
assign SRAM_CE_N = 1'b0;
assign fifo_wdata = ( read & chipselect ) ? 16'hzzzz : SRAM_DQ ;
assign readdata = ( read & chipselect ) ? SRAM_DQ : 16'hzzzz ;
reg [2:0] rclk_dcnt;
wire clk_rst_n;
wire fifo_full;
wire fifo_wr;
wire [15:0] fifo_wdata;
wire fifo_rclk;
wire rclk_rst_n;
wire fifo_empty;
wire fifo_rd;
wire [15:0] fifo_rdata;
wire lcd_enable;
wire [5:0] red, green, blue;
assign LEDCTRL = 0;
//system clk divion 8, to generate fifo_rclk
always@(posedge clk or negedge clk_rst_n)
if (!clk_rst_n)
rclk_dcnt <=0;
else
rclk_dcnt <= rclk_dcnt + 1'b1;
sync_level sync_clk_rst_n (
.clk ( clk ),
.clk_rst_n ( rst_n ),
.async_sig ( 1'b1 ),
.sync_sig ( clk_rst_n ));
assign fifo_rclk = rclk_dcnt[2];
sync_level sync_rclk_rst_n (
.clk ( fifo_rclk ),
.clk_rst_n ( rst_n ),
.async_sig ( 1'b1 ),
.sync_sig ( rclk_rst_n ));
wr_fifo u_wr_fifo (
.clk ( clk ),
.clk_rst_n ( clk_rst_n ),
.chipselect ( chipselect ),
.fifo_full ( fifo_full ),
.fifo_wr ( fifo_wr ),
.fifo_address( fifo_address ));
//FIFO 18bits,512 deepth
fifo u_fifo (
.data ( fifo_wdata ),
.rdclk ( fifo_rclk ),
.rdreq ( fifo_rd ),
.wrclk ( clk ),
.wrreq ( fifo_wr ),
.q ( fifo_rdata ),
.rdempty ( fifo_empty ),
.wrfull ( fifo_full ));
de u_de (
.fifo_rclk ( fifo_rclk ),
.rclk_rst_n ( rclk_rst_n ),
.fifo_empty ( fifo_empty ),
.fifo_rdata ( fifo_rdata ),
.fifo_rd ( fifo_rd ),
.lcd_enable ( lcd_enable ),
.red ( red ),
.green ( green ),
.blue ( blue ));
//lcd interface
assign DCLK = ~rclk_dcnt[2];
assign ENB = lcd_enable;
assign RED = red;
assign GREEN = green;
assign BLUE = blue;
endmodule
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
在SOPC里面生产IP即可!