• FPGA之旅设计99例之第二十一例----VGA串口SDRAM显示图片


    一. 简介

    本例将接着上一例实现的sdram控制器进行封装。上例中只是实现了一个基本的控制器,在实际使用中,通常读写时钟是两个不同频率的,所以并不能满足要求。

    在本例中,将对读写接口进行封装,将读写接口封装成FIFO接口这样封装主要是为了让,读写的时候,满足设计要求(存储OV5640传输过来的图像,并且显示在VGA显示器上)。

    最后将设计好的接口,配置之前写好的串口以及VGA驱动,实现一个小例子。通过串口发送图片,sdram存储,vga显示。本例完成后,就可以使用此sdram模块做很多事情啦!

    欢迎关注微信公众号 FPGA之旅 回复 FPGA之旅设计99例之第二十一例 获取完整代码,以及相关软件。

    本例写的比较匆忙,望见谅。

    二. 写接口封装

    在封装的时候,使用到了FIFO IP,主要用来,外部传输图像数据到SDRAM中间的一个缓存区域,接口信号设计如下,外部给定帧地址,以及同步信号后(将写入sdram的地址复位为帧的起始地址),后面来的时候,就会依次往sdram中存储,这样外部就不需要管地址了,只需要知道存储到第几个帧的位置就可以了。帧大小以及写的突发长度,通过宏定义在sdram_defines.v文件中,方便修改。整个代码实现如下,非常简单。

    请添加图片描述

    //写正常 中转,外部写入数据暂存于此,然后写入sdram
    `include "sdram_defines.v"
    module  sdram_hpfifo_write
    (
        input                       rst_n,
        input                       write_clk,              //写时钟
        input                       write_en,               //写使能
        input[1:0]                  write_frame_addr,       //帧地址选择
        input                       write_frame_sync,       //帧同步
        input[15:0]                 write_data,
        //sdram
        input                       read_clk,
        output                      write_req,
        input                       write_ack,
    
        output[23:0]                write_addr,
        output[9:0]                 write_burst_length,
        output[15:0]                write_sdram_data,
        input                       write_data_en
    );
    
    
    wire[9:0]	rdusedw;
    reg [23:0]	read_addr_reg;
    assign		write_burst_length	    =	`burst_length;
    assign	   write_addr				=   read_addr_reg;
    assign		write_req				=	( rdusedw >= `burst_length )	 ? 1'b1 : 1'b0;
    
    always@(posedge  read_clk or negedge rst_n)
    begin
    	if( rst_n == 1'b0)
    		read_addr_reg <= 'd0;
    	else if( write_ack == 1'b1 )
    		read_addr_reg <= read_addr_reg + `burst_length;
    	else
    		read_addr_reg <= read_addr_reg;
    end
    
     fifo 	fifo_w
     (
    	.aclr			( ~rst_n 	   ),
    	.data			( write_data	 ),
    	.rdclk		( read_clk      ),
    	.rdreq		( write_data_en ),
    	
    	.wrclk		( write_clk    ),
    	.wrreq		( write_en	),
    	.q				( write_sdram_data),
    	.rdusedw		( rdusedw       ),
    	.wrusedw		()
    );
    
    
    endmodule 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    三. 读接口封装

    读接口主要用于外部从sdram读取数据,内部也调用了一个FIFO IP。信号接口,以及实现过程和写接口封装一模一样。就不做信息的说明了。

    请添加图片描述

    四. SDRAM_FIFO 模块

    封装完成后,整体的框图如下,也是非常的简介。

    请添加图片描述

    封装的实现还是比较容易的,大家可以试试不调用FIFO,自己实现一个FIFO实现。

    五. 串口-VGA-SDRAM显示图片

    为了检测封装的是否成功,通过这个小例子,就可以检测出来。如果图片显示无误,那么说明封装正确了。

    本例所使用到的模块,均是前几例中实现了的模块,所以这个例子也就是将其组合在一起。

    module	main(
    	
        input                       sys_clk,
        input                       rst_n,
    
    
    	//????
    	input                       uartrx,         /*uart rx???*/
    
    	//vga
    	output[15:0]				vga_rgb,
    	output						vga_hsync,
    	output						vga_vsync,
    	
    	input								key,
        //sdram
    	output                      sdram_clk,         //sdram clock
    	output                      sdram_cke,         //sdram clock enable
    	output                      sdram_cs_n,        //sdram chip select
    	output                      sdram_we_n,        //sdram write enable
    	output                      sdram_cas_n,       //sdram column address strobe
    	output                      sdram_ras_n,       //sdram row address strobe
    	output[1:0]                 sdram_dqm,         //sdram data enable
    	output[1:0]                 sdram_ba,          //sdram bank address
    	output[12:0]                sdram_addr,        //sdram address
    	inout[15:0]                 sdram_dq           //sdram data
    );
    
    
    wire		uart_rxs_done;
    wire[15:0]	uart_data;
    
    wire		display_data_en;
    wire[15:0]	display_data;
    
    wire		vga_clk_25M;
    wire		sdram_clk_75M;
    wire		sdram_clk_75M_Shift;
    
    
    
    reg[23:0]	cnt;
    
    reg[1:0]	read_frame_addr;
    
    
    always@(posedge vga_clk_25M or negedge rst_n)
    begin
    	if( rst_n == 1'b0)
    		read_frame_addr <= 2'b00;
    	else if( key == 1'b0)
    		read_frame_addr  <= read_frame_addr + 1'b1;
    	else
    		read_frame_addr <= read_frame_addr;
    
    end
    
    pll pll_PL(
    	.inclk0	(sys_clk),
    	.c0		(vga_clk_25M),
    	.c1		(sdram_clk_75M),
    	.c2		(sdram_clk_75M_Shift));
    
    
    
    UART_MulRX UART_MulRX_HP(
        .sys_clk					(	sys_clk			),        /*???? 50M*/
        .rst_n						(	rst_n			   ),          /*????*/
    
        .uart_rxs_done			(	uart_rxs_done	),   /*??????*/
        .odats						(	uart_data		),           /*????*/
    
        .uartrx         			(	uartrx			)/*uart rx???*/
    );
    
    
    vga_driver	vga_driver_HP(
    	.vga_clk					   (	vga_clk_25M		),
    	.rst_n						(	rst_n			),
    	
    	.display_data_en			(	display_data_en	),
    	.curr_x						(					),
    	.curr_y						(					),
    	.display_data				(	display_data	),
    	
    	.vga_rgb					   (	vga_rgb			),
    	.vga_hsync					(	vga_hsync		),
    	.vga_vsync					(	vga_vsync		)
    
    );
    
    
    sdram_hpfifo sdram_hpfifoHP(
       .sys_clk                 (  sdram_clk_75M      ),                //sdram_??
    	.sdram_clk_100M_F			 (	 sdram_clk_75M_Shift	),
       .rst_n                   (   rst_n               ),
        //?    
       .read_clk                (  vga_clk_25M          ),               //???
       .read_en                 (  display_data_en      ),                //???
       .read_frame_addr         (  read_frame_addr                  ),        //?????
       .read_fram_sync          (  vga_vsync          	),         //???
       .read_data               (  display_data         ),
    
        //?    
        .write_clk              (   sys_clk             ),              //???
        .write_en               (   uart_rxs_done       ),               //???
        .write_frame_addr       (   2'b00               ),       //?????
        .write_frame_sync       (   1'b0                ),       //???
        .write_data             (   uart_data          ),
    
          //sdram??
        .sdram_clk              (   sdram_clk          ),         //sdram clock
    	.sdram_cke              (   sdram_cke          ),         //sdram clock enable
    	.sdram_cs_n             (   sdram_cs_n         ),        //sdram chip select
    	.sdram_we_n             (   sdram_we_n         ),        //sdram write enable
    	.sdram_cas_n            (   sdram_cas_n        ),       //sdram column address strobe
    	.sdram_ras_n            (   sdram_ras_n        ),       //sdram row address strobe
    	.sdram_dqm              (   sdram_dqm          ),         //sdram data enable
    	.sdram_ba               (   sdram_ba           ),          //sdram bank address
    	.sdram_addr             (   sdram_addr         ),        //sdram address
    	.sdram_dq               (   sdram_dq           )        //sdram data
    );
    endmodule 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123

    通过串口发送图片的时候,并不需要额外去提取图像数据,像很多例程中说提到的通过其他编程语言来实现,只需要用来下面的软件即可生成。这里一定要选择生成二进制文件。

    请添加图片描述

    然后将生成好的bin文件,放入com软件中,发送即可。

    请添加图片描述

    最后的显示效果如图所示。最后上面的软件会放到本例的下载链接中。

    请添加图片描述

    ps: 测试时,本人使用的开发板跑不到100M,调试了好久,才发现这个问题,最终将时钟频率降低到了75M。

  • 相关阅读:
    同步辐射散射测试中影响效果的原因有哪些?
    快速找到需要包含函数的头文件
    代码改造:设计模式之责任链
    【数据结构】栈和队列的实现及应用
    做个小工具显示UE里地形的高度图和权重图
    nodejs+vue养老人员活体鉴权服务系统elementui
    算法笔记:哈夫曼树、哈夫曼编码
    MySQL第二弹
    springboot+vue前后端音乐网系统,挺漂亮的
    菁染料CY3/CY5.5/CY7标记替尼泊苷/鬼臼噻吩甙/肝素前体,CY3/CY5.5/CY7-Teniposide/Heparsan
  • 原文地址:https://blog.csdn.net/weixin_44678052/article/details/127463508