Vivado常用编程方法

Vivado常用技巧

  • 1 如何提升Vivado编译速度
  • 2 调用一个IP核后,如何对m_axis_data_tdata截位得到所需数据
  • 3 IP核如何看实部和虚部对应的bit位
  • 4 vivado如何学习某个语句的用法
  • 5 常用快捷键
  • 6 如何快速添加已有工程的IP核
  • 7 vivado的ip锁定了怎么解锁
  • 8 高阻态z什么时候用
  • 9 case语句的作用
    • 9.1 让程序顺序执行(状态机+case语句)
    • 9.2 对某个信号延时一定时间
  • 10 如何让一个数缩小2倍或者4倍
  • 11 如何得到一个复数的共轭( +x到-x的快速转换方法)
  • 12 如何抓取信号的上升沿
    • 12.1 产生的是一个脉冲信号
    • 12.2 产生的是一个高电平信号
  • 13 FPGA如何表示矩阵(二维数组的定义方法)
    • 13.1 矩阵定义方法
    • 13.2 矩阵A的赋值的两种实现方法(assign A=B)。
    • 13.3 Verilog如何输出一个8*8的矩阵信号?
  • 14 VHDLdebug方法
  • 15 直流偏置(校正)的方法
  • 16 上位机的角度值如何等价到FPGA的弧度值
  • 17 for Loop 语句的写法
  • 18 每个模块的标志信号最好用脉冲信号(上升沿有效),其波形为__---__
  • 19 如何准确看FPGA工程的资源消耗
  • 20 得到 a ,b 脉冲都有效后的标志信号,是一个脉冲信号
  • 21 滤波器如何截位

1 如何提升Vivado编译速度

在tcl脚本处输入如下命令:
设置多线程的命令为: set_param general.maxThreads 8
读取当前线程数的命令: get_param general.maxThreads

2 调用一个IP核后,如何对m_axis_data_tdata截位得到所需数据

(1)满幅输入,看IP 核的输出应该从哪里开始截位。
比如16位的乘法IP,输入为全1。此时根据输出数据 m_axis_tdata 进行截位(连续相同的即为符号位)。
(2) 如何从m_axis_data_tdata得到m_axis_data_tdata[15:0]
选中需要截取出来的bit位---->单击右键----->选择new virtual bus—>命名

3 IP核如何看实部和虚部对应的bit位

Vivado常用编程方法_第1张图片

4 vivado如何学习某个语句的用法

tool------language templates-------输入关键词
Vivado常用编程方法_第2张图片

5 常用快捷键

1、crtl+Alt,再滚动鼠标。即可进行批量操作。
2、crtl+F。快速查找某一个参数的上一次/下一次出现的地方。
3、crtl+R。批量替换

6 如何快速添加已有工程的IP核

点击±—单击add or create design source------add file—找到现有工程的.srcs文件-----点击source----点击 ip----找到所需的IP,点击进去,选择.xci文件----添加所需的.xci文件–点击完成
Vivado常用编程方法_第3张图片

7 vivado的ip锁定了怎么解锁

(1)法一:
1.生成IP核的状态报告 Tools -> Report -> Report IP Status-> upgrade
(2)法二:
下面介绍另一种方法,对应上述方法不能使用的情况(Upgrade Selected 按钮是灰色的)。在 Tcl console中 执行如下一条命令即可:

upgrade_ip [get_ips]

8 高阻态z什么时候用

如果信号直接对应外部芯片的管脚,那就用10’dz.
如果只是芯片内部的信号,那就不要用高阻态。

9 case语句的作用

9.1 让程序顺序执行(状态机+case语句)

复位时,state=0;

case(state)
	0:
		begin
			state<=1;
			...程序功能	
		end
	1:
		begin
			state<=2;
			...程序功能	
		end
	default :
	   state<= 0;
endcase

9.2 对某个信号延时一定时间

