断断续续地学了verilog HDL和FPGA一段时间,一直没有完整的做一个东西,看到论坛上有做TFT控制器的,于是就仿制了一个.
verilog程序大部分是自己写的,一些部分如异步写入,HSync,VSync时序产生部分参考了"dzng11"
废话不说了:直接上图上资料
电路原理图如下:
verilog HDL源程序如下:
- /**********************************************************************
- 通用4.3寸tft驱动
- 地址1位
- -----------------------------------------------------------------——----
- A0=0寄存器,寄存器0-7
- 0 SRAM数据
- 1 xIdex x轴寄存器
- 2 yIdex y轴寄存器
- 3 yend 结束寄存器,用于窗口绘图加速
- 4 前景颜色
- 5 背景色
- 6
- 7 系统状态0-15位
- bo-b2 b3 b4-b6 b7-b9 b10-b12
- 背光 显示开/关 显示方式 要写入的页 当前显示页
- 必须位x00 必须位x00
- x可改变(b7) x可改变(b10)
- -----------------------------------------------------------------------
- AO=1数据
- 2011.12.5
- ***********************************************************************/
- /*
- 接口说明:
- Clk54:系统晶振,选择54M晶振
- SysRst:系统复位线.
- ExDataBus:外部16位数据总线
- ExCs:控制器片选,
- ExRs:数据批令选择
- ExWr:写信号
- ExRd:读信号
- RamAddrBus:显存地址线.
- RamDataBus:显存数据总线
- RamCs:显存片选
- RamWe:显存写选通.
- LedOn:背光控制PWM
- DE:TFT屏
- DE:VSyncTFT屏,
- HSync:TFT屏
- RGB:TFT屏
- Pclk:TFT屏);
- */
- module tft43(Clk54, SysRst, ExDataBus, ExCs, ExRs, ExWr, ExRd, RamAddrBus,
- RamDataBus, RamCs, RamWe,RamOe, LedOn, DE, VSync, HSync, RGB, Pclk);
- input Clk54, SysRst, ExCs, ExRs, ExRd, ExWr;
- inout [15:0] ExDataBus;
- inout [15:0] RamDataBus;
- output [17 : 0] RamAddrBus;
- output [15:0] RGB;
- output RamCs, RamWe,RamOe, LedOn, DE, VSync, HSync, Pclk;
- reg [2:0] ClkCnt_Q3;
- reg DotClkEn_Q;
- reg Pclk_Q;
- reg WrEn_Q;
- reg [15:0]ExBusOut_Q;
- reg [15:0] ExOutM;
- reg [15:0] WriteRgb_Q;
- reg ExWrClk_Q;
- reg ExRsR_Q;
- reg ExCsR_Q;
- reg ExRdClk_Q;
- reg ExRdClk_Q1;
- reg ExRdClk_Q2;
-
- reg ExWrClk_Q1;
- reg ExWrClk_Q2;
-
- reg [12:0] SramAddr;
- reg [15:0] PrePareData;
- reg [7:0] IndexData;
- reg InRamWe;
- reg IncAddr;
- reg XRegOver;
- reg YRegOver;
- reg AskWr;
- reg [15:0] RGB_Q;
- reg [15:0] InBusOut_Q;
- reg [8:0] XRegValue_Q;
- reg [8:0] YRegValue_Q;
- reg [15:0] SysCmdValue_Q;
- reg [2:0] RegAddr_Q;
- reg RamWeReg_Q;
- reg RamTriState_Q;
- reg [2:0] FillCount_Q;
- reg [15:0] BRGBValue_Q;
- reg [15:0] FRGBValue_Q;
- reg [17:0] RamAddrBus_Q;
- reg FillHead_Q;
- reg [8:0] HsCount_Q;
- reg [8:0] DotCount_Q;
- reg SelDispRam_Q;
- reg RamCsReg_Q;
- reg DsMark;
- reg HsMark;
- reg [1:0]DsState_Q;
- reg [1:0]HsState_Q;
- reg DE_Q;
- reg [4:0]LedCount_Q;
- reg LedOn_Q,LedOn_W;
- assign Pclk = Pclk_Q;
- assign RGB = RGB_Q;
- assign RamAddrBus = {RamAddrBus_Q};
- assign RamWe = RamWeReg_Q;
- assign RamCs = RamCsReg_Q;
- assign RamOe = RamCsReg_Q;/////
- assign RamDataBus = (RamTriState_Q | Clk54)?16'bzzzzzzzzzzzzzzzz:InBusOut_Q;
- assign VSync = DE_Q;
- assign HSync = DE_Q;//1'b0;
- assign DE = DE_Q;
- assign LedOn = LedOn_Q;
- assign ExDataBus = ExOutM;
- /*
- --1.将54M主时钟6分频,产生9M时钟并输出至引脚Pclk
- --2.输出DotClkEn为9M信号同步其他进程.高电平为1个主时钟周期,低电平5个主时钟周期
- --3.技巧: 001,010,011,100,101,110.共6个状态,高位刚好是6分频等宽.
- */
- always @(posedge Clk54 or negedge SysRst)
- begin
- if (!SysRst) begin
- ClkCnt_Q3 = 3'd1;
- Pclk_Q = 1'b0;
- DotClkEn_Q = 1'b0;
- end else begin
- if (ClkCnt_Q3[2] & ClkCnt_Q3[1]) begin
- ClkCnt_Q3 <= 3'd1;
- end else begin
- ClkCnt_Q3 <= ClkCnt_Q3 + 3'd1;
- end
- Pclk_Q <= (SysCmdValue_Q[3])?1'b0:ClkCnt_Q3[2];
- DotClkEn_Q <= ((~ClkCnt_Q3[2]) & ClkCnt_Q3[1] & ClkCnt_Q3[0]);
- end
- end
- /*
- --外部接口在RD及CS低电平期间输出内部数据
- --RS为0时输出忙信号.RS为1时输出当前地址的内部数据
- */
- always @(SysRst or ExBusOut_Q or WrEn_Q or ExCs or ExRs or ExWr or ExRd)
- begin
- if (!SysRst) begin
- ExOutM = 16'bzzzzzzzzzzzzzzzz;
- end else begin
- if ((~ExCs) & ExWr & (~ExRd)) begin
- ExOutM = (ExRs)?ExBusOut_Q:({15'd0,WrEn_Q});
- end else begin
- ExOutM = 16'bzzzzzzzzzzzzzzzz;
- end
- end
- end
- /*
- --外部异步WR写入数据.
- */
- always @(posedge ExWr or negedge SysRst)
- begin
- if (!SysRst) begin
- WriteRgb_Q = 16'd0;
- ExWrClk_Q = 1'b0;
- RegAddr_Q = 3'd0;
- end else begin
- if (!ExCs) begin
- if (!ExRs) begin
- RegAddr_Q <= ExDataBus[2:0];
- end else begin
- WriteRgb_Q <= ExDataBus;
- ExWrClk_Q <= ~ExWrClk_Q;
- end
- end
- end
- end
- /*
- --外部异步RD读出数据.
- */
- always @(negedge ExRd or negedge SysRst)
- begin
- if (!SysRst) begin
- ExRsR_Q = 1'b0;
- ExCsR_Q = 1'b1;
- end else begin
- ExCsR_Q <= ExCs;
- ExRsR_Q <= ExRs;
- end
- end
- always @(posedge ExRd or negedge SysRst)
- begin
- if (!SysRst) begin
- ExRdClk_Q = 1'b0;
- end else begin
- if ((~ExCsR_Q) & ExRsR_Q) begin
- ExRdClk_Q <= ~ExRdClk_Q;
- end
- end
- end
- /******************************************
- --主时钟打两拍同步采用外部读写信号
- ******************************************/
- always @(posedge Clk54 or negedge SysRst)
- begin
- if (!SysRst) begin
- ExRdClk_Q1 = 1'b0;
- ExRdClk_Q2 = 1'b0;
- ExWrClk_Q1 = 1'b0;
- ExWrClk_Q2 = 1'b0;
-
- end else begin
- ExRdClk_Q1 <= ExRdClk_Q;
- ExRdClk_Q2 <= ExRdClk_Q1;
- ExWrClk_Q1 <= ExWrClk_Q;
- ExWrClk_Q2 <= ExWrClk_Q1;
- end
- end
- always @(posedge Clk54 or negedge SysRst)
- begin
- if (!SysRst) begin
- InBusOut_Q = 16'd0;
- ExBusOut_Q = 16'd0;
- XRegValue_Q = 9'd0;
- YRegValue_Q = 9'd0;
- SysCmdValue_Q = 16'b0000000000110000;
- WrEn_Q = 1'b0;
- RamWeReg_Q = 1'b1;
- RamTriState_Q = 1'b1;
- RGB_Q = 16'd0;
- FillCount_Q = 3'd7;
- BRGBValue_Q = 16'd0;
- FRGBValue_Q = 16'd0;
- RamAddrBus_Q = 18'd0;
- RamCsReg_Q = 1'b1;
- PrePareData = 16'd0;
- end else begin
- if (ExRdClk_Q2 ^ ExRdClk_Q1) begin
- IncAddr = 1'b1;
- end else begin
- IncAddr = 1'b0;
- end
- if (ExWrClk_Q2 ^ ExWrClk_Q1) begin
- AskWr = 1'b1;
- end else begin
- AskWr = WrEn_Q;
- end
- XRegOver = (XRegValue_Q == 9'b111011111)?1'b1:1'b0;
- YRegOver = (YRegValue_Q == 9'b100001111)?1'b1:1'b0;
- PrePareData = WriteRgb_Q;
- IndexData[7:0] = WriteRgb_Q[7:0];
- InRamWe = 1'b1;
- if (!ClkCnt_Q3[0]) begin
- if (AskWr) begin
- case (RegAddr_Q)
- 3'b000:begin
- XRegValue_Q <= PrePareData[8:0];
- WrEn_Q <= 1'b0;
- end
- 3'b001:begin
- YRegValue_Q <= PrePareData[8:0];
- WrEn_Q <= 1'b0;
- end
- 3'b010:begin
- InRamWe = 1'b0;
- IncAddr = 1'b1;
- WrEn_Q <= 1'b0;
- end
- 3'b100:begin
- FRGBValue_Q <= PrePareData;
- WrEn_Q <= 1'b0;
- end
- 3'b101:begin
- BRGBValue_Q <= PrePareData;
- WrEn_Q <= 1'b0;
- end
- 3'b110:begin
- SysCmdValue_Q <= PrePareData;
- WrEn_Q <= 1'b0;
- end
-
- 3'b011:begin
- if (!IndexData[FillCount_Q]) begin
- PrePareData = BRGBValue_Q;
- InRamWe = SysCmdValue_Q[12];
- end else begin
- PrePareData = FRGBValue_Q;
- InRamWe = 1'b0;
- end
- IncAddr = 1'b1;
- WrEn_Q <= (FillCount_Q[0] | FillCount_Q[1] | FillCount_Q[2]);
- FillCount_Q <= FillCount_Q + 3'd7;
- end
- 3'b111:begin
- if (FillHead_Q) begin
- IncAddr = 1'b1;
- InRamWe = 1'b0;
- if (YRegOver & XRegOver) begin
- WrEn_Q <= 1'b0;
- end
- end else begin
- WrEn_Q <= 1'b1;
- end
- end
- endcase
- end
- RGB_Q <= (SysCmdValue_Q[3])?16'd0:RamDataBus;
- SramAddr[12:4] = YRegValue_Q[8:0];
- SramAddr[3:0] = XRegValue_Q[8:5];
- RamAddrBus_Q[4:0] <= XRegValue_Q[4:0];
- RamAddrBus_Q[17] <= SysCmdValue_Q[7];
- end else begin
- if (AskWr) begin
- WrEn_Q <= 1'b1;
- end
- ExBusOut_Q <= RamDataBus;
- SramAddr[12:4] = HsCount_Q[8:0];
- SramAddr[3:0] = DotCount_Q[8:5];
- RamAddrBus_Q[4:0] <= DotCount_Q[4:0];
- RamAddrBus_Q[17] <= SelDispRam_Q;
- end
- InBusOut_Q <= PrePareData;
- RamTriState_Q <= InRamWe;
- RamWeReg_Q <= InRamWe;
- SramAddr[12:0] = SramAddr[12:0] - {4'd0,SramAddr[12:4]};
- RamAddrBus_Q[16:5] <= SramAddr[11:0];
- /*根据配置字调整XY*/
- if (IncAddr) begin
- case (SysCmdValue_Q[6:4])
- 3'b001:begin
- if (XRegOver) begin
- XRegValue_Q <= 9'd0;
- end else begin
- XRegValue_Q <= XRegValue_Q + 9'd1;
- end
- end
- 3'b011:begin
- if (XRegOver) begin
- XRegValue_Q <= 9'd0;
- if (YRegOver) begin
- YRegValue_Q <= 9'd0;
- end else begin
- YRegValue_Q <= YRegValue_Q + 9'd1;
- end
- end else begin
- XRegValue_Q <= XRegValue_Q + 9'd1;
- end
- end
- 3'b110:begin
- if (YRegOver) begin
- YRegValue_Q <= 9'd0;
- end else begin
- YRegValue_Q <= YRegValue_Q + 9'd1;
- end
- end
- 3'b111:begin
- if (YRegOver) begin
- YRegValue_Q <= 9'd0;
- if (XRegOver) begin
- XRegValue_Q <= 9'd0;
- end else begin
- XRegValue_Q <= XRegValue_Q + 9'd1;
- end
- end else begin
- YRegValue_Q <= YRegValue_Q + 9'd1;
- end
- end
- default:begin
- end
- endcase
- end
- RamCsReg_Q <= SysCmdValue_Q[3];
- end
- end
- /*--产生TFT行同步*/
- always @(posedge Clk54 or negedge SysRst)
- begin
- if (!SysRst) begin
- DotCount_Q = 9'd0;
- DsState_Q = 2'd0;
- DsMark = 1'b0;
- end else begin
- if (DotClkEn_Q) begin
- case (DsState_Q)
- 2'd0:/*=>--41 相当于<= 40*/
- DsMark = (DotCount_Q[5] & DotCount_Q[3]);
- 2'd1:/*when "01" =>--2 相当于<= 1*/
- DsMark = DotCount_Q[0];
- 2'd2:/*=>--480 相当于<= 479*/
- DsMark = (DotCount_Q[0] & DotCount_Q[1] & DotCount_Q[2] & DotCount_Q[3] &
- DotCount_Q[4] & DotCount_Q[6] & DotCount_Q[7] & DotCount_Q[8]);
- 2'd3:/*--2 相当于<= 1*/
- DsMark = DotCount_Q[0];
- endcase
- DsState_Q <= DsState_Q + {1'b0,DsMark};
- DotCount_Q <= (DsMark)?9'd0:(DotCount_Q + 9'd1);
- end
- end
- end
- /*--产生TFT帧同步信号*/
- always @(posedge Clk54 or negedge SysRst)
- begin
- if (!SysRst) begin
- DE_Q = 1'b0;
- end else begin
- DE_Q <= (SysCmdValue_Q[3])?1'b0:(HsState_Q[1] & (~HsState_Q[0]) & DsState_Q[1] & (~DsState_Q[0]));
- end
- end
- /*--产生帧同步时钟*/
- always @(posedge Clk54 or negedge SysRst)
- begin
- if (!SysRst) begin
- HsCount_Q = 9'd0;
- HsState_Q = 2'd0;
- FillHead_Q = 1'b0;
- SelDispRam_Q = 1'b0;
- LedCount_Q = 5'd0;
- end else begin
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
tft43.rar
(9.52 MB, 下载次数: 112)
stm32程序.7z
(559.44 KB, 下载次数: 87)
|