Verilog,自定义原语(UDP)的创建与使用

玩FPGA的人大多数都知道原语,但很多初学者并不是很了解但有调用过,会有一种疑问,它和IP有什么区别?下面就讲解一下区别,以及如何自定义一个原语

原语和IP是FPGA中的两个重要概念。

  1. 原语:原语是指FPGA中用于实现特定硬件操作的基本单元,通常由多个逻辑门和触发器组成。原语可以由硬件设计者根据特定应用需求进行设计和优化,以实现高性能、低功耗的硬件电路。在FPGA中,原语可以用来实现各种硬件操作,例如算术运算、逻辑运算、数据存储和传输等。
  2. IP:IP(Intellectual Property)是指FPGA中预先设计好的、可重复使用的硬件模块。这些模块通常由FPGA厂商提供,并经过优化和测试,以确保其性能和稳定性。IP可以包括各种不同的功能模块,例如串口通信、DDR内存控制器、PCIe接口控制器等。使用IP可以加速硬件设计的速度,减少开发和验证的时间和资源,并提高设计的可靠性和稳定性。

总的来说,原语和IP都是FPGA中的硬件模块,但它们的使用方式和目的略有不同。原语主要用于设计和优化特定的硬件电路,以满足特定应用的需求;而IP则主要用于加速硬件设计的速度和减少开发和验证的资源和时间。在实际应用中,硬件设计者可以根据需要选择使用原语或IP来实现特定的硬件功能。

UDP(User-Defined Primitive) 

在这里的UDP就不是协议了,自定义原语的一种表达方式的缩写。嗯~,相信很多人会想这说我们为什么要去自定原语,直接调用不就好了吗!

确实这样省时又方便,但有的人面向的是设计,他们需要面对嵌入式等高性能数据开发必须要取了解并且编写更改,就相当于自带原语编写者的工作一样。

使用用户自定义原语与FPGA自带原语的利弊区别如下:

  1. 灵活性和效率:使用用户自定义原语(UDP)可以根据特定应用需求来设计和优化硬件电路,从而在灵活性和效率上具有优势。UDP允许用户在HDL代码中直接使用硬件操作,这使得硬件设计者可以更直接地控制硬件行为,并可以根据需要自由地优化和定制硬件电路。
  2. 易用性和可维护性:使用FPGA自带的原语(IP核)可以简化开发流程,因为IP核是经过优化和预先测试的,而且通常具有更高的可靠性和稳定性。此外,IP核的使用可以减少开发时间和错误,并且通常具有更好的可维护性。
  3. 成本和资源:使用UDP需要更多的时间和资源来设计和验证硬件电路,这可能导致更高的开发成本。相比之下,使用FPGA自带的IP核可能更快地完成设计和验证过程,并且通常需要更少的资源。
  4. 适用范围:UDP适用于需要定制和优化硬件电路的应用场景,例如高性能计算、信号处理和嵌入式系统等。而IP核则适用于需要快速开发和可靠运行的应用场景,例如通信、数据转换和接口控制等。

综上所述,用户自定义原语和FPGA自带原语各有其利弊,选择使用哪种方式取决于具体的应用需求和开发团队的偏好。在需要灵活性和效率的情况下,UDF可能更合适;而在需要快速可靠的开发和降低成本的情况下,使用IP核可能更有优势。

 好了,废话不多说,开始实用。

首先了解一下UDP的基础组合部分有哪些

primitive project_name(output_name,input_name1,input_name2);//第一个必须是输出
    input  input_name1;//输入端口1,可以有多个输入端口,但只能是一位宽
    input  input_name2;//输入端口2,输入端口数量最好在10个以内,不然工作量就很大,因为真值表的结果是指数型增长的
    output output_name;//输出端口,只能有一个输出端口并且只能是一位宽
    
    table
        //真值表,自己定义所想要的结果即可,下面只是一个小举例
        //input_name1    input_name2  :    output_name
            1                1        :        0
    endtable
endprimitive

注意几点:第一个必须是输出!

输入端口可以多,但只能是一位宽!

输出端口只能是一个,并且一位宽 !

建议输入端口在10个以内(最好5个以内),因为真值表的数据是指数型增长,会占用很大的运算和存储。

其次举个栗子

举一个“与(and)”逻辑的例子,组合逻辑的例子。

primitive AND(c,b,a);
	input 	a,b;
	output 	c;

	table
	//	a	b	:	c
		0	0	:	0;
		0	1	:	0;
		1	0	:	0;
		1	1	:	1;
	endtable
endprimitive

仿真 

后面的例子的仿真代码,自己写一下哈,我就偷个懒 