//改进:PINC_flag=1后,还需要间隔一定的时间,LMS算法才校正完成,所以需要对上式改进
reg [7:0] PINC_flag_delayCount;
reg [3:0] ST_PINC_flag;//状态机
reg PINC_flag_delay50;
always @(posedge clk)
begin
    if(reset)
        begin
            PINC_flag_delayCount<=8'd0;
            ST_PINC_flag<=4'd0;//状态0
            PINC_flag_delay50<=1'b0;
        end
    else 
        begin
            case(ST_PINC_flag)
            0://进入状态0
                if(PINC_flag==1)//完成整个频段的频率字的输出的标志信号 
                    begin
                        PINC_flag_delayCount<=PINC_flag_delayCount+1'b1;
                        ST_PINC_flag<=4'd1;
                    end
            1:
                if(PINC_flag_delayCount==8'd50)
                    begin
                        ST_PINC_flag<=4'd2;
                        PINC_flag_delayCount<=PINC_flag_delayCount;
                    end
                else
                    begin
                         ST_PINC_flag<=4'd0;
                    end    
            2:
                 PINC_flag_delay50=1'b1;
            default :
                ST_PINC_flag<=4'd0;
            endcase                            
        end  
end   
assign Calib_State=!( (PINC_flag_delay50) && (!Calib_flag) );

10 如何让一个数缩小2倍或者4倍

通过截位的方法

//缩小两倍: 0000_1000_0000_0000       0_0000_1000_0000_000
assign RtI={RtI_temp[15],RtI_temp[15:1]};  //将参考信号缩小一半
assign RtQ={RtQ_temp[15],RtQ_temp[15:1]};  //将参考信号缩小一半


//assign RtI={RtI_temp[15],RtI_temp[15], RtI_temp[15:2]};  //将参考信号缩小为1/4
//assign RtQ={RtQ_temp[15],RtQ_temp[15], RtQ_temp[15:2]};  //将参考信号缩小为1/4

11 如何得到一个复数的共轭( +x到-x的快速转换方法)

数据格式为补码。
对于位宽为16位的数据而言,例如 x = 0111_1111_1111_1111,x的相反数-x = 1111_1111_1111_1111(原码表示方式)。
根据负数的补码与原码的转换规则:符号位不变,数据位按位取反,再+1。
所以 -x 的补码为:1000_0000_0000_0000+1= 1000_0000_0000_0001。
因此,+x到-x的快速转换方法为:所有位按位取反,再+1。

assign W_GE = {((~W[31:16]) + 1), W[15:0]};   //W的共轭; 高16位是虚部,低16位是实部。

12 如何抓取信号的上升沿

12.1 产生的是一个脉冲信号

//---2、抓取phase_vec_vaild的下降沿
reg phase_vec_vaild_delay;
reg phase_vec_vaild_syn;
always@(posedge clk)
begin
    phase_vec_vaild_delay<=phase_vec_vaild;
    //if(phase_vec_vaild_delay==1'b0 && phase_vec_vaild==1'b1)//抓取信号的上升沿
	if(phase_vec_vaild_delay==1'b1 && phase_vec_vaild==1'b0)//抓取信号的下降沿
        begin
            phase_vec_vaild_syn<=1'b1;
        end
     else
        begin
            phase_vec_vaild_syn<=1'b0;
        end        
end

12.2 产生的是一个高电平信号

/*
    step 1: 抓取 beam1_tvalid 的上升沿
*/
reg beam1_tvalid_delay;
reg beam1_tvalid_syn;//是一个高电平信号
always@(posedge clk_250M)
begin
    beam1_tvalid_delay<=beam1_tvalid;
    if(reset) 
        begin
            beam1_tvalid_syn<=1'b0;
        end    
    else if(beam1_tvalid_delay==1'b0 && beam1_tvalid==1'b1)//抓取信号的上升沿
        begin
            beam1_tvalid_syn<=1'b1;
        end
    else
        begin
            beam1_tvalid_syn<=beam1_tvalid_syn;
        end        
end

13 FPGA如何表示矩阵(二维数组的定义方法)

13.1 矩阵定义方法

[ 31 : 0 ]表示一个数据的信号位宽,而 [0:7][0:7] 表示有8x8个位宽为32的数据。;

wire [31:0] A_matrix [0:7][0:7]; 
reg  [31:0] B_matrix [0:7][0:7]; 

好处:
(1)直观;
(2)可以用这种数据表示方法+序号m、n来处理matlab的for语句(大量,重复的语句)。
Vivado常用编程方法_第4张图片

13.2 矩阵A的赋值的两种实现方法(assign A=B)。

第一种方法:
Vivado常用编程方法_第5张图片

第二种方法:
integer i_clk,j_clk;
Vivado常用编程方法_第6张图片

13.3 Verilog如何输出一个8*8的矩阵信号?

(1)第一种方法
  将矩阵放在变量A里面作为输出。

wire [8*8*31 : 0] A。

(2)第二种方法
  二维数组直接作为输出,对于VHDL语言是可行的,但是对于Verlog是不可行的。但是,我们可以用串行输出的方式来将一个二维数组输出出来,此时需要一个计数器。最后,外部模块根据计数器count和矢量,来拼成一个矩阵。

always@(posedge clk)
begin
    if(y_Vaild)  //是一个脉冲信号(上升沿有效)
        begin
            Men_y[count_scan]<=y;
            Men_y_Vaild[count_scan]<=1'b1;  //是一个脉冲信号
        end 
    else
        begin
            Men_y[count_scan]<=Men_y[count_scan];
            Men_y_Vaild[count_scan]<=1'b0;     //是一个脉冲信号(上升沿有效)          
        end                   
end 

14 VHDLdebug方法

     --debug 类似于ila
     attribute MARK_DEBUG : string;
     attribute MARK_DEBUG of A: signal is "TRUE";----****
     attribute MARK_DEBUG of B: signal is "TRUE";
     attribute MARK_DEBUG of C: signal is "TRUE";   
     attribute MARK_DEBUG of D: signal is "TRUE";  

  通过上述语句生成bit文件时,应该按照下面步骤进行操作。否则,debug加不上。
  点击综合(run synthesis)—>展开open synthesisized Design—点击set up debug----设置完成后,最后点击生成比特流文件。
  为了通过直接点击生成bit流文件生成bit文件,且保证ILA一定加上了,则采用添加ila IP核这种方法。

15 直流偏置(校正)的方法

  (1)处理板连接好线,但是此时没有输入信号,将ADC采集的数据偏置到平均值为0
  (2)**两级希尔伯特变换。**具体而言,首先经过第一级希尔伯特变换,其实部是有直流的,虚部信号没有直流,所以我们保留虚部信号;第二级希尔伯特变换,其输入为第一级希尔伯特变换的虚部。

16 上位机的角度值如何等价到FPGA的弧度值

  --temp_alpha单位是度,temp_mult_a单位是弧度
  -- 182是怎么来的:根据弧度=/180*pi=*pi/180
  --  pi/180=  (2*pi/2)/180= =(65536/2)/180=182
                
  -------1种理解方式:
  -- 为了提高角度精度,上位机如果要发360度,实际上发的是ffff,即65536
  -- 那么对于FPGA而言,为了对应真实的角度(360度),需要除以18265536/182=360---为了转换为弧度,根据公式:弧度=/180*pi=*pi/180=*1822*PI对应65536),
  -- 即需要再乘以182,所以最终为:/182*182= *1 。如下所示
  
  -------2种理解方式:
  -- 上位机如果发送的角度为360度,真实发的是ffff,即65536
  -- 对于FPGA而言,360度的弧度为2*pi,即65536。。
  -- 所以上位机的角度值转化为FPGA的弧度值,直接*1即可
                
  temp_mult_a := temp_alpha*1;--将度转化成弧度, 182是量化因子
  temp_mult_b := temp_beta*1;--没有<,所以是串行执行,先执行这两行语句

