AX7A200教程(8): HDMI输入和输出显示1080p视频

news2025/1/20 3:37:02

文章目录

本章节主要将hdmi输入的1080p视频通过ddr3缓存,然后通过hdmi输出口输出到显示屏上显示

一, 突发读写命令

设置读写突发长度为64

//parameter define
 parameter  WRITE_LENGTH = 64;
 parameter  READ_LENGTH = 64;
 parameter  IDLE        = 3'd0;            //空闲状态
 parameter  WRITE       = 3'd1;            //写状态
 parameter  WRITE_DONE  = 3'd2;            //读到写过度等待
 parameter  READ        = 3'd3;            //读状态
 parameter  READ_DONE   = 3'd4;

1.突发写命令

当写fifo计数器rd_data_count计数大于62,执行一次写突发命令,拉高wr_len_en

    //突发写使能
    always@(posedge ui_clk or negedge i_rst_n)begin
            if(!i_rst_n)
                wr_len_en    <=  1'd0;    
            else if(ddr_wr_end)
                wr_len_en    <=  1'd0;    
            else if(rd_len_en)
                wr_len_en    <=  1'd0;    
            else if(wr_len_done)
                wr_len_en    <=  1'd0;                             
            else if(rd_data_count >= 9'd62)
                wr_len_en    <=  1'd1;                        
    end 

2.突发读命令

当读fifo计数器wr_data_count小于等于64执行一次读突发命令,拉高rd_len_en

//突发读使能
    always@(posedge ui_clk or negedge i_rst_n)begin
            if(!i_rst_n)
                rd_len_en    <=  1'd0;
            else if(ddr_rd_end)
                rd_len_en    <=  1'd0;            
            else if(wr_len_en)
                rd_len_en    <=  1'd0;     
            else if(rd_len_done)
                rd_len_en    <=  1'd0;                 
            else if(ddr_rd_en && wr_data_count <= 9'd64)
                rd_len_en    <=  1'd1;                     
    end  

从上面的读突发命令可以看出来,读突发命令rd_len_en拉高,需要fifo计数器wr_data_count小于等于64和ddr_rd_en为高才行。因读突发设置的fifo读计数器wr_data_count小于等于64才触发,开发板上电后,ddr初始化后ddr里这时并没有数据,但如果直接设置读fifo小于等于64触发,那么这时进行的突发读将会读到的是ddr里面的随机值,因为此时突发读是先开始执行的,所以加入ddr_rd_en这个信号,当ddr_rd_en拉高才能使能突发读,ddr_rd_en信号需要输入的hdmi的场信号vs计数为3开始拉高ddr_rd_en这个信号,也就是ddr写入三个帧存才开始ddr突发读。

3.突发读使能信号

将hdmi输入的vs_in场信号打拍,每次上升沿计数,当计数到3时开始拉高start_en信号

reg vs_r; 
reg [2:0] count;  
always@(posedge clk or negedge rst)begin
        if(!rst)    
            vs_r    <=  1'b0;
        else
            vs_r    <=  vs_in;
end                

always@(posedge clk or negedge rst)begin
        if(!rst)    
            count    <=  3'd0;
        else if(count == 3'd3)
            count    <=  count;    
        else if(vs_in && !vs_r)
            count    <=  count + 1'b1;
end

assign  start_en = (count == 3'd3)? 1'b1:1'b0;

可以看到start_en信号直接连接ddr_rd_en

  ddr_test ddr_test_inst (
    // Memory interface ports
    .ddr3_addr                      (ddr3_addr),  // output [13:0]		ddr3_addr
    .ddr3_ba                        (ddr3_ba),  // output [2:0]		ddr3_ba
    .ddr3_cas_n                     (ddr3_cas_n),  // output			ddr3_cas_n
    .ddr3_ck_n                      (ddr3_ck_n),  // output [0:0]		ddr3_ck_n
    .ddr3_ck_p                      (ddr3_ck_p),  // output [0:0]		ddr3_ck_p
    .ddr3_cke                       (ddr3_cke),  // output [0:0]		ddr3_cke
    .ddr3_ras_n                     (ddr3_ras_n),  // output			ddr3_ras_n
    .ddr3_reset_n                   (ddr3_reset_n),  // output			ddr3_reset_n
    .ddr3_we_n                      (ddr3_we_n),  // output			ddr3_we_n
    .ddr3_dq                        (ddr3_dq),  // inout [31:0]		ddr3_dq
    .ddr3_dqs_n                     (ddr3_dqs_n),  // inout [3:0]		ddr3_dqs_n
    .ddr3_dqs_p                     (ddr3_dqs_p),  // inout [3:0]		ddr3_dqs_p
	.ddr3_cs_n                      (ddr3_cs_n),  // output [0:0]		ddr3_cs_n
    .ddr3_dm                        (ddr3_dm),  // output [3:0]		ddr3_dm
    .ddr3_odt                       (ddr3_odt),  // output [0:0]		ddr3_odt
    .init_calib_complete            (init_calib_complete),
    // System Clock Ports
    .sys_clk_i                      (clk_out2),
    .sys_rst                        (rst_n), // input sys_rst
   //fifo
    .wr_clk                         (vin_clk),
    .rd_clk                         (video_clk),
    .write_fifo_wr_en               (vin_de),
    .write_fifo_din                 ({8'd0,vin_data[23:0]}),
    .read_fifo_rd_en                (read_en),
    .read_fifo_dout                 (read_data),
    .read_fifo_empty                (read_fifo_empty),
    .read_valid                     (read_valid),
    .ddr_rd_en                      (start_en),
    .vin_vs                         (vin_vs),
    .vout_vs                        (read_req),
    .rd_reset                       (read_req_ack)    

    ); 

二,fifo读写复位信号 

1.写fifo复位信号

hdmi输入的场信号vin_vs检测到上升沿,拉高wr_reset信号用于写fifo复位

always@(posedge ui_clk or negedge rst_n)begin
        if(!rst_n)begin
            wr_load_r0   <=  1'd0;
            wr_load_r1   <=  1'd0;
            end
        else begin
            wr_load_r0   <=  vin_vs;
            wr_load_r1   <=  wr_load_r0;
            end
end 

always@(posedge ui_clk or negedge rst_n)begin
        if(!rst_n)
            wr_reset   <=  1'd0;
        else if(wr_load_r0 && !wr_load_r1)
            wr_reset   <=  1'd1;
        else if(app_addr_wr == 0 && !(wr_load_r0 && !wr_load_r1))    
            wr_reset   <=  1'd0;
end

2.读fifo复位信号

hdmi输出的场信号vout_vs检测到上升沿,拉高rd_reset信号用于读fifo复位

always@(posedge ui_clk or negedge rst_n)begin
        if(!rst_n)begin
            rd_load_r0   <=  1'd0;
            rd_load_r1   <=  1'd0;
            end
        else begin 
            rd_load_r0   <=  vout_vs;
            rd_load_r1   <=  rd_load_r0;
            end
end

always@(posedge ui_clk or negedge rst_n)begin
        if(!rst_n)
            rd_reset   <=  1'd0;
        else if(rd_load_r0 && !rd_load_r1)
            rd_reset   <=  1'd1;
        else if(app_addr_rd == 0 && !(rd_load_r0 && !rd_load_r1))    
            rd_reset   <=  1'd0;
end 

三,帧缓存切换

从下面的ddr手册可以看出,ddr一共有8个bank,也就是这个ddr一共可以缓存8页

而且地址是[14:0],注意这里在mig选ddr型号的时候一定要注意ddr的地址务必要选[14:0]或者以上,不然就只能操作一个帧缓存,我前面的工程都是[13:0],即使写了多帧,也只能操作一帧,目前这个工程是[14:0],按照ddr手册可以最大操作8个帧存 ,当然具体可以操作多少个帧存也和mig控制器有关,如果ddr最大帧存有8个,那我们操作8个帧存或者8个以下的帧存都是可以,当然mig也必须配置相应的帧存个数,如果我们的帧存为4个那么只能操作4个或者以下的,即使你的mig设置为8个帧存,那么能操作的最大的也只能是4个,帧存说白了就是ddr的bank数。

1.mig控制器帧设置 

 bank数量设置,ddr最大的bank数为8,我们这里设置为4表示最大能操作4个帧存,也就是0,1,2,3这四页

 2.ddr写帧缓存切换

将hdmi输入的场信号vin_vs的上升沿做为计数信号,每次检测到上升沿就直接加1,因wr_page位宽为[1:0],也就是两个位宽,所以ddr写帧存在0,1,2,3之间切换

always@(posedge ui_clk or negedge rst_n)begin
        if(!rst_n)begin
            wr_load_r0   <=  1'd0;
            wr_load_r1   <=  1'd0;
            end
        else begin
            wr_load_r0   <=  vin_vs;
            wr_load_r1   <=  wr_load_r0;
            end
end 

always @(posedge ui_clk or negedge rst_n) begin
         if(!rst_n)
             wr_page    <=  2'd0;
         else if(wr_load_r0 && !wr_load_r1)
             wr_page    <=  wr_page + 1'b1;
end

3.ddr读帧缓存切换

将hdmi输出的场信号的上升沿做为计数信号,每次检测到上升沿直接将当前读ddr帧存减1,这样做的目的,就是为了让读和写不在同一个帧存,避免图像有撕裂现象(一般显示撕裂也不明显,单帧也是可以的,但为了显示效果建议还是不要在同一个帧存进行)

always@(posedge ui_clk or negedge rst_n)begin
        if(!rst_n)begin
            rd_load_r0   <=  1'd0;
            rd_load_r1   <=  1'd0;
            end
        else begin 
            rd_load_r0   <=  vout_vs;
            rd_load_r1   <=  rd_load_r0;
            end
end

always @(posedge ui_clk or negedge rst_n) begin
         if(!rst_n)
             rd_page    <=  2'd0;
         else if(rd_load_r0 && !rd_load_r1)
             rd_page    <=  wr_page - 1'b1;
end

从ddr手册看,行地址宽度是[14:0],列地址宽度为[9:0],所以ddr的寻址空间为[24:0],所以帧存控制管脚BA0,BA1,BA2,为ddr地址里25,26,27这三个管脚,2^3=8所以最大寻址控制为0~7一共8个帧存,又因我们上面mig控制器设置的是4,所以将ddr寻址的27这个管脚设置为0,直接使用25,26两个管脚来进行帧存切换,一共有0,1,2,3这样四种帧存切换,如下图所示。

hdmi输入和输出显示工程截图如下所示

工程看起来也不是很多,将黑金的hdmi输入和输出工程的axi的ddr控制全部去掉,然后把ddr读写这部分放进去,两个hdmi输入和输出的iic配置都是使用黑金的代码,ddr缓存使用前面的工程文件

四,硬件连接

hdmi输入接机箱,hdmi输出接显示屏

 五,显示效果

手机不行,只能拍出这种效果了,实际显示还是很清晰的

  工程下载链接:链接:链接:https://pan.baidu.com/s/1_3o0YiaL7cE_9mjd9fy6GQ  提取码:4clr

如若转载,请注明出处

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/813407.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SSM面试题-Spring容器的启动流程

解答: 1. BeanDefinitionReader读取配置文件(xml yml properties),创建BeanDefinition(存储bean的定义信息) 2. 配置文件读取成功后&#xff0c;将相应的配置转换成 BeanDefinition 的对象实例保存在DefaultListableBeanFactory#beanDefinitionMap 中 3. 根据配置的 BeanFacto…

fastadmin采坑之固定表格某一列

// 初始化表格table.bootstrapTable({url: $.fn.bootstrapTable.defaults.extend.index_url,pk: id,sortName: id,fixedColumns: true,fixedRightNumber: 1,columns: [[{checkbox: true},{field: id, title: __(Id)},{field: proposal_title, title: __(Proposal_title), opera…

Modbus Poll 软件----下载和安装

Modbus Poll 下载 modbus tools 官网地址&#xff1a;https://www.modbustools.com/ 步骤1 点击进入官网&#xff0c;然后点击 DOWNLOAD&#xff0c;进入下载界面。 步骤2 在下载界面&#xff0c;点击 Download 64bit &#xff0c;下载 Modbus Poll。 步骤3 下载完成 Mo…

如何生成丰富的啸叫样本?

前段时间有个公众号的朋友问我如何生成丰富的啸叫类型&#xff0c;当时回答比较简单&#xff0c;只是把啸叫产生的条件说了一下&#xff0c;后来在写AI降噪的N种数据扩增方法时候也简单提了一下使用冲激响应(Impluse Respose, IR)和增益产生啸叫&#xff0c;今天我们把这个坑填…

RabbitMQ 教程 | 第3章 客户端开发向导

&#x1f468;&#x1f3fb;‍&#x1f4bb; 热爱摄影的程序员 &#x1f468;&#x1f3fb;‍&#x1f3a8; 喜欢编码的设计师 &#x1f9d5;&#x1f3fb; 擅长设计的剪辑师 &#x1f9d1;&#x1f3fb;‍&#x1f3eb; 一位高冷无情的编码爱好者 大家好&#xff0c;我是 DevO…

第1章 JavaScript简史

JavaScript的起源 JavaScript是Netscape公司与Sun公司合作开发的在JavaScript诞生之前游览器就是显示超文本文档的简单的软件&#xff0c;JavaScript为此增加了交互行为ECMAScript是JavaScript的标准化&#xff0c;本质上是同一个语言JavaScript是一门脚本语言通常只能运行在游…

VCS ICO - Intelligent Coverage Optimization

ico是vcs提供的用于优化覆盖率的feature&#xff1b;一般用户通过dist solver bofore等约束了变量的随机概率&#xff0c;而ico会在用户约束的基础上&#xff0c;做一些自动“修正”&#xff0c;以此来优化随机激励&#xff0c;提高随机多样性&#xff0c;加速覆盖率收敛&#…

【腾讯云 Cloud Studio 实战训练营】通过云IDE构建Web3项目

文章目录 背景一、 前言二、 Cloud Studio 主要功能三、Cloud Studio 实验前期准备3.1. 注册平台 四、构建Web3项目项目中技术栈 五、其他功能演示六、常见问题及注意事项七、总结八、相关链接 ​ Cloud Studio 是基于浏览器的集成式开发环境&#xff08;IDE&#xff09;&#…

《吐血整理》进阶系列教程-拿捏Fiddler抓包教程(12)-Fiddler设置IOS手机抓包,你知多少???

1.简介 Fiddler不但能截获各种浏览器发出的 HTTP 请求&#xff0c;也可以截获各种智能手机发出的HTTP/ HTTPS 请求。 Fiddler 能捕获Android 和 Windows Phone 等设备发出的 HTTP/HTTPS 请求。同理也可以截获iOS设备发出的请求&#xff0c;比如 iPhone、iPad 和 MacBook 等苹…

每日一题——只出现一次的数字

只出现一次的数字 题目链接 思路 要求为线性时间复杂度&#xff0c;即时间复杂度为O(n)&#xff0c;那么我们就不能用简单的两层循环来解决问题 要求只能使用常量额外空间&#xff0c;即空间复杂度为O(1)&#xff0c;那么我们就不能额外开辟一个数组来记录每个元素出现的次数…

Cpp学习——通过日期类来了解Cpp中的运算符重载

目录 一&#xff0c;日期类 二&#xff0c;运算符重载 运算符重载1(比较&#xff09; 1.< 2. 复用 3.> 4.! 5.< 6.> 运算符重载2(日期加减&#xff09; 0.准备条件------计算每月的日期函数 1. 2. 3.- 4.- 5.前置 6.后置 7前置-- 6.后置-- 7.计…

「BLIP 微调指南」以 Image-Text Captioning 任务为例

前言&#xff1a;近日需要用到 BLIP 微调下游任务&#xff0c;搜索发觉如今并无 BLIP 微调教程&#xff0c;下面就以 Image-Text Captioning 任务为例&#xff0c;演示如何完成 BLIP 模型在自己数据集上的微调。 目录 1. BLIP 介绍2. 关键代码定位3. 关键参数赋值4. 模型定义&a…

Scratch 教程 之 如何四舍五入保留一个小数到指定的数位

有些时候&#xff0c;我们需要四舍五入一个多位小数到指定的位&#xff0c;但scratch并没有这个积木&#xff0c;怎么做呢&#xff1f;我来教你&#xff5e; 我们创建一个函数&#xff0c;需要时调用就行了&#xff5e; 如图&#xff0c;创建一个带参函数&#xff0c;勾选"…

《GreenPlum系列-部署维护》GreenPlum数据库Standby故障处理

一、Standby故障 1.检查监控中心数据库状态 2.查看master节点数据库状态 su - gpadmin gpstate -f二、重启数据库 1.快速关闭数据库 [gpadminmdw pg_log]$ gpstop -M fast ... Continue with Greenplum instance shutdown Yy|Nn (defaultN): > y ...2.开启数据库 [gpad…

[SSM]Spring对事务的支持

目录 十六、Spring对事务的支持 16.1事务概述 16.2引入事务场景 16.3Spring对事务的支持 Spring实现事务的两种方式 Spring事务管理API 声明式事务之注解实现方式 事务属性 事务的全注解式开发 声明式事务之XML实现方式 十六、Spring对事务的支持 16.1事务概述 什么是…

stm32 mpu6050 cubemx DMP法读取角度

文章目录 前言一、相关文件二、cubemx配置三、代码变量初始化主循环 总结 前言 文件 记录使用dmp库来读取mpu6050的角度。 这是参考文件 参考1–主要参考 github参考 参考2 参考三 一、相关文件 相关文件在这里下载&#xff08;未填&#xff0c;不过可以在上面的git中下载&a…

(树) 剑指 Offer 28. 对称的二叉树 ——【Leetcode每日一题】

❓ 剑指 Offer 28. 对称的二叉树 难度&#xff1a;简单 请实现一个函数&#xff0c;用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样&#xff0c;那么它是对称的。 例如&#xff0c;二叉树 [1,2,2,3,4,4,3] 是对称的。 1/ \2 2/ \ / \3 4 4 3但是下面这个…

在Python中导入gurobipy模块显示ModuleNotFoundError: No module named ‘gurobipy‘的解决办法

笔者在学习用pythonAnacondagurobi求解优化问题时遇到了这个问题&#xff0c;看了很多帖子的方法都没有解决&#xff0c;所以这里分享一下自己的解决办法。 首先找到自己用的Anaconda3所在位置&#xff0c;这里不再赘述。 下拉文件夹找到envs&#xff0c;双击PythonProject&…

【雕爷学编程】MicroPython动手做(18)——掌控板之声光传感器

知识点&#xff1a;什么是掌控板&#xff1f; 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片&#xff0c;支持WiFi和蓝牙双模通信&#xff0c;可作为物联网节点&#xff0c;实现物联网应用。同时掌控板上集成了OLED…

深入探索Linux文件系统与挂载点:掌握分区、挂载技巧

Linux 文件系统就是在 Linux 操作系统里咱们用来组织和管理文件的工具。它规定了文件和文件夹的结构&#xff0c;还确定了它们在存储设备上的储存方式。大致上来说&#xff0c;Linux 有很多种文件系统&#xff0c;比如 ext4、XFS、Btrfs 等。 挂载点其实就是把一个文件系统与 …