玩转FPGA山寨版

看了《玩转FPGA》,写的不错,写写山寨版和大家交流!

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

基于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即可!

posted on 2011-04-25 10:01  Neddy11  阅读(3041)  评论(0编辑  收藏  举报