(1)设计定义:UART_RX模块接收数据,通过写入逻辑写入RAM存储器中,然后通过读取逻辑,从RAM中读出数据,发送给TFT显示屏。
(2)FPGA逻辑资源有限,因此设置128 * 128 像素点图片输出,首先使用画图工具制造合适的像素图片,保存为24位位图。
(3)Verilog代码编写:
- 串口数据接收模块:
module UART_RX(clk,reset_n,uart_rxd,rx_done,rx_data);input clk;input reset_n;input uart_rxd;output reg rx_done;output reg [7:0]rx_data;reg dff0_uart_rxd;reg dff1_uart_rxd;reg last_dff1_uart_rxd;wire nedge;wire w_rx_done;reg [29:0]baud_cnt;reg [3:0]bit_cnt;reg en_baud_cnt;reg [7:0]r_rx_data;parameter f_system = 50_000_000;parameter Baud = 115200; parameter MCNT = f_system/Baud;//为解决亚稳态问题,加入两个寄存器,使外部输入的异步信号uart_rx与时钟信号clk同步。 //同步化处理always@(posedge clk)begindff0_uart_rxd <= uart_rxd;dff1_uart_rxd <= dff0_uart_rxd;end//下降沿设计 always@(posedge clk)last_dff1_uart_rxd <= dff1_uart_rxd;assign nedge = last_dff1_uart_rxd && (!dff1_uart_rxd);//波特计数器模块设计always@(posedge clk or negedge reset_n)if(!reset_n)baud_cnt <= 30'd0;else if(en_baud_cnt)beginif(baud_cnt == MCNT - 1)baud_cnt <= 30'd0;else baud_cnt <= baud_cnt + 30'd1;endelse baud_cnt <= 30'd0;//位设计always@(posedge clk or negedge reset_n)if(!reset_n)bit_cnt <= 4'd0;else if(w_rx_done)bit_cnt <= 4'd0;else if(baud_cnt == MCNT - 1)bit_cnt <= bit_cnt + 4'd1;else bit_cnt <= bit_cnt;//en_baud_cnt使能信号的设计always@(posedge clk or negedge reset_n)if(!reset_n)en_baud_cnt <= 0;else if(nedge)en_baud_cnt <= 1;else if((baud_cnt == MCNT/2)&&(bit_cnt == 0)&& (dff1_uart_rxd))en_baud_cnt <= 0;else if(w_rx_done)en_baud_cnt <= 0;else en_baud_cnt <= en_baud_cnt;//接收主代码设计always@(posedge clk or negedge reset_n)if(!reset_n)r_rx_data <= 8'd0;else if(baud_cnt == MCNT/2)begincase(bit_cnt)4'd1:r_rx_data[0] <= dff1_uart_rxd;4'd2:r_rx_data[1] <= dff1_uart_rxd;4'd3:r_rx_data[2] <= dff1_uart_rxd;4'd4:r_rx_data[3] <= dff1_uart_rxd;4'd5:r_rx_data[4] <= dff1_uart_rxd;4'd6:r_rx_data[5] <= dff1_uart_rxd;4'd7:r_rx_data[6] <= dff1_uart_rxd;4'd8:r_rx_data[7] <= dff1_uart_rxd;default: r_rx_data <= r_rx_data;endcaseendelse r_rx_data <= r_rx_data;always@(posedge clk)if(w_rx_done)rx_data <= r_rx_data;else rx_data <= rx_data;//w_rx_done 和 rx_done信号的设计assign w_rx_done = (baud_cnt == MCNT/2)&&(bit_cnt == 9);always@(posedge clk)rx_done <= w_rx_done;endmodule
- ram读写逻辑控制模块:
module ram_ctrl(input clk ,input reset_n ,input clk_33M ,input [7:0] rx_data ,input rx_done ,input [9:0] hang ,input [9:0] lie ,output reg ram_wren ,output reg [13:0] rdaddress ,output reg [13:0] ram_wraddr , output [15:0] ram_w_data ,output img_display );//128*128*2 = 32768 需要一个十五位的寄存器去计数reg [14:0] done_cnt ;reg [15:0] temp_wrdata ;/* ---------------------------------------------------写逻辑部分------------------------------------------------*///串口传输完成计数器 always@(posedge clk or negedge reset_n)if(!reset_n)done_cnt <= 15'd0;else if(rx_done)done_cnt <= done_cnt + 15'd1;else done_cnt <= done_cnt;//ram写入数据寄存器 always@(posedge clk or negedge reset_n)if(!reset_n)temp_wrdata <= 16'd0;else if(rx_done)temp_wrdata <= {temp_wrdata[7:0],rx_data};else temp_wrdata <= temp_wrdata;assign ram_w_data = temp_wrdata ;//ram写使能设计 always@(posedge clk or negedge reset_n)if(!reset_n)ram_wren <= 1'd0;else if(done_cnt[0] && rx_done)ram_wren <= 1'd1;else ram_wren <= 1'd0;//ram写地址设计 always@(posedge clk or negedge reset_n)if(!reset_n)ram_wraddr <= 14'd0;else if(done_cnt[0] && rx_done)ram_wraddr <= done_cnt[14:1];else ram_wraddr <= ram_wraddr;/* ---------------------------------------------------读逻辑部分------------------------------------------------*///tft读出有效区域设计 assign img_display = (hang >= 337) && (hang < 465) && (lie >= 177) && (lie < 305) ;//ram读地址设计 always@(posedge clk_33M or negedge reset_n)if(!reset_n)rdaddress <= 14'd0;else if(img_display) rdaddress <= rdaddress + 14'd1;else rdaddress <= rdaddress; endmodule
- 顶层模块:
module tft_img_top(input clk ,input reset_n ,input uart_rxd ,output hsync ,output vsync ,output [15:0] rgb_tft ,output tft_bl ,output tft_clk ,output tft_DE );wire rx_done ;wire [7:0] rx_data ;wire clk_33M ;wire locked ;wire [9:0] hang ;wire [9:0] lie ;wire ram_wren ;wire [13:0] rdaddress ;wire [13:0] ram_wraddr ;wire [15:0] data_tft ;wire [15:0] ram_w_data ;wire [15:0] q ;wire [15:0] data_in ;wire img_display ;UART_RX UART_RX_INST(.clk (clk ),.reset_n (locked ),.uart_rxd (uart_rxd ),.rx_done (rx_done ),.rx_data (rx_data ) );pll_33M pll_33M_inst (.areset ( ~reset_n ),.inclk0 ( clk ),.c0 ( clk_33M ),.locked ( locked ) );ram_ctrl ram_ctrl_inst(.clk ( clk ),.reset_n ( locked ),.clk_33M ( clk_33M ),.rx_data ( rx_data ),.rx_done ( rx_done ),.hang ( hang ),.lie ( lie ),.ram_wren (ram_wren ),.rdaddress (rdaddress ),.ram_wraddr (ram_wraddr ), .ram_w_data (ram_w_data ),.img_display (img_display ) );myram myram_inst (.data ( ram_w_data ),.rdaddress ( rdaddress ),.rdclock ( clk_33M ),.wraddress ( ram_wraddr ),.wrclock ( clk ),.wren ( ram_wren ),.q ( q ) );assign data_in = (img_display) ? q : 16'd0 ;tft_ctrl tft_ctrl_inst(.clk_33M (clk_33M ),.reset_n (locked ),.data_in (data_in ),.hang (hang ),.lie (lie ),.hsync (hsync ),.vsync (vsync ),.rgb_tft (rgb_tft ),.tft_bl (tft_bl ),.tft_clk (tft_clk ),.tft_DE (tft_DE ) );endmodule
(4)引脚绑定:
(5)实验现象: