Verilog语法点滴

begin end:
感觉是和C语言中的{}类似
比如:

always @(*)
if
...
else
...

同一句if else 可以不添加begin end,但是在always块整体,可能还是需要添加比较好,但是如果是:

always @(*)
begin
	if(OE_n==1'b0)
		if(G==1'b1)
			DO=DI;
		else
			DO=DO;
	else
		DO=8'bz;
end

这种在 if语句下面的就可以不用添加。

//220707
变位宽fifo:
fifo_generator_0 your_instance_name (
.clk(clk), // input wire clk
.srst(rst), // input wire srst
.din(din), // input wire [255 : 0] din
.wr_en(wr_en), // input wire wr_en
.rd_en(rd_en), // input wire rd_en
.dout(dout), // output wire [511 : 0] dout
.full(full), // output wire full
.empty(empty) // output wire empty
);
依次写入256’d1,256’d2,读出512bit为{256’d1,256’d2}:类似大端传输的方式
测试波形图如下:
在这里插入图片描述
//220708
关于格雷码:
相邻代码间只有一位取值不同:模拟数据传输过程中,如果3变化到4,二进制码:4’b0011->4’b0100,总共3bit变化,如果每个bit位变化时间不一致,可能产生误码如4’b0000.而格雷码:0010->0110,只有1bit变化,误码可能性较低。
二进制码转化为格雷码:
(1)gray = (bin>>1)^bin;
格雷码转化为二进制码:
(2)bin[i] = ^(bin>>i);

//220709
FPGA中触发器类型:

//同步复位:
//FDR、FDRE(带时钟使能)
always @(posedge clk)begin
	if(rst)
		a <= 1'b0;
	else
		a <= ......
end 

//同步置位:
//FDS、FDSE
always @(posedge clk)begin
	if(rst)
		a <= 1'b1;
	else
		a <= ......
end 

//异步复位:
//FDC、FDCE
always @(posedge clk or posedge rst)begin
	if(rst)
		a <= 1'b0;
	else
		a <= ......
end 

//异步置位:
//FDP、FDPE
always @(posedge clk or posedge rst)begin
	if(rst)
		a <= 1'b1;
	else
		a <= ......
end 

//220727
最近开始使用native接口的block ram:
接口类型有:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

主要关注了read端口的数据输出延时问题:
block ram输出部分可以配置为block ram 源语输出处寄存器和IP核输出处寄存器,如下图:
在这里插入图片描述
read端口,dout输出时序图:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
仿真结果如下:采用simple dual port ,输出端没有寄存器:结果如下:
在这里插入图片描述
写入端:ena与wea要同时为高,写入数据成功;
读出段:enb有效到读出数据dout有效有一拍延迟,并且bram存储值初始值为0。
在这里插入图片描述
上图中,simple dual port配置为异步时钟,可以理解为ab端口互相独立,a的模式不影响b。(a端口nochange/write/read,b端口默认write first),b端口表现为read first。可以看出,简单双端口bram,a端口为写入端,b端口为读出端,互相独立并不影响。
在这里插入图片描述
当A端写入同时B端读出,则B会读出写入前的值,与true dual port一样。

当simple dual port配置为common clk时,B端口默认为read first。可以认为ab端口有一定联系,a的模式write first会使得b端口表现为write first。其他两种模式不影响b,b表现为read first。
在这里插入图片描述
上图中(a端口write,b端口read first),b端口表现为write first。
在这里插入图片描述
上图中(a端口read,b端口read first),b端口表现为read first。
在这里插入图片描述
上图中(a端口no change,b端口read first),b端口表现为read first。
//220805
对于使用true dual port bram:
block design中接口为:
在这里插入图片描述
并且端口A和B均默认配置为WRITE FIRST:
接口读写时序如下:
在这里插入图片描述
en有效时:当we有效,为写操作,下一个周期dout的值为上一周期写入的din;当we无效,为读操作。
仿真结果如下:
当A端写入同时B端读出,则B会读出写入前的值:
在这里插入图片描述
对于READ FIRST:
在这里插入图片描述
对于 NO CHANGE:
在这里插入图片描述
**当 true dual port 配置为common clk时,将ab设置为write first,ab地址不一致时,ab独立,各自端口写操作表现出各自的write first。当ab地址一致,且一端读、一端写,写端口自身为write first,并且影响读端口出现write first,如a往4地址写4,b读地址为4,dout均为a现在写入的4;两端同时写有冲突,要避免,时序如下图: **(xilinx该仿真模型有问题,与下板结果不一致!!!)
在这里插入图片描述

//220825
关于时序逻辑中添加#延时在不同位置仿真的不同结果:

`timescale  1ns/1ps

module test_delay ();
parameter DELAY = 1;
parameter CLK_PERIOD = 10;


logic clk;
logic rst;
logic [3:0] a,b,c;

always #(CLK_PERIOD/2) clk = ~clk;



initial begin 
	rst = 1;
	clk = 0;

	#(CLK_PERIOD*100+1);
	rst = 0;

	#(CLK_PERIOD*10000);
	$stop();

end


always @(posedge clk or posedge rst)begin 
	if(rst)
		a <=#DELAY 4'd0;
	else
		a <=#DELAY a + 4'd1; 
end

always @(posedge clk or posedge rst)begin 
	if(rst)
		b <=#(DELAY*2) 4'd0;
	else
		b <=#(DELAY*2) a;
end

always @(posedge clk or posedge rst)begin 
	#(DELAY*2)
	if(rst)
		c <= 4'd0;
	else
		c <= a;

end


endmodule

仿真结果如下:
在这里插入图片描述
b <=#DELAY a:b在时钟上升沿采样,然后DELAY后赋值。
#DELAY c <= a :c在时钟沿DELAY后,然后再采样,后续赋值。

//220928
?和z等价,表示高阻态。
对于case、casez、casex的用法:
真值表如下:
在这里插入图片描述
对于case:严格按照条件执行;
对于casez:casez(表达式)分支项1: 分支项2:…,表达式中的z以及分支项中的z的对比判断都需要忽略,默认真值为1;
对于casex:casex(表达式)分支项1: 分支项2:…,表达式中的z\x以及分支项中的z\x的对比判断都需要忽略,默认真值为1;
这样使用casez的好处是,可以忽略掉分支项与表达式中某些bit位的比较,比如:

casez(a)
	4'b1???:
	4'b01??:
	4'b001?:
	4'b0001:
endcasez

上述例子可以实现优先级分配,bit3优先级最高,bit0优先级最低。

//220928
对于verilog中for循环和generate的使用:
参考:
1、https://blog.csdn.net/abcdef123456gg/article/details/102951636?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166433386416782428618106%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall%255Fv2.%2522%257D&request_id=166433386416782428618106&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2all_v2first_rank_ecpm_v1~rank_v31_ecpm-2-102951636-null-null.142v50control_1,201v3control_1&utm_term=verilog%E4%B8%AD%E7%9A%84generate%E8%AF%AD%E5%8F%A5&spm=1018.2226.3001.4187
2、https://blog.csdn.net/m0_47137431/article/details/108648522
大概总结一下如下所示:

//generate_for循环生成语句,多次例化同一模块,或者循环赋值操作等
genvar i;//integer i,for循环放在always内部时,需使用integer定义循环变量?
generate
	for(i = 0; i < 100 ; i = i + 1)begin:generate_for//一定要有块名
		//......例化模块、赋值等,for循环可放在always外部或者内部。 放在always内部时,需使用integer定义循环变量?
	end
endgenerate



//generate_if语句,根据模块参数作为条件判断,生成所需要的电路部分,例如裘师兄中通过TX_ONLY==1?来判断是否生成nread模块
parameter TX_ONLY = 1;
generate
	if(TX_ONLY == 1)begin:exclude_nread//不一定要有
		//......
	end
	else begin:include_nread
		//......
	end
endgenerate



//generate_case语句,类似generate_if语句,根据常量参数作为判断条件,生成不同电路模块
parameter RX_ONLY = 1;
generate
	case(RX_ONLY)
		0:begin:include_swrite  //不一定要有 
			//......
		end
		1:begin:exclude_swrite
			//......
		end
		default:begin:swrite
			//......
		end
	endcase // RX_ONLY
endgenerate

在这里插入图片描述
//221013
对于算数表达式的位宽问题,运算过程中的临时值的位宽应该会扩充到与整个表达式中(包括赋值左侧),最大位宽变量一致。
//221014
关于task使用:
task可以调用task和函数,反之函数不能调用task,但可以调用函数;
task中的输入输出,不能直接用于操作别的模块的输入输出;
例如top_tb.sv中例化了模块:
instance test(a,b);
调用task(a,b);task中对a、b的更改不会传递到test中。

//221103
Processor System Reset IP 复位顺序:
1、bus或者interconnect
2、peripheral
3、mb

//230209
拼接符{}使用:
在这里插入图片描述
此外,当想要将a + b的结果中的某些bit位赋值给c时,可采用:
c <= {a + b}[m:n];//时序
c = {a + b}[m:n];//组合
//230214
空语句:直接“;”即可

case(a)
	default:;
endcase
或者:
case(a)
	state1:begin
	
	end
endcase

//220214
xilinx推荐高电平复位;altera推荐低电平复位;
参考文献:
https://cloud.tencent.com/developer/article/1801181?shareByChannel=link#1.4
https://mp.weixin.qq.com/s?__biz=MzUyNTc4NTk0OA==&mid=2247484081&idx=1&sn=fa274fe2976efb4908c61aa414ed30b0&chksm=fa198c82cd6e0594248f63bba2fd6a9b83b08e4b20e3aa19beba52eea24b6ca2ac7f2844ceb1&scene=21#wechat_redirect

//230221
关于vivado时序报告,建立时间时序路径分析,目的时钟路径,最后的setup时间计算理解,原本是latch edge + tclk2 - Tsu,可能是考虑到C端到D端还有一段延时x,该延时减去Tsu,即x-Tsu = 0.059,所以最后加上了0.059。
在这里插入图片描述
//230604
关于 << 和 >> 位宽问题:
b <= a << n;
会将a低位补n个零,然后位宽增加n位赋值给b;
b <= a >> n;
会将a高位补n个零,然后位宽不变赋值给b;

//230707
下图结构,初始化时异或门两端输入均为0,则输出a_en为0,此时当异或门输入有一周期脉冲出现,则会让a_en输出变为1;直到异或门的下一脉冲输入,则输出a_en变为0;也就是异或门输入的1周期脉冲信号会让a_en发生反转。
在这里插入图片描述
//230921
参考链接:
https://blog.csdn.net/NcowGboyL/article/details/103171723
https://blog.csdn.net/weixin_45791458/article/details/128754313
https://blog.csdn.net/weixin_45791458/article/details/128772558
对于有符号数位宽扩展:
(1)首先表达式右边全为有符号数,才会进行有符号数运算;如果表达式右边存在无符号数,即进行无符号数运算,(其中未指定位宽和基数的为有符号数,如1、2等,而-3‘d2为无符号数)
(2)位宽扩展根据表达式左右两边进行,一些测试样例如下,注意res5和res8的区别,对于res5,我的理解为a已经为一个确定的值-8’d12 = 8‘b1111_0100,当成无符号数扩展后还是32’h0000_00f4;而对于res8,-8’d12中8’d12先进行位宽扩展为32’d12,然后再取“-”得到32‘hffff_fff4。
在这里插入图片描述
在这里插入图片描述
//240206
关于上述有符号数计算补充,右边计算的结果,赋值给左边为截断处理,如下图:
mul = signed(a) * signed(b);不管mul是有符号数还是无符号数,a * b的结果都截断后赋值给mul;
在这里插入图片描述
对于负数表示:
-4’d16,会将16截断为0,结果为-0 = 0;
所以负数的数值,需要用足够的位宽表示,如-5’d16;

//240103
对于建立时间时序分析:
arrive_time = Tlauntch_laytency+Tco+Tdelay_max;
require_time=Tcapture_laytency+Tclk-Tsu;
裕度:require_time-arrive_time;

对于保持时间时序分析:
arrive_time = Tlauntch_laytency+Tco+Tdelay_min;
require_time=Tcapture_laytency+Thd;
裕度:-(require_time-arrive_time);

对于最大输入延时:(类似于发射端的数据路径最大延时)
arrive_time = Tlauntch_laytency+Tinput_max;
require_time=Tcapture_laytency+Tclk-Tsu;
裕度:require_time-arrive_time;
对于最小输入延时:(类似于发射端的数据路径最小延时)
arrive_time = Tlauntch_laytency+Tinput_min;
require_time=Tcapture_laytency+Thd;
裕度:-(require_time-arrive_time);

对于最大输出延时:(类似于捕获端的建立时间)
arrive_time = Tlauntch_laytency+Tco+Tdelay_max;
require_time=Tcapture_laytency+Tclk-Toutput_max;
裕度:require_time-arrive_time;
对于最小输出延时:(类似于捕获端的保持时间,但是要取反,因为相对于虚拟时钟,hold所在的位置是捕获沿之后)
arrive_time = Tlauntch_laytency+Tco+Tdelay_min;
require_time=Tcapture_laytency+(-Touput_min);
裕度:-(require_time-arrive_time);

//240123
Verilog运算符优先级:
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值