资讯详情

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

前言

tft屏控制

生成测试阵列

其他说明


前言

疫情能把一个人逼到什么程度?甚至让我无聊到四年前。FPGA拿出板子做点事。

我想在一个tft在屏幕上做一个阵列,可以在屏幕上输出一些内部信号,比如状态机的状态,帮助我定位一些后续问题。这个功能有点像状态灯,但是这个板子只有四个状态灯,肯定不够,所以我想做这样的事情。

其实有些内部状态是不需要这个阵列的,用逻辑分析仪应该是比较常见的做法,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_CLK TFT屏像素时钟
LCD_Rx RGB中R的数值
LCD_Gx RGB中G的数值
LCD_Bx RGB中B的数值

控制信号太多了,最关键的三个信号是LCD_HSYNC、LCD_VSYNC、LCD_CLK。我用的屏幕是480 * 272像素,因此相应的市场信息如下:

LCD_CLK = 525 * 286 * 60(屏幕刷新率/Hz) = 9009000Hz= 9MHz,因此,模块的控制时钟是9M。板上只有50块M所以要例化一个时钟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(can_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];

 

标签: 连接器j15

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台