17 for Loop 语句的写法

generate
    genvar j;
    for (j=0;j<10;j=j+1)
        begin : Loop_j             
            assign b[j]    = a[j];           
        end
endgenerate

18 每个模块的标志信号最好用脉冲信号(上升沿有效),其波形为__—__

原因:
(1)在每一个clk,都会对该信号进行判断,所以不用担心采集不到该信号的上升沿;
(2)如果生成的是一个高电平信号,那么对于算法下一次执行时,是不利的。

19 如何准确看FPGA工程的资源消耗

synthesis—report Utilization—>Hierarchy
Vivado常用编程方法_第7张图片

20 得到 a ,b 脉冲都有效后的标志信号,是一个脉冲信号

`timescale 1ns / 1ps

module Get_RxBeam_WPower_vaild(
    input       clk_250M                    ,
    input       reset                       ,     
    input       receive_beam_weight_valid   ,  //权值有效---是一个脉冲信号
    input       select_beam_power_valid     , //---是一个脉冲信号
    
    
    
    output      receive_beam_WPower_vaild_pulse 
);
    
wire a,b;
assign a=receive_beam_weight_valid;
assign b=select_beam_power_valid;


/*
    step 1:保证a,b 是一个脉冲(仅持续一个clk)
*/
reg a_delay;
reg a_pulse; // 是一个脉冲信号
always@(posedge clk_250M)
begin
    a_delay<=a;
    if(a_delay==1'b0 && a==1'b1)//抓取信号的上升沿
        begin
            a_pulse<=1'b1;
        end
     else
        begin
            a_pulse<=1'b0;
        end        
end 

reg b_delay;
reg b_pulse; // 是一个脉冲信号
always@(posedge clk_250M)
begin
    b_delay<=b;
    if(b_delay==1'b0 && b==1'b1)//抓取信号的上升沿
        begin
            b_pulse<=1'b1;
        end
     else
        begin
            b_pulse<=1'b0;
        end        
end 
 
 
 
/*
    step 2 :得到 a ,b 脉冲都有效后的标志信号,是一个脉冲信号
*/
reg c;
reg delay_a_pulse;
reg dd_a_pulse;
reg delay_b_pulse;
reg [3:0] ST;
always @(posedge clk_250M)
begin
    delay_a_pulse<=a_pulse;
    dd_a_pulse<=delay_a_pulse;
    delay_b_pulse<=b_pulse;    
    if(reset) 
        begin 
            c<=1'b0;
            ST<=4'd0;
        end
    case(ST)      
        0: 
            begin
                if(a_pulse==1'b1 && b_pulse==1'b0)  //a这个脉冲先来,b这个脉冲后来
                    begin
                        ST<=4'd1;
                    end
                else if(b_pulse==1'b1 && a_pulse==1'b0)  //b这个脉冲先来,a这个脉冲后来
                    begin
                        ST<=4'd2;
                    end
                else if(a_pulse==1'b1 && b_pulse==1'b1)  //a、b 脉冲同时来
                    begin
                        ST<=4'd3;
                    end                    
                else
                    begin
                        ST<=4'd0;
                    end                       
            end   
        1:
            begin
                if(delay_a_pulse) //a这个脉冲先来,b这个脉冲后来
                    c<=1'b1;
                else if(delay_b_pulse) 
                    begin
                        c<=1'b0;
                        ST<=4'd4;
                    end
                else
                    c<=c;     
            end
        2:
            begin
                if(delay_b_pulse) //b这个脉冲先来,a这个脉冲后来
                    c<=1'b1;
                else if(delay_a_pulse) 
                    begin
                        c<=1'b0;
                        ST<=4'd4;
                    end                   
                else
                    c<=c;     
            end
        3:    //a、b 脉冲同时来
            begin
               ST<=4'd4;
               if(delay_a_pulse)
                    c<=1'b1;
               else
                    c<=1'b0;  
            end                     
        4:
            begin
                ST<=4'd0;
                c<=1'b0; 
            end    
      endcase           
end        
       
    
   
reg c_delay;
reg c_pulse; // 是一个脉冲信号
assign receive_beam_WPower_vaild_pulse=c_pulse;
always@(posedge clk_250M)
begin
    c_delay<=c;
    if(c_delay==1'b1 && c==1'b0)//抓取信号的下降沿
        begin
            c_pulse<=1'b1;
        end
     else
        begin
            c_pulse<=1'b0;
        end        
end     
     
endmodule

21 滤波器如何截位

对于滤波器而言,滤波器的增益为0dB,所以待滤波信号(位宽16)过了滤波器之后,应该仍然是16bit。但是,现在利用MATLAB生成滤波器系数的coe文件时,我们将滤波器的系数扩大 2^15-1倍,
所以在FPGA里面,要截去滤波器输出信号的低15位,即assign y = m_axis_data_tdata[30 : 15];

你可能感兴趣的:(FPGA,fpga)