IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 【FPGA的小娱乐】tft显示屏生成信号辅助测试阵列 -> 正文阅读

[嵌入式]【FPGA的小娱乐】tft显示屏生成信号辅助测试阵列

目录

前言

tft屏控制

测试阵列生成

其他说明


前言

论疫情可以把一个人逼到什么地步呢?甚至可以让我无聊到把4年前的FPGA板子拿出来搞点事情。

我想在一个tft屏做一个下图这样的阵列,能把内部的一些信号比如状态机的状态输出到屏幕上,辅助我定位后续的一些问题。这功能就有点类似于状态灯,只不过这个板子的状态灯只有4个,肯定是不够用的,所以我要做这么个东西出来。

实际上看内部的一些状态是不用这种阵列的,用逻辑分析仪应该是更普遍的做法,quartus ii里也有内置的逻辑分析仪:

altera小实验——SignalTap II 使用指导

不过在一些简单的场景里,一般看下状态就够了,比如某个信号是0还是1,所以做这个测试阵列还是挺有意思的。

我用的开发板是小梅哥家的AC620,芯片型号EP4CE10F17C8(N)。

tft屏控制

tft屏的控制逻辑和VGA逻辑是一样的:

VGA控制的verilog模块设计

我们再简单复习下,tft屏提供的用户接口是这样:

TP_XXX这几个信号不用关注,显然这是一组SPI的接口,还不知道怎么用在屏幕上,只看LCD这一组就够了。LCD_XXX的信号作用:

LCD_HSYNC行同步有效信号
LCD_VSYNC场同步有效信号
LCD_DE背光使能,有效输出像素点时使能
LCD_BL背光控制,直接与复位信号相连,即复位后一直打开背光
LCD_CLKTFT屏像素时钟
LCD_RxRGB中R的数值
LCD_GxRGB中G的数值
LCD_BxRGB中B的数值

控制信号呢就这么多,最关键的三个信号是LCD_HSYNC、LCD_VSYNC、LCD_CLK。我用的这个屏是480 * 272的像素,因此对应的行场信息为:

LCD_CLK = 525 * 286 * 60(屏幕刷新率/Hz) = 9009000Hz?= 9MHz,因此模块的控制时钟是9M。这块板子上只有50M的时钟,因此要例化一个PLL来生成需要的时钟。

因此我最后设计的模块,初始版的接口就是这样的:

module tft_ctrl (
	input clk,
	input rst_n,
	
	input chan_in,
	input [24 -1:0]chan_data,
	
	output [8-1:0]tft_r,
	output [8-1:0]tft_g,
	output [8-1:0]tft_b,
	output 		  tft_hs,
	output		  tft_vs,
	output 		  tft_pwm,
	output        tft_de,
	output        tft_clk,
	
	output [10-1:0]hcount,
	output [10-1:0]vcount	
);

hcount和vcount的取值范围分别是0~479和0~271,是给前级的图形生成模块看当前扫描的位置点的。那么前级的图形生成模块就可以根据当前的位置决定是否要输出,如果要在这个点输出,那么就把chan_in置为H,同时给一个{r,g,b}的24bit像素值。比如说前级模块是一个方块图形生成器,那么代码就可以这样写:

module square_gen(
	input [10-1:0]x_point,
	input [10-1:0]y_point,
	input [10-1:0]x_size,
	input [10-1:0]y_size,
	input [8 -1:0]r,
	input [8 -1:0]g,
	input [8 -1:0]b,
	input [10-1:0]hcount,
	input [10-1:0]vcount,

	input         power_en,
	
	output		  chan_en,
	output[24-1:0]chan_data
);

