news 2026/8/7 18:00:39

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

作者头像

张小明

前端开发工程师

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/7 18:00:24

Windows 11精简终极指南:用tiny11builder打造高效纯净系统

Windows 11精简终极指南:用tiny11builder打造高效纯净系统 【免费下载链接】tiny11builder Scripts to build a trimmed-down Windows 11 image. 项目地址: https://gitcode.com/GitHub_Trending/ti/tiny11builder 还在为Windows 11的臃肿而烦恼吗&#xff1…

作者头像 李华
网站建设 2026/8/7 18:00:18

免费和付费ai整理会议纪要对比评测差多少?2026年实测后给你靠谱结论

先回答用户真正关心的问题 2026年我拿职场新人常用的入职培训、产品学习场景实测下来,免费和付费AI整理会议纪要的核心差不是功能数量,是场景适配能力:免费版大多带时长额度限制、只支持基础转写,适合单次短录音;付费…

作者头像 李华
网站建设 2026/8/7 18:00:15

苹果手机音频转文字怎么选?2026性价比对比评测:花39元每月省16小时

先说明白核心判断 苹果手机选音频转文字工具,核心要匹配职场新人整理入职培训记录、梳理产品知识的需求,不能只看转写功能,还要看能不能帮你省整理时间。根据我当前版本的实际试用,对于高频需要转写整理的新人,月均约…

作者头像 李华
网站建设 2026/8/7 17:59:25

ESP32智能语音助手:5分钟打造你的AI聊天机器人伴侣

ESP32智能语音助手:5分钟打造你的AI聊天机器人伴侣 【免费下载链接】xiaozhi-esp32 An MCP-based chatbot | 一个基于MCP的聊天机器人 项目地址: https://gitcode.com/GitHub_Trending/xia/xiaozhi-esp32 还在为智能家居设备缺乏人性化交互而烦恼&#xff1f…

作者头像 李华
网站建设 2026/8/7 17:56:38

Unity脚本编译速度优化:10个实战技巧提升开发效率

1. 项目概述:为什么Unity脚本编译速度是开发者的“生命线” 如果你是一名Unity开发者,尤其是项目规模稍大、脚本数量超过几百个之后,一定对那个熟悉的“旋转进度条”又爱又恨。爱的是,它意味着代码正在被编译,新功能即…

作者头像 李华