目录
- 前言
- 一、安装器件库
- 二、仿真工程操作
- 1、进入文件列表
- 2、找到bounding_box_locate.vt,双击打开文件
- 3、修改路径
- 4、路径设置
- 5、切换回“Hierarchy”,即工程界面
- 6、运行仿真
- 7、查看波形
- 重点:调试问题
- 三、仿真代码
- 1、仿真顶层文件
- 2、绘制包围盒模块
- 四、工程获取
前言
前面写了几篇关于运动目标检测的文章了:
1、基于FPGA:运动目标检测(VGA显示,原理图+源码+硬件选择)
2、基于FPGA:运动目标检测(LCD显示+串口输出,纯Verilog工程)
3、基于FPGA:运动目标检测(补充仿真结果,可用毕设)
LCD显示、VGA显示都做完了,这篇文章补充一下包围盒的仿真代码,下载工程可以直接运行仿真。
一、安装器件库
因为仿真占用逻辑资源比较多,这里需要用的cyclone V的器件库,如果没有的,自己安装(最好是Quartus II 18.0以上)
18.0器件库链接:https://www.intel.com/content/www/us/en/software-kit/667160/intel-quartus-prime-standard-edition-design-software-version-18-0-for-windows.html
在这里面就能找到了。其他版本可以自己选。(下载的时候,最好自己用邮箱注册一个英特尔账号)
下载完器件库,把器件库放在quartus的安装目录的bin目录下,然后在win开始页,选择Device Installer,进行安装。
选择Bin路径
一路nex。
二、仿真工程操作
1、进入文件列表
2、找到bounding_box_locate.vt,双击打开文件
3、修改路径
在右侧窗口中找到45~47行,修改里面的文件路径,如果不知道怎么修改请看第4条
4、路径设置
路径修改主要是确保doc文件夹路径要正确,因为在你的电脑上解压存放的路径和我的路径不一定一样,比如在我电脑上doc路径是:F:\FPGA\FPGA\bounding_box_locate\doc,注意在修改3中的路径时单斜杠要换成双斜杠;
5、切换回“Hierarchy”,即工程界面
6、运行仿真
点击“Tools”–“Run Simulation Tool”–“RTL Simulation”
7、查看波形
仿真开始后可以在“Wave”窗口看到波形,仿真完成会自动停止
重点:调试问题
问题1:
如果第6步点了之后,出现这个界面,证明你的quartus没有安装modelsim,或者指定modelsim路径。
这个时候,需要点击Tools-Options…
添加正确真实的ModelSim-Altera安装路径。
问题2:
Error: (vish-42) Unsupported ModelSim library format for "F:/FPGA/FPGA/bounding_box_locate/par/simulation/modelsim/rtl_work". (Format: 4)
这种问题多出现在拷贝别人的工程然后直接打开进行仿真,或者电脑软件重装且Modelsim软件降版之后。
实际原因为工程中已经有的编译生成的仿真库文件版本比正在使用的仿真软件版本高,导致现在版本的Modelsim无权限去删除旧的库文件以重新生成新的库文件。所以报这个错误。
解决办法:
手动将当前工程目录(注意,是当前工程目录,不是你的Quartus或者Modelsim软件安装目录,这种低级理解性错误很多人都犯),你当前仿真的是哪个工程,就把这个工程目录下的simulation文件夹删除了,然后重新运行仿真就可以了。
问题3:
#** Error: (vlog-7) Failed to open design unit file "F:/FPGA/FPGA/bounding_box_locate/par/simulation/modelsim/bounding_box_locate.vt" in read mode.
因为很乖巧,按问题2我说的方法解决了问题2,所以就出现了问题3🐸
这个问题,很明显,就是在simulation文件夹下,有bounding_box_locate.vt,然后被你删除了🐸
到这里应该就没有其他问题了,一些路径过长,路径有空格,中文的,记得不要有。
三、仿真代码
1、仿真顶层文件
//功能:绘制包围盒模块
module bounding_box_top#(parameter MAX_NUM = 8 ,parameter GAP_THR = 60 ,//离散阈值,即任意白点到某个已存在的包围盒距离小于等于GAP_THR则归属于此包围盒parameter CW = 10 , //cordinate widthparameter BOX_COLOR = 24'hff_00_00//包围盒默认红色)
(input clk ,input rst_n ,//原始图像input i_vsync,input i_hsync,input i_clken,input [23:0] i_data ,////目标检测并二值化后图像input i_vsync_bin,input i_hsync_bin,input i_clken_bin,input [0:0] i_data_bin ,////目标数量output [$clog2(MAX_NUM)-1:0] obj_num,//原始图像添加包围盒后的图像output o_vsync,output o_hsync,output o_clken,output [23:0] o_data //
);
wire post1_frame_vsync;
wire post1_frame_href ;
wire post1_frame_clken;
wire [7:0] post1_frame_data ;wire [CW*MAX_NUM-1:0] x_min;
wire [CW*MAX_NUM-1:0] x_max;
wire [CW*MAX_NUM-1:0] y_min;
wire [CW*MAX_NUM-1:0] y_max;
multy_locate#(.MAX_NUM(MAX_NUM),//支持的最大目标数量.GAP_THR(GAP_THR),//离散阈值,即任意白点到某个已存在的包围盒距离小于等于GAP_THR则归属于此包围盒.CW (CW )//cordinate width)u_multy_locate_0
(.clk (clk ) ,.rst_n (rst_n ) ,.i_vsync(i_vsync_bin) ,.i_hsync(i_hsync_bin) ,.i_clken(i_clken_bin) ,.i_data (i_data_bin ) ,//binary data.obj_num(obj_num ) ,//检测到的目标个数.x_min (x_min ) ,//目标的包围盒坐标.x_max (x_max ) ,//目标的包围盒坐标.y_min (y_min ) ,//目标的包围盒坐标.y_max (y_max ) //目标的包围盒坐标
);
// bounding_box_locate #(
// .MAX_NUM (MAX_NUM ) ,
// .GAP_THR (GAP_THR) ,//离散阈值,即任意白点到某个已存在的包围盒距离小于等于GAP_THR则归属于此包围盒
// .CW (CW) //cordinate width
// )u_bounding_box_locate_0
// (
// .clk (clk),
// .rst_n(rst_n),
// .i_vsync(i_vsync_bin),
// .i_hsync(i_hsync_bin),
// .i_clken(i_clken_bin),
// .i_data (i_data_bin ),//binary data
// .o_valid(),
// .x_min(x_min),
// .x_max(x_max),
// .y_min(y_min),
// .y_max(y_max)
// );
wire [MAX_NUM-1:0] i_vsync_w;
wire [MAX_NUM-1:0] i_hsync_w;
wire [MAX_NUM-1:0] i_clken_w;
wire [23:0] i_data_w[MAX_NUM-1:0];
wire [MAX_NUM-1:0] o_vsync_w;
wire [MAX_NUM-1:0] o_hsync_w;
wire [MAX_NUM-1:0] o_clken_w;
wire [23:0] o_data_w[MAX_NUM-1:0];
//使用generate语句循环例化多个bounding_box_draw模块,每个bounding_box_draw模块画一个包围盒,同时产生一个时钟的数据延迟
generate
genvar m;
for(m=0;m<MAX_NUM;m=m+1)begin:u_drwif(m==0)begin:u_drw_0bounding_box_draw#(.BOX_COLOR ( BOX_COLOR ),//包围盒默认红色.CW ( CW ) //cordinate width) u_bounding_box_draw_0(.clk (clk ),.rst_n (rst_n),.i_vsync(i_vsync) ,.i_hsync(i_hsync) ,.i_clken(i_clken) ,.i_data (i_data ) ,.x_min (x_min[(m+1)*CW-1-:CW]),.x_max (x_max[(m+1)*CW-1-:CW]),.y_min (y_min[(m+1)*CW-1-:CW]),.y_max (y_max[(m+1)*CW-1-:CW]),.o_vsync(o_vsync_w[m]),.o_hsync(o_hsync_w[m]),.o_clken(o_clken_w[m]),.o_data (o_data_w[m]) //binary data);endelse begin:u_drw_mbounding_box_draw#(.BOX_COLOR ( BOX_COLOR ),//包围盒默认红色.CW ( CW ) //cordinate width) u_bounding_box_draw_0(.clk (clk ),.rst_n (rst_n),.i_vsync(o_vsync_w[m-1]),.i_hsync(o_hsync_w[m-1]),.i_clken(o_clken_w[m-1]),.i_data (o_data_w[m-1] ),.x_min (x_min[(m+1)*CW-1-:CW]),.x_max (x_max[(m+1)*CW-1-:CW]),.y_min (y_min[(m+1)*CW-1-:CW]),.y_max (y_max[(m+1)*CW-1-:CW]),.o_vsync(o_vsync_w[m]),.o_hsync(o_hsync_w[m]),.o_clken(o_clken_w[m]),.o_data (o_data_w[m] ) //binary data);end
end
endgenerate
assign o_vsync = o_vsync_w[MAX_NUM-1];
assign o_hsync = o_hsync_w[MAX_NUM-1];
assign o_clken = o_clken_w[MAX_NUM-1];
assign o_data = o_data_w[MAX_NUM-1] ;
endmodule
2、绘制包围盒模块
//功能:绘制包围盒模块
module bounding_box_draw#(parameter BOX_COLOR = 24'hff_00_00,//包围盒默认红色parameter CW = 12 //cordinate width)
(input clk ,input rst_n ,input i_vsync,input i_hsync,input i_clken,input [23:0]i_data ,//binary datainput [CW-1:0] x_min,x_max,y_min,y_max,output reg o_vsync,output reg o_hsync,output reg o_clken,output reg [23:0]o_data //binary data
);
reg [CW-1:0] x_cnt,y_cnt;//当前输入的像素坐标
reg i_vsync_r,i_hsync_r,i_vsync_neg_r;
wire i_vsync_neg,i_hsync_neg;
assign i_vsync_neg = ~i_vsync && i_vsync_r;//vsyn下降沿检测
assign i_hsync_neg = ~i_hsync && i_hsync_r;//hsyn下降沿检测
//产生i_vsync_r、i_hsync_r逻辑
always@(posedge clk or negedge rst_n)
if(~rst_n)begini_vsync_r <= 1'b0;i_hsync_r <= 1'b0;end
elsebegini_vsync_r <= i_vsync;i_hsync_r <= i_hsync;end
//产生x_cnt,y_cnt逻辑
always @(posedge clk or negedge rst_n)
if(~rst_n) //复位,包围盒坐标全部清零,坐标全零的包围盒视为不存在beginx_cnt <= 'd0;y_cnt <= 'd0;end
else if(i_vsync_neg)beginx_cnt <= 'd0;//每帧结束清空坐标计数器y_cnt <= 'd0;//每帧结束清空坐标计数器 end
elsebegin //坐标计数器计数x_cnt <= i_hsync_neg?'d0:(i_clken?x_cnt+1'b1:x_cnt);//hsyn下降沿清零,i_clken高电平时自增1y_cnt <= i_hsync_neg?y_cnt+1'b1:y_cnt;//hsyn下降沿自增1 end
//包围盒着色
always@(posedge clk or negedge rst_n)
begin
if(~rst_n) //复位begino_vsync <= 1'b0;o_hsync <= 1'b0;o_clken <= 1'b0;o_data <= 'd0; end
else begino_vsync <= i_vsync; o_hsync <= i_hsync; o_clken <= i_clken; if( (( (x_cnt+2'd3 >= x_min && x_cnt <= x_min) || (x_cnt <= x_max+2'd3 && x_cnt >= x_max)) && y_cnt+2'd3 >= y_min && y_cnt <= y_max+2'd3) || (( (y_cnt+2'd3 >= y_min && y_cnt <= y_min) || (y_cnt <= y_max+2'd3 && y_cnt >= y_max)) && x_cnt+2'd3 >= x_min && x_cnt <= x_max+2'd3) ) o_data <= BOX_COLOR;else o_data <= i_data;end
end
endmodule
四、工程获取
1、直接点击下载:
基于FPGA:运动目标包围盒仿真(Quartus+modelsim)
注:如果点击无效,证明资源还在审核。
2、私信我或添加邮箱获取