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

目录

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 格式的文件,方便后续的图像处理和分析。这种方法可以帮助开发人员在仿真过程中方便地将图像数据输出到文件中,以便进行后续的验证和分析工作。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

dmdts连接kingbase8报错

dmdts连接kingbase报错 环境介绍1 人大金仓jdbc配置2 dmdts 人大金仓jdbc默认配置3 dmdts 修改jdbc配置4 达梦产品学习使用列表 环境介绍 dts版本 使用dmdts连接kingbase金仓数据库报错 无效的URL 对比jdbc连接串,修改配置解决 1 人大金仓jdbc配置 配置URL模版信息等 类名…

LabVIEW中PID控制器系统的噪声与扰动抑制策略

在LabVIEW中处理PID控制器系统中的噪声和外部扰动,需要从信号处理、控制算法优化、硬件滤波和系统设计四个角度入手。采用滤波技术、调节PID参数、增加前馈控制和实施硬件滤波器等方法,可以有效减少噪声和扰动对系统性能的影响,提高控制系统的…

2020 6.s081——Lab2:system calls

左岸的一座白色环形阶梯 浪人正在用和弦练习忧郁 晨曦下的少女听着吉他旋律 在许愿池边巴洛克式的叹息 ——许愿池的希腊少女 完整代码见:SnowLegend-star/6.s081 at syscall (github.com) System call tracing (moderate) 这个实验要求我们跟踪系统调用。 感觉实…

高级Java开发者的自我修养:深入剖析JVM垃圾回收机制及面试要点

在探索Java虚拟机(JVM)的奥秘过程中,垃圾回收机制(GC)是一个不可或缺的话题,尤其在面对大型应用和系统优化时显得尤为重要。JVM的自动内存管理是Java编程语言中一项革命性的特性,它大大简化了程…

Python——Selenium快速上手+方法(一站式解决问题)

目录 前言 一、Selenium是什么 二、Python安装Selenium 1、安装Selenium第三方库 2、下载浏览器驱动 3、使用Python来打开浏览器 三、Selenium的初始化 四、Selenium获取网页元素 4.1、获取元素的实用方法 1、模糊匹配获取元素 & 联合多个样式 2、使用拉姆达表达式 3、加上…

5.30 学习总

刷题记录(Codeforces Round 947 (Div. 1 Div. 2)B,C题)和Codeforces Round 948 (Div. 2)B题 一.B. 378QAQ and Mochas Array B. 378QAQ and Mochas Array time limit per test 1 second memory limit per test 256 megabytes in…

AI盒子在智慧加油站的应用

方案背景 为规范加油站作业,保障人民生命财产安全,《加油站作业安全规范》(AQ 3010-2007)中第五条规定:卸油作业基本要求,明确防静电、防雷电、防火、人员值守、禁止其他车辆及非工作人员进入卸油区。 痛点…

[羊城杯 2021]BabySmc

运行就是输入flag 不知道怎么跳过去的 这个应该就是smc加密的函数了 运行完这个函数才能继续往下 int __cdecl main(int argc, const char **argv, const char **envp) {__int64 v3; // rbx__int64 v4; // r12__int64 v5; // r13unsigned __int64 v6; // raxchar v7; // spcha…

迅狐跨境电商系统源码:技术栈与多端集成

随着全球化贸易的不断深入,跨境电商系统源码成为了连接不同国家和地区消费者与商家的重要桥梁。本文将探讨跨境电商系统源码的技术栈以及如何通过多端集成来提升用户体验。 技术栈概览 跨境电商系统源码的技术栈是构建高效、稳定平台的基础。以下是构建跨境电商系…

一份不知道哪里来的第十五届国赛模拟题

这是一个不知道来源的模拟题目,没有完全完成,只作代码记录,不作分析和展示,极其冗长,但里面有长按短按双击的复合,可以看看。 目录 题目代码底层驱动主程序核心代码关键:双击单击长按复合代码 …

七年之痒!一个 PHP 程序员职业生涯的自述

大家好,我是码农先森。 今年刚好是我毕业的第七个年头,在婚姻感情当中都有一种「七年之痒」的说法,这次我把这个词「七年之痒」用一次在我的职业生涯复盘上。七年前我从告别校园,踏入互联网编程行业,七年后我依旧在编…

FreeRtos进阶——中断的内部逻辑

中断与非中断API的区别 BaseType_t xQueueSendToBack(QueueHandle_t xQueue,const void *pvItemToQueue,TickType_t xTicksToWait); BaseType_t xQueueSendToBackFromISR(QueueHandle_t xQueue,const void *pvItemToQueue,BaseType_t *pxHigherPriorityTaskWok…

SpringBoot源码(自动装配、内嵌Tomcat)

文章目录 依赖管理pom依赖管理Web依赖自定义starter 一、WebMvcAutoConfiguration1.1 Filter1.2 Interceptor 二、源码解析2.1 SpringApplication2.1.1 构造方法1、填充webApplicationType2、自动装配Initializers3、自动装配Listeners 2.1.2 run(args) 2.2 SpringApplicationR…

实用软件分享---超级轻量级的强力卸载软件工具UninstallView_1.51

专栏介绍:本专栏主要分享一些实用的软件(Po Jie版); 声明1:软件不保证时效性;只能保证在写本文时,该软件是可用的;不保证后续时间该软件能一直正常运行;不保证没有bug;如果软件不可用了,我知道后会第一时间在题目上注明(已失效)。介意者请勿订阅。 声明2:本专栏的…

【OrangePi AIpro】从开箱到第一个AI应用开发

第一章 OrangePi AIpro介绍和开发环境搭建 1.1 OrangePi AIpro介绍 OrangePi AIpro(8T)采用昇腾AI技术路线,具体为4核64位处理器AI处理器,集成图形处理器,支持8TOPS AI算力,拥有8GB/16GB LPDDR4X,可以外接32GB/64GB/…

CANOE制造dll文件,以及应用dll文件

1、使用canoe自带的capl dll 2、然后使用Visual Studio 2022 打开项目 3、项目打开后修改下项目属性 4、修改capldll.cpp文件 4.1 添加的内容 void CAPLEXPORT far CAPLPASCAL appSum(long i, long j, long* s){*s i j;} {"sum", (CAPL_FARCALL)appSum, "…

FinalShell无法连接Linux

Linux使用Vmware会创建一个网络,让两个子网处于一个网关,这样就能在windows中连接Linux,只有在这种情况下才能FinalShell才能连接Linux

Redis 和 Mysql 如何保证两者数据一致性

文章目录 概述解决方案消息队列异步重试 基于 RocketMQ 的可靠性消息通信,来实现最终一致Canal 组件,监控 Mysql 中 binlog 的日志,把更新后的数据同步到 Redis 里面延时双删弱一致性和强一致性Canal详解 概述 在分布式系统中,保…

2024中国军民两用智能装备与通信技术产业展览会带你走进轻元素量子材料世界

在科技创新的浪潮中,北京怀柔科学城迎来了一场革命性的突破——世界首个轻元素量子材料平台正式启动运行。这一里程碑事件不仅彰显了中国在量子科学研究上的领先地位,也为全球科技界带来了一股新风潮。由北京大学领衔打造的这一平台,专注于轻…

[论文笔记]MemGPT: Towards LLMs as Operating Systems

引言 今天介绍一篇论文MemGPT: Towards LLMs as Operating Systems。翻过过来就是把LLM看成操作系统。 大语言模型已经在人工智能领域引起了革命性的变革,但受到有限上下文窗口的限制,在扩展对话和文档分析等任务中的效用受到了阻碍。为了能够利用超出…