module tb_2(  );
    reg a, b;
    wire c;
    initial begin
        #5 a = 0;b = 0; $display("a = %b, b = %b", a, b);
        #5 $display("c = %b", c);   
        #5 a = 1;b = 1; $display("a = %b, b = %b", a, b);
        #5 $display("c = %b", c);               
        #5 a = 1;b = 0; $display("a = %b, b = %b", a, b);
        #5 $display("c = %b", c);
        #5 a = 1;b = 1; $display("a = %b, b = %b", a, b);
        #5 $display("c = %b", c);           
        #5 a = 0;b = 1; $display("a = %b, b = %b", a, b);
        #5 $display("c = %b", c);
    end
    AND and_inst(c, a, b);
endmodule

 TCL显示

波形显示

 举个时序逻辑的例子,电平敏感触发

primitive clk_latch(out,data,clk,rst_n);
    output reg out;
    input data;
    input clk;
    input rst_n;
    initial out = 0; //赋个初值
    table  
        //data  clk   	rst_n:  out : out+;
           ?     ?       1    :   ?  : 0;//清零,out+新的输出值
	    //clk = 1时将data值锁存到q中
           1     1       0    :   ?  :1;//将data的数值1所存到out中
           0     1       0    :   ?  : 0;//将data的数值0所存到out中
     
           ?     0       0    :   ?  : -;//当clk=0时保持不变
    endtable
endprimitive

?表示不会影响下一个状态的输出

 举个时序逻辑的例子,边沿敏感触发。

带清零的时钟下降沿触发的D触发器

 primitive clk_neged(out,data,clk,rst_n);
	 output reg out;
	 input data;
	 input clk;
	 input rst_n;
	 initial out = 0; //赋个初值
		 table
//			  data   clk   rst_n  :     out : out+;
				 ?     ?     1    : 	 ?  :  0  ;//清零
				 ?     ?    (10)  : 	 ?  :  -  ;//忽略 rst_n 的负跳变沿
				 1    (10) 	0     : 	 ?  :  1  ;//在clk的下降沿锁存数据
				 0    (10) 	0     : 	 ?  :  0  ;
				 ?    (1x) 	0     : 	 ?  :  -  ;// clk变化到不定状态时,out保持不变
				 ?    (0?) 	0     : 	 ?  :  -  ;//忽略 clk 的正跳变    
				 ?    (x1) 	0     : 	 ?  :  -  ;//忽略 clk 的正跳变
				(??)  ?     0     : 	 ?  :  -  ;//clk不变时,忽略data的变化
		 endtable
 endprimitive

符号含义入下:

(10)表示从逻辑1到逻辑0的负跳变沿;

(1x) 表示从逻辑1到不确定状态x的跳变;

(0?)表示从逻辑0到0, 1或x的跳变,这里隐含正跳变沿;

(??)表示信号值从0. 1或x,到0, 1或x的任意跳变。

缩写 符义解释
0,1,x不能用于输出部分
b0,1不能用于输出部分
-维持原值不变只能用在时序 UDP 的輸出部分
r(01)信号的上升沿
f(10)信号的下降沿
p(01), (0x)或(x1)可能是信号的上升沿
n(10), (1x)或(x0)可能是信号的下降沿
*(??)信号值的任意变化

建议

在设计功能模块时,决定使用module还是用户自定义原语(UDP)来建模是一个重要的决策。以下是一些指导原则,可以帮助你在两者之间进行选择:

  1. 复杂性和可重用性:如果功能模块比较复杂,或者需要多次在不同的项目中使用,那么使用module可能更合适。Module可以提供更好的封装和抽象,使得代码更易于理解和维护。此外,module还支持参数化,可以使用户更容易地复用代码。
  2. 性能优化:如果功能模块对性能要求很高,或者需要进行定制化的优化,那么使用UDP可能更合适。UDP允许用户直接控制硬件行为,可以根据特定应用的需求进行优化,从而提高性能。
  3. 硬件资源:如果硬件资源有限,或者需要尽可能减少资源占用,那么使用module可能更合适。Module通常比UDP更节省资源,因为它们是预先编译和优化过的。
  4. 开发时间和经验:如果开发时间紧迫,或者开发人员缺乏硬件设计经验,那么使用module可能更合适。Module可以提供更高级别的抽象和易用性,使得开发人员能够更快地开发和调试代码。
  5. 社区支持和维护:如果功能模块需要与开源社区共享或维护,或者需要获得更广泛的支持,那么使用module可能更合适。Module通常比UDP更容易被社区接受和维护。

综上所述,选择使用module还是UDP取决于特定应用的需求和约束。在决定使用哪种方式时,需要考虑功能模块的复杂性、可重用性、性能要求、硬件资源、开发时间、经验以及社区支持和维护等因素。

动动你的小手手一键三连,点个赞,收藏,关注。后续会发更多作品哦(有时间的话)。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值