我是靠谱客的博主 自由饼干,最近开发中收集的这篇文章主要介绍FPGA杂记,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

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可以去调用来使用的。

最后

以上就是自由饼干为你收集整理的FPGA杂记的全部内容,希望文章能够帮你解决FPGA杂记所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(53)

评论列表共有 0 条评论

立即
投稿
返回
顶部