wire [10-1:0]x_left   = x_point;
wire [10-1:0]x_right  = (x_point + x_size >= 11'd480) ? 10'd480 : x_point + x_size;
wire [10-1:0]y_top    = y_point;
wire [10-1:0]y_bottom = (y_point + y_size >= 11'd272) ? 10'd272 : y_point + y_size;

assign chan_en   = power_en && (hcount >= x_left) && (hcount < x_right) && (vcount >= y_top) && (vcount < y_bottom);
assign chan_data = {r,g,b};
endmodule

对应的图形就是这样的:

?那么基于这种控制,就可以把tft_ctrl模块进行一下拓展:

module tft_ctrl #(
	parameter CHAN_NUM = 1
)(
	input clk,
	input rst_n,
	
	input [CHAN_NUM    -1:0]chan_in,
	input [CHAN_NUM*24 -1:0]chan_data,
	
	output [8-1:0]tft_r,
	output [8-1:0]tft_g,
	output [8-1:0]tft_b,
	output 		  tft_hs,
	output		  tft_vs,
	output 		  tft_pwm,
	output        tft_de,
	output        tft_clk,
	
	output [10-1:0]hcount,
	output [10-1:0]vcount	
);

允许有很多输入的chan_in,哪个bit有效了,就输出对应的颜色,这样就可以实现多个色块的输出了,于是这样一个模块就可以作为一个通用接口,前级做多少控制模块都可以,只要把CHAN_NUM给对,一切就都好说。

而且这样做接口的好处,就是可以简单的判断两个“物体”色块的碰撞问题。我之前在FPGA上做碰撞球、小鸟跑酷包括课设跟大佬做俄罗斯方块游戏,里面都涉及到物体碰撞的事:

?然而当时应该都没有想到通过这个chan_in来做判断(主要原因我对外提供的接口不是这样的):

OK,那么具体的代码我放在work目录的src文件夹下了,不在此赘述。

测试阵列生成

我在square_gen模块里提供了一个接口power_en,这个信号直接作用在chan_en上,也就是说如果power_en是0,那么即使到了要输出的色块也不会输出。因此待测试的信号可以把值连接到这个接口,就可以通过屏幕来观察当前值。

在定层的work中(具体文件在工程里),tft_ctrl的例化如下:

wire [16*8 -1:0]chan_in;
wire [16*8*24 -1:0]chan_data;
tft_ctrl #(.CHAN_NUM(16*8))
u_tft_ctrl(
	.clk	(clk),
	.rst_n	(rst_n),
	
	.chan_in(chan_in),
	.chan_data(chan_data),
	
	.tft_r	(tft_r),
	.tft_g	(tft_g),
	.tft_b	(tft_b),
	.tft_hs	(tft_hs),
	.tft_vs	(tft_vs),
	.tft_pwm(tft_pwm),
	.tft_de	(tft_de),
	.tft_clk(tft_clk),	
	.hcount	(hcount),
	.vcount	(vcount)
);

目的就是做8行16列的测试阵列。

阵列生成模块的例化使用generate完成:

reg[16*8 -1:0]power;

genvar i;
genvar j;
generate
for(i=0;i<8;i=i+1)begin:GEN0
	for(j=0;j<16;j=j+1)begin:GEN1
	square_gen u_squ(
	.x_point	(20*(j+1)),
	.y_point	(20*(i+1)),
	.x_size		(10),
	.y_size		(10),
	.r			(8'b10101010),
	.g			(8'b10101010),
	.b			(8'b10101010),
	.hcount		(hcount),
	.vcount		(vcount),
	.power_en	(power[i*16+j]),
	.chan_en	(chan_in[i*16+j]),
	.chan_data	(chan_data[(i*16+j)*24 +:24])
	);
	end
end
endgenerate

对外提供了power信号作为控制端。比如我有一个阵列键盘的控制模块,里面有很多控制信号,行为一直不对的话我就可以这样连接:

always @*begin
	power = {128{1'b1}};
	power[0*16 +: 16] = 16'hffff;//第一行全开,作为参考行
	power[1*16 +: 16] = key;
	power[2*16 +: 4] = row_i;
	power[3*16 +: 4] = col_o;
	power[4*16 +: 4] = row_stable;
	power[4*16 +: 4] = row_change;
	power[5*16 +: 4] = state_out;
end

最后看到的结果就是开头的那个图了:

其他说明

工程的路径:

链接:https://pan.baidu.com/s/1RE7caFvP-fKDPkwZv1B3yw?
提取码:2ooo?
?

工程中使用了PLL,50M to 9M,在工程中创建即可,我太久没用quartus ii了,找了半天一直跟Qsys那较劲:

使用了以下管脚,具体的摆放在工程里有:

没有做时序约束,所以可以看编译区对应时序分析是红的,9M时钟的一个系统,我觉得不做也无所谓,没有啥违规的风险:

具体TFT的管脚对应关系,我习惯写一个.v文件,在.v里做分配,先对齐到FPGA的输出,再对到TFT屏幕的管脚:

//assign PIN_F16 = rst_n;//TFT_RESET
assign PIN_F13 = 1'b0;//TFT TS_PEN, SPI
assign PIN_G15 = 1'b0;//TFT TS_CLK, SPI
assign PIN_F15 = 1'b0;//TFT TS_MISO, SPI
assign PIN_G11 = 1'b0;//TFT TS_MOSI, SPI
assign PIN_F14 = 1'b0;//TFT TS CS, SPI
assign PIN_J12 = tft_pwm;
assign PIN_J11 = tft_de;
assign PIN_J14 = tft_vs;
assign PIN_K11 = tft_hs;
assign PIN_J15 = tft_clk;
assign PIN_J16 = tft_b[7];
assign PIN_K15 = tft_b[6];
assign PIN_K16 = tft_b[5];
assign PIN_J13 = tft_b[4];
assign PIN_L15 = tft_b[3];
assign PIN_L12 = tft_g[7];
assign PIN_K12 = tft_g[6];
assign PIN_L13 = tft_g[5];
assign PIN_M12 = tft_g[4];
assign PIN_L14 = tft_g[3];
assign PIN_N16 = tft_g[2];
assign PIN_P16 = tft_r[7];
assign PIN_N15 = tft_r[7];
assign PIN_R16 = tft_r[6];
assign PIN_P15 = tft_r[4];
assign PIN_N14 = 1'b0;//TFT NC
assign PIN_N13 = tft_r[3];

?

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-05-19 12:00:56  更:2022-05-19 12:01:42 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 0:51:02-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码