FPGA部分
2021年10月11日
(1)D触发器的Q是在D端数据到达后下一个时钟上升沿输出
(2)
(*ram_style="distributed"*) reg [0:31] MyMem [0:7];
定义了7个32bit长度的数组,
这里的内存可以使用FPGA的分布式
RAM实现,也可以使用BRAM来实现,取决于关键词
distributed或者
block
(3)可以使用`define以及`ifdef以及`endif等指令
`define Y;
`ifdefY
Z=1;
`else
Z=0;
`endif
(4)clk信号的写法
时钟激励产生方法一:50%占空比时钟
----------------------------------------------------------------*/
parameter ClockPeriod=10;
initial begin
clk_i=0;
forever
#(ClockPeriod/2) clk_i=~clk_i;
end
/*----------------------------------------------------------------
时钟激励产生方法二:50%占空比时钟
----------------------------------------------------------------*/
initial begin
clk_i=0;
end
always #(ClockPeriod/2) clk_i=~clk_i;
/*----------------------------------------------------------------
时钟激励产生方法三:产生固定数量的时钟脉冲
----------------------------------------------------------------*/
initial begin
clk_i=0;
repeat(6)
#(ClockPeriod/2) clk_i=~clk_i;
end
/*----------------------------------------------------------------
时钟激励产生方法四:产生非占空比为50%的时钟
----------------------------------------------------------------*/
initial begin
clk_i=0;
forever begin
#((ClockPeriod/2)-2)clk_i=0;
#((ClockPeriod/2)+2)clk_i=1;
end
end
(5)复位信号怎么写
/*----------------------------------------------------------------
复位信号产生方法一:异步复位
----------------------------------------------------------------*/
initial begin
rst_n_i=1;
#100;
rst_n_i=0;
#100;
rst_n_i=1;
end
/*----------------------------------------------------------------
复位信号产生方法二:同步复位
----------------------------------------------------------------*/
initial begin
rst_n_i=1;
clk_i=0;
@(negedge clk_i) rst_n_i=0;
#100;//固定时间复位
repeat(10) @(negedge clk_i);//固定周期数复位
@(negedge clk_i)
rst_n_i=1;
end
always #5 clk_i=~clk_i;
/*----------------------------------------------------------------
复位信号产生方法三:复位任务封装
----------------------------------------------------------------*/
task reset;
input [31:0] reset_time;//复位时间可调,输入复位时间
RST_ING=0;//复位方式可调,低电平或高电平
begin
rst_n=RST_ING;//复位中
#reset_time;//复位时间
rst_n=~RST_ING;//撤销复位,复位结束
end
endtask
(6)双向信号inout
如果inout在testbench中定义为wire型变量(表示输出),使用force来进行初始化的操作。
如果待测试文件中存在双向信号(inout)需要注意,需要一个
reg变量
来表示输入,一个
wire变量
表示输出;
双向信号描述:强制force
----------------------------------------------------------------*/
//当双向端口作为输出口时,不需要对其进行初始化,而只需开通三态门;当双向端口作为输入时,只需要对其初始化并关闭三态门,初始化赋值需
使用wire型数据,通过force命令来对双向端口进行输入赋值。
assign dinout=(!en)din:16'hz;完成双向赋值
initial begin
force dinout=20;
#200
force dinout=dinout-1;
end
(7)触发的两种
@是沿出发,而wait则是电平触发的一种方式。
//@使用沿触发
//wait语句都是使用电平触发
initial begin
start=1'b1;
wait(en==1'b1); //wait使用电平触发的机制
#10;
start=1'b0;
end
(8)仿真控制语句及系统任务描述
/*----------------------------------------------------------------
仿真控制语句及系统任务描述
----------------------------------------------------------------*/
$stop //停止运行仿真,modelsim中可继续仿真
$stop(n) //带参数系统任务,根据参数0,1或2不同,输出仿真信息
$finish //结束运行仿真,不可继续仿真
$finish(n) //带参数系统任务,根据参数0,1或2不同,输出仿真信息
//0:不输出任何信息
//1:输出当前仿真时刻和位置
//2:输出当前仿真时刻、位置和仿真过程中用到的memory以及CPU时间的统计
$random //产生随机数
$random%n //产生范围-n到n之间的随机数
{$random}%n //产生范围0到n之间的随机数
/*----------------------------------------------------------------
仿真终端显示描述
----------------------------------------------------------------*/
$monitor //仿真打印输出,打印出仿真过程中的变量,使其终端显示,如果发生了变化就会输出一次
/*
$monitor($time,,,"clk=%d reset=%d out=%d",clk,reset,out);
*/
$display //终端打印字符串,显示仿真结果等
/*
$display(”Simulation start!");
$display(”At time %t,input is %b %b %b,output is %b",$time,a,b,en,z);
*/
$time //返回64位整型时间
$stime //返回32位整型时间
$realtime //实行实型模拟时间
/*----------------------------------------------------------------
文本输入方式:$readmemb / $readmemh
----------------------------------------------------------------*/
//激励具有复杂的数据结构
//verilog提供了读入文本的系统函数
$readmemb/$readmemh("<数据文件名>",<存储器名>);
$readmemb/$readmemh("<数据文件名>",<存储器名>,<起始地址>);
$readmemb/$readmemh("<数据文件名>",<存储器名>,<起始地址>,<结束地址>);
$readmemb:/*读取二进制数据,读取文件内容只能包含:空白位置,注释行,二进制数
数据中不能包含位宽说明和格式说明,每个数字必须是二进制数字。*/
$readmemh:/*读取十六进制数据,读取文件内容只能包含:空白位置,注释行,十六进制数
数据中不能包含位宽说明和格式说明,每个数字必须是十六进制数字。*/
/*当地址出现在数据文件中,格式为@hh...h,地址与数字之间不允许空白位置,可出现多个地址*/
//例子
module
reg[7:0]memory[0:3];//声明4个8位存储单元
integer i;
initial begin
$readmemh("D:/mem.dat",memory);//读取系统文件到存储器中的给定地址,mem.dat路径可以给出绝对地址
//显示此时存储器内容
for(i=0;i<4;i=i+1)
$display("Memory[%d]=%h",i,memory[i]);
end
endmodule
/*mem.dat文件内容
@001 //到第一个地址的位置,那么默认的地址 @0000 为XX 未知态
AB CD //@0001 AB
@003 //@0002 CD
A1 //@0003 A1
*/
//仿真输出为
Memory[0]=xx;
Memory[1]=AB;
Memory[2]=CD;
Memory[3]=A1;
2021年10月12日
(9)对于zu的差分时钟原语,可以使用
IBUFGDS来产生时钟信号,它相比较于IBUFDS,是xilinx的专用时钟信号转换。
//对差分时钟使用IBUFGDS IP核去进行转换
IBUFGDS CLK_U(
.I(diff_clock_clk_p),
.IB(diff_clock_clk_n),
.O(CLK_i)
);
(10)对于ZYNQUltarScale+为了减少bit文件大小,提高加载速度,在管脚约束文件中添加如下代码
#bitcompress 比特流压缩
set_property BITSTREAM.GENERAL.COMPRESS true[current_design]
备注:
如果你是
ZYNQ的FPGA,由于ZYNQ的FLASH不是通过FPGA加载的,而是通过ARM,那么只要以下几行代码:
set_property CFGBVS VCCO [current_design]
set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property BITSTREAM.GENERAL.COMPRESS true [current_design]
如果你是
ZYNQUltarScale+的FPGA,那么只要以下几行代码:
set_property BITSTREAM.GENERAL.COMPRESS true[current_design]
(11)怎么写XDC文件?
set_property IOSTANDARD LVCMOS12 [get_ports <name>]
set_property PACKAGE_PIN <PIN> [get_ports <name>]
时钟约束的模板如下,单位为ns:
create_clock -name<clock_name> -period<period> [get_ports<clockport>]
create_clock -name sys_clk -period 8 [get_ports diff_clock_clk_p]
set_property IOSTANDARD LVDS [get_ports diff_clock_clk_p]
set_property IOSTANDARD LVDS [get_ports diff_clock_clk_n]
set_property PACKAGE_PIN H9 [get_ports diff_clock_clk_p]
set_property PACKAGE_PIN G9 [get_ports diff_clock_clk_n]
set_property IOSTANDARD LVCMOS12 [get_ports RST_i]
set_property PACKAGE_PIN AL10 [get_ports RST_i]
set_property IOSTANDARD LVCMOS12 [get_ports {LED_o[0]}]
set_property PACKAGE_PIN AL11 [get_ports {LED_o[0]}]
set_property IOSTANDARD LVCMOS12 [get_ports {LED_o[1]}]
set_property PACKAGE_PIN AL13 [get_ports {LED_o[1]}]
set_property BITSTREAM.GENERAL.COMPRESS true[current_design]
(12)程序的固化
(13)输出时钟源的种类
DPLL时钟源 是DDR的PLL产生的
APLL时钟源 是APU的PLL产生的
RPLL时钟源 是RPU的PLL产生的
IOPLL时钟源 是IO的PLL产生的
VPLL时钟源 是DP的PLL产生的
(14)
IRQ的全称是“
Interupt ReQuest"
如果图片上的IRQ0为1,那么在zynq的ip核上就会有一个
pl到ps的中断请求信号
。
(15)vitis中,在
lscript.ld中可以看到代码、数据、堆栈运行所在的内存情况。
(16)运行Hello world成功后的现象如下图所示
但是会有一行 PMU-FW is not running,certain applications may not be supported.
PMU(PlatformManagementUnit)的作用: 用于电源检测、错误管理、为功能安全应用程序
执行可选的软件测试库(STL)
怎么去增加这个呢?
(使用SD或者QSPI都会报错……)
(17)vitis 如果需要
调试fsbl,以发现fsbl启动过程中的故障,让fsbl输出打印的调试信息,只需要修改
xfsbl_config.h
中的宏定义如下图设置为
然后需要重新编译zu_base以及产生新的boot.bin。
(会报错……)
(18)怎么增加代码的
ILA在线逻辑分析仪
先在变量前加上
(*mark_debug ="true"*)
再综合后打开逻辑分析仪
在上面的逻辑分析仪中,可以选择
ILA Core Options设置,
Sample of data depth(采样的深度)大小是2048,并且用
Capture control(以自己设置的捕获信号去捕获)。
在线逻辑分析仪的采样深度,使用的是FPGA的BRAM,以及设置Captrue control,对于这种超慢信号,
XILINX的在线逻辑分析低于20M采样速度的,波形窗口就不会显示波形,这个XILINX也没有特别说明过,但是
通过设置Captrue control,可以用我们这里的en_10ms来作为扑捉控制,而采样时钟依然用系统时钟。
Captrue mode设置为BASIC
(BASIC是以自己设定的capture信号来捕捉的,如果是always,那么就跟这里设置的capture setup没有关系了)
Window data depth为采样深度设置为2048
Trigger position in window设置为1024
2021年10月13日
(19)
3分频的本质是我们需要在每次1.5倍的时钟周期的时候实现3分频寄存器的翻转,但是我们无法直接实现1.5
倍的分频。因此采取分别采取2个计数器pos_cnt和neg_cnt,分别对上升沿和下降沿计数。计数周期是0-1-2,共
计3个时钟周期。我们取pos_cnt==2’d1的时候div3_o_r0输出高电平,neg_cnt==2’d1的时候div3_o_r1输出高电
平。由于div3_o_r0和div3_o_r1输出1个时钟的高电平,但是相位相差180°,因此只要执行div3_o=div3_o_r0|
div3_o_r1运算,就能实现1.5倍周期的输出高电平,那么剩余的1.5倍源时钟周期就是输出低电平了。
reg [1:0] pos_cnt;
reg [1:0] neg_cnt;
always @(posedge clk_i) begin
if(rst_i)
pos_cnt<=2'b00;
else if(pos_cnt==2'd2)
pos_cnt<=2'b00;
else
pos_cnt<=pos_cnt+1'b1;
end
always @(negedge clk_i) begin
if(rst_i)
neg_cnt<=2'b00;
else if(neg_cnt==2'd2)
neg_cnt<=2'b00;
else
neg_cnt<=neg_cnt+1'b1;
end
reg div3_o_r0;
reg div3_o_r1;
always @(posedge clk_i) begin
if(rst_i)
div3_o_r0<=1'b0;
else if(pos_cnt<2'd1)
div3_o_r0<=1'b1;
else
div3_o_r0<=1'b0;
end
always @(negedge clk_i) begin
if(rst_i)
div3_o_r1<=1'b0;
else if(neg_cnt<2'd1)
div3_o_r1<=1'b1;
else
div3_o_r1<=1'b0;
end
assign div3_o = div3_o_r0 | div3_o_r1;
如图所示,就一个三倍频的时钟。
(20)怎么去读取pl端的DDR4、BRAM,米联客的技术是需要
使用一个IP核 FDMA
读取BRAM的设计如下图所示,但是
最后读取BRAM还是失败了
。
2021年10月14日
(21)
IDELAYCTRL的计算
(22)在代码里面写ila可以使用generate语句,其中DEBUG_ENABLE语句可以作为module的一个parameter来使用。
generate if(DEBUG_ENABLE==1'b1)begin:debugcore
//添加ilaIP,Chipscope观察信号
ila_0 ila_debug(
.clk(sysclk_i),//inputwireclk
.probe0({plus_20us,pwm_o})//inputwire[1:0]probe0
);
end
endgenerate
(23)
怎么保存波形文件 一般保存为WDB(sim里面)跟WCFG
1.点击Vivado的菜单栏中的 Flow -> Open Static simulation,然后选中之前保存的 .WDB 文件即可。
2. 点击Vivado的菜单栏中的 File -> Open Waveform Configuration,选择我们之前保存的 .WCFG文件即可恢复上一次的仿真结果
2021年10月18日
(24)
用AXI-Lite来构建了数据发送以及GPIO来控制pl端的led灯去点亮都实验成功了!!!
(25)new project summary
xczu7ev-ffvc 1156-2-e
(26)
ILA有一种分类叫做
System ILA IP
,用这个东西可以实现对Post-implemented的设计进行分析和调试(参见ug908-page170)。按照ug908这个说明,system ila应该放到
ip block design
里面才对。
System ILA debug可以直连AXI协议。连上AXI协议接口线之后,Waveform的窗口会显示每个接口的连线信号,事件。如果有不止一个AXI连到一个ILA上面,各个AXI会以几个不同的slot展现出来。每个slot都会显示各个AXI接线上相关的Read,Write,Address events和Data channel evets。
(27)vitis的使用方案
2021年10月20日
(28)怎么使用XAPP例程
先下载,修改启动版本,再使用vivado的tcl版本进行运行,启动GUI版本来执行代码。
vivado -source pl_eth_sgmii.tcl
(29)自定义的AXI4总线需要定义地址 大概在xparameters文件中的410地址的位置处。
2021年10月21日
(30)BRAM的IP核深度怎么去计算
(31)AXI GPIO
如果没有点击All outputs,会有三个数值出现:
如果点击了All outputs,就会只有一个数值出现。
2021年10月22日
(32)
FDMA波形图如下图所示:
fdma是米联客自己做的一个ip,用来读取DDR非常的方便,里面已经有封装好的ip可以去调用来使用的。
文章来源地址https://www.toymoban.com/news/detail-645766.html
文章来源:https://www.toymoban.com/news/detail-645766.html
到了这里,关于FPGA杂记的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!