Zynq学习笔记--AXI4-Stream 图像数据从仿真输出到图像文件

news2025/1/20 1:53:17

目录

1. 简介

2. 构建工程

2.1 Vivado 工程

2.2 TestBench 代码

2.3 关键代码分析

3. VPG Background Pattern ID (0x0020) Register

4. 总结


1. 简介

使用 SystemVerilog 将 AXI4-Stream 图像数据从仿真输出到图像文件 (PPM)。

用到的函数包括 $fopen、$fwrite 和 $fclose。

PPM 格式

PPM (Portable Pixmap Format) 是一种简单的图像文件格式,用于存储彩色图像。PPM 格式很简单,主要用于科研或某些需要图像处理但不需要复杂图像格式的场合。PPM 文件通常较大,因为它们不使用压缩。一个 PPM 文件由一个文件头和图像数据体组成。文件头指定了图像的宽度、高度和最大颜色值,而数据体则包含按顺序排列的像素颜色值,每个像素颜色通常由红、绿、蓝三个颜色分量组成。

2. 构建工程

2.1 Vivado 工程

2.2 TestBench 代码

`timescale 1ns / 1ps

import axi_vip_pkg::*;
import design_1_axi_vip_0_0_pkg::*;

module tb_tpg();

bit aclk = 0, aresetn = 0;
xil_axi_resp_t 	resp;
bit tpg_tready = 1, tpg_tuser, tpg_tvalid, tpg_tlast;
bit [23:0] tpg_tdata;
integer counter_width = 0, counter_height = 0;
integer final_width = 0, final_height = 0;
integer output_file;
integer img_writing = 1, img_start = 0;

parameter integer tpg_base_address = 12'h000;
    parameter integer TPG_CONTROL_REG       = tpg_base_address;
    parameter integer TPG_ACTIVE_H_REG      = tpg_base_address + 8'h10;
    parameter integer TPG_ACTIVE_W_REG      = tpg_base_address + 8'h18;
    parameter integer TPG_BG_PATTERN_REG = tpg_base_address + 8'h20;
integer height=400, width=640;
integer pattern_id = 8'h09;

always #10ns aclk = ~aclk;

design_1_wrapper UUT (
    .aclk_50MHz     (aclk      ),
    .aresetn_0      (aresetn   ),
    .tpg_tdata      (tpg_tdata ),
    .tpg_tlast      (tpg_tlast ),
    .tpg_tready     (tpg_tready),
    .tpg_tuser      (tpg_tuser ),
    .tpg_tvalid     (tpg_tvalid));

initial begin
    #350ns aresetn = 1;
    @(posedge tpg_tuser); // Start of the first frame
    @(posedge tpg_tuser); // Start of the second frame, stop the simulation
    wait (tpg_tuser == 1'b0);
    #20ns;
    if((final_height == height)&&(final_height == height))
        $display("Resolution match, test succeeded");
    else
        $display("Resolution do not match, test failed");

    $finish;
end

design_1_axi_vip_0_0_mst_t      master_agent;
initial begin
    master_agent = new("master vip agent",UUT.design_1_i.axi_vip_0.inst.IF);
    master_agent.start_master();
    wait (aresetn == 1'b1);

    #200ns
    master_agent.AXI4LITE_WRITE_BURST(TPG_ACTIVE_H_REG, 0, height, resp);
    master_agent.AXI4LITE_WRITE_BURST(TPG_ACTIVE_W_REG, 0, width,  resp);
    master_agent.AXI4LITE_WRITE_BURST(TPG_BG_PATTERN_REG, 0, pattern_id, resp);

    #200ns
    master_agent.AXI4LITE_WRITE_BURST(TPG_CONTROL_REG, 0, 8'h81, resp);
end

always @(posedge aclk)
begin
    if((tpg_tvalid == 1) && (tpg_tready == 1)) begin
        if(tpg_tlast == 1) begin
            final_width = counter_width + 1;
            counter_width = 0;
        end
        else
            counter_width = counter_width + 1;
    end
end

always @(posedge aclk)
begin
    if((tpg_tvalid == 1) && (tpg_tready == 1)) begin
        if(tpg_tuser == 1) begin
            final_height =  counter_height;
            counter_height = 0;
        end
        else if(tpg_tlast == 1)
            counter_height = counter_height + 1;
    end
end

initial begin
    output_file = $fopen("image_out_1.ppm", "w");
    $fwrite(output_file, "P3\n");
    $fwrite(output_file, "%0d %0d\n", width, height);
    $fwrite(output_file, "%0d\n", 2**8-1);

    while(img_writing == 1) begin
        @(posedge aclk)
        #1ns;
        if ((tpg_tvalid == 1) && (tpg_tready == 1)) begin
            if((tpg_tuser == 1) && (img_start == 1)) img_writing = 0;
            else begin
                if(tpg_tuser == 1) img_start = 1;
                $fwrite(output_file, "%0d\n%0d\n%0d\n", int'(tpg_tdata[23:16]), int'(tpg_tdata[7:0]), int'(tpg_tdata[15:8]));
            end
         end
    end
    $fclose(output_file);
    $display("Image written");
end
endmodule

2.3 关键代码分析

initial begin
    output_file = $fopen("image_out_1.ppm", "w");
    $fwrite(output_file, "P3\n");
    $fwrite(output_file, "%0d %0d\n", width, height);
    $fwrite(output_file, "%0d\n", 2**8-1);
    
    while(img_writing == 1) begin
        @(posedge aclk);
        #1ns;
        if ((tpg_tvalid == 1) && (tpg_tready == 1))
        begin
            if((tpg_tuser == 1) && (img_start == 1))
                img_writing = 0;
            else begin
                if(tpg_tuser == 1) img_start = 1;
                $fwrite(output_file, "%0d\n%0d\n%0d\n",
                        int'(tpg_tdata[23:16]),
                        int'(tpg_tdata[ 7: 0]),
                        int'(tpg_tdata[15:8]));
            end
         end
    end
    $fclose(output_file);
    $display("Image written");
end

文件创建与头信息写入:

  • 使用 $fopen 函数打开(或创建)一个新的文件image_out_1.ppm,用于写入模式("w")。
  • 利用 $fwrite 函数向文件写入PPM图像的头信息:
    • "P3\n":PPM文件的格式标识,表示该文件是一个ASCII编码的彩色PPM图像。
    • "%0d %0d\n":接下来写入图像的宽度(width)和高度(height),这两个数值应该在代码的其他部分定义。
    • "%0d\n":写入颜色的最大值,这里是2**8-1,即255,表示每个颜色通道(红、绿、蓝)的最大值。

图像数据写入:

  • 代码进入一个while循环,循环条件是 img_writing 等于1,这意味着将在满足某些条件时写入图像数据。
  • 在每个时钟周期的上升沿(@(posedge aclk)),并在等待1纳秒(#1ns;)后,检查tpg_tvalid和tpg_tready信号。只有当这两个信号都为1时,才会执行数据写入的逻辑。
  • 如果tpg_tuser信号为1且img_start也为1,这表示图像数据的结束,将img_writing设置为0,退出循环。
  • 如果仅tpg_tuser为1,这意味着图像数据的开始,设置img_start为1。
  • 在其他情况下,使用$fwrite函数将图像数据(tpg_tdata)写入文件。这里的数据被分解为红、蓝、绿三个颜色通道,并按顺序写入文件。

文件关闭与信息显示:

  • 使用$fclose函数关闭文件。
  • 通过$display函数在仿真控制台显示“Image written”信息,表示图像数据已成功写入文件。
if ((tpg_tvalid == 1) && (tpg_tready == 1)) begin
    if((tpg_tuser == 1) && (img_start == 1)) img_writing = 0; // 第二帧开始后,img_writing标记为0
    else begin
        if(tpg_tuser == 1) img_start = 1; // 第一帧开始,img_start标记为1
        $fwrite(output_file, "%0d\n%0d\n%0d\n", xxx); // 第一、二帧之间,逐个像素写入
    end
 end

3. VPG Background Pattern ID (0x0020) Register

背景模式 ID 寄存器控制 TPG Core 生成的模式操作。

该寄存器根据以下值控制核心输出的模式:

  • 0x00 - 直接将视频输入传递到视频输出
  • 0x1 - 水平坡道,每个分量(RGB或Y)水平增加1
  • 0x2 - 垂直坡道,每个分量(RGB或Y)垂直增加1
  • 0x3 - 时间坡道,根据运动速度寄存器设置的值,每帧逐像素增加
  • 0x4 - 纯红色输出
  • 0x5 - 纯绿色输出
  • 0x6 - 纯蓝色输出
  • 0x7 - 纯黑色输出
  • 0x8 - 纯白色输出
  • 0x9 - 色条
  • 0xA - 区域板输出产生一个基于ROM的正弦模式。此选项依赖于运动速度、zplate水平起点、zplate水平增量、zplate垂直起点和zplate垂直增量寄存器。
  • 0xB - 方格色条
  • 0xC - 绘制十字交叉线模式
  • 0xD - 色彩扫描模式
  • 0xE - 组合的垂直和水平坡道
  • 0xF - 黑白棋盘
  • 0x10 - 伪随机模式
  • 0x11 - DisplayPort颜色坡道
  • 0x12 - DisplayPort黑白垂直线
  • 0x13 - DisplayPort彩色方块

4. 总结

本文介绍了如何使用 SystemVerilog 将 AXI4-Stream 图像数据输出到 PPM 格式的图像文件中。通过使用 $fopen、$fwrite 和 $fclose 函数,成功地将仿真生成的图像数据写入到文件中,实现了图像数据的输出。在 TestBench 代码中,设置了图像的分辨率和颜色模式,并通过循环逐像素地写入数据。通过这种方式,我们可以将仿真生成的图像数据保存为 PPM 格式的文件,方便后续的图像处理和分析。这种方法可以帮助开发人员在仿真过程中方便地将图像数据输出到文件中,以便进行后续的验证和分析工作。

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

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

相关文章

vmware esxi虚拟化数据迁移

1、启用esxi的ssh 登录esxi的web界面,选择主机-》操作——》服务——》启动ssh 2.xshell登录esxi 3、找到虚拟机所在目录 blog.csdnimg.cn/direct/d57372536a4145f2bcc1189d02cc7da8.png)#### 3在传输数据前需关闭防火墙服务 查看防火墙状态:esxcli …

Android MediaCodec 简明教程(九):使用 MediaCodec 解码到纹理,使用 OpenGL ES 进行处理,并编码为 MP4 文件

系列文章目录 Android MediaCodec 简明教程(一):使用 MediaCodecList 查询 Codec 信息,并创建 MediaCodec 编解码器Android MediaCodec 简明教程(二):使用 MediaCodecInfo.CodecCapabilities 查…

【传知代码】双深度学习模型实现结直肠癌检测(论文复现)

前言:在医学领域,科技的进步一直是改变人类生活的关键驱动力之一。随着深度学习技术的不断发展,其在医学影像诊断领域的应用正日益受到关注。结直肠癌是一种常见但危害极大的恶性肿瘤,在早期发现和及时治疗方面具有重要意义。然而…

【VSCode】快捷方式log去掉分号

文章目录 一、引入二、解决办法 一、引入 我们使用 log 快速生成的 console.log() 都是带分号的 但是我们的编程习惯都是不带分号,每次自动生成后还需要手动删掉分号,太麻烦了! 那有没有办法能够生成的时候就不带分号呢?自然是有…

C++ 特殊运算符

一 赋值运算符 二 等号作用 三 优先级和结合顺序 四 左值和右值 五 字节数运算符 条件运算符 使用条件运算符注意 逗号运算符 优先级和结合顺序 总结

如何修改开源项目中发现的bug?

如何修改开源项目中发现的bug? 目录 如何修改开源项目中发现的bug?第一步:找到开源项目并建立分支第二步:克隆分支到本地仓库第三步:在本地对项目进行修改第四步:依次使用命令行进行操作注意:Gi…

平衡二叉树的应用举例

AVL 是一种自平衡二叉搜索树,其中任何节点的左右子树的高度之差不能超过 1。 AVL树的特点: 1、它遵循二叉搜索树的一般属性。 2、树的每个子树都是平衡的,即左右子树的高度之差最多为1。 3、当插入新节点时,树会自我平衡。因此…

生信服务器配置选择说明

阿小云整理关于生信云服务器的配置选择攻略,生物信息服务器需要强大的计算能力和大容量存储,超高计算能力可以应对生物数据分析计算,如大规模基因序列比对等,大容量存储可以用来存储各种基因组、蛋白质组等数据。 生信服务器配置选…

Superset二次开发之更新 SECRET_KEY

SECRET_KEY 的作用 加密和签名:SECRET_KEY用于对敏感数据(如会话、cookie、CSRF令牌)进行加密和签名,防止数据被篡改。安全性:确保应用的安全性,防止跨站请求伪造(CSRF)攻击和会话劫持等安全问题。如何生成 SECRET_KEY openssl rand -base64 42 配置 SECRET_KEY 在sup…

VisualSVN Server/TortoiseSVN更改端口号

文章目录 概述VisualSVN Server端更改端口号TortoiseSVN客户端更改远程仓库地址 概述 Subversion(SVN)是常用的版本管理系统之一。部署在服务器上的SVN Server端通常会在端口号80,或者端口号443上提供服务。其中80是HTTP访问方式的默认端口。…

虚拟现实环境下的远程教育和智能评估系统(三)

本周继续进行开发工具的选择与学习,基本了解了以下技术栈的部署应用; 一、Seata: Seata(Simple Extensible Autonomous Transaction Architecture)是一款开源的分布式事务解决方案,旨在提供高性能和简单易…

创新实训2024.05.29日志:评测数据集与baseline测试

1. 评测工作 在大模型微调和RAG工作都在进行的同时,我们搭建了一套评测数据集。这套数据集有山东大学周易研究中心背书。主要考察大模型对于易学基本概念与常识的理解与掌握能力。 1.1. 构建评测集 在周易研究中心的指导下,我们构建出了一套用以考察大…

【并查集】专题练习

题目列表 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 模板 836. 合并集合 - AcWing题库 #include<bits/stdc.h> using lllong long; //#define int ll const int N1e510,mod1e97; int n,m; int p[N],sz[N]; int find(int a) {if(p[a]!a) p[a]find(p[a]);return p[a…

数据结构:希尔排序

文章目录 前言一、排序的概念及其运用二、常见排序算法的实现 1.插入排序2.希尔排序总结 前言 排序在生活中有许多实际的运用。以下是一些例子&#xff1a; 购物清单&#xff1a;当我们去超市购物时&#xff0c;通常会列出一份购物清单。将购物清单按照需要购买的顺序排序&…

【前端】Mac安装node14教程

在macOS上安装Node.js版本14.x的步骤如下&#xff1a; 打开终端。 使用Node Version Manager (nvm)安装Node.js。如果你还没有安装nvm&#xff0c;可以使用以下命令安装&#xff1a; curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash 然后关…

安通控股CRM数字化一阶段成功上线,重塑企业客户关系管理新格局

在数字化浪潮的席卷下&#xff0c;企业数字化转型已成为不可逆转的趋势&#xff0c;由于内循环增加、数字化转型、流量成本获客趋高等趋势作用力下&#xff0c;企业的精益化管理以围绕客户为中心构建市场竞争力的重要性日益凸显。 随着“客户为中心”理念的愈加深入&#xff0…

NFT Insider #132:Solana链上NFT销售总额达到55.49亿美元, The Sandbox成立DAO

引言&#xff1a;NFT Insider由NFT收藏组织WHALE Members&#xff08;https://twitter.com/WHALEMembers&#xff09;、BeepCrypto &#xff08;https://twitter.com/beep_crypto&#xff09;联合出品&#xff0c;浓缩每周NFT新闻&#xff0c;为大家带来关于NFT最全面、最新鲜、…

docker基本操作命令(3)

目录 1.Docker服务管理命令&#xff1a; 启动&#xff1a;systemctl start docker 停止&#xff1a;systemctl stop docker 重启&#xff1a;systemctl restart docker 开机自启&#xff1a;systemctl enable docker 查看docker版本&#xff1a; 2.镜像常用管理命令&…

k8s的ci/cd实践之旅

书接上回k8s集群搭建完毕&#xff0c;来使用它强大的扩缩容能力帮我们进行应用的持续集成和持续部署&#xff0c;整体的机器规划如下&#xff1a; 1.192.168.8.156 搭建gitlab私服 docker pull gitlab/gitlab-ce:latest docker run --detach --hostname 192.168.8.156 --publ…

数据挖掘 | 实验三 决策树分类算法

文章目录 一、目的与要求二、实验设备与环境、数据三、实验内容四、实验小结 一、目的与要求 1&#xff09;熟悉决策树的原理&#xff1b; 2&#xff09;熟练使用sklearn库中相关决策树分类算法、预测方法&#xff1b; 3&#xff09;熟悉pydotplus、 GraphViz等库中决策树模型…