Verilog踩坑日记

前言

如果对verilog FPGA及其Linux系统上的使用的相关知识有疑问可以参照:https://www.kancloud.cn/dlover/fpga/1251121

本人仿真环境: iverilog + gtkwave

2020年了,似乎去官网上下载modelsim只能下载student版本的,关键是还没有linux版本的,在eetop找的资源安装,都失败了。只好选择iverilog + gtkwave 了。
安装链接即步骤看链接:https://blog.youkuaiyun.com/zoomdy/article/details/79525870
链接中执行一次需要输入四行命令:

$:iverilog -o counter_test counter_tb.v counter.v
$:vvp -n counter_test -lxt2
$:cp counter_test.vcd counter_test.lxt
$:gtkwave counter_test.lxt

作为一个懒人,忍受不了,所以简单包装了一下,其中参数“gtk可选”:

bash iv.sh counter_tb.v counter.v
或者
bash iv.sh counter_tb.v counter.v gtk

#grep --exclude Defines.h Truthtable.h *

#!/usr/bin/env bash
#SELFDIR=$(dirname $(realpath "$BASH_SOURCE"))
SELFDIR=$(cd $(dirname "$BASH_SOURCE");pwd)
if [[ ${SELFDIR} == "" ]]; then
    echo "Internal error: can not locate the script dir"
    exit 1
fi
echo $1
if [ "$1" == "" ]
then
	echo  "Parameter Fail"
	echo " eg:bash iv.sh counter_tb.v counter.v"
	exit 1
elif [ "$2" == "" ]
then
	echo  "Parameter Fail"
		echo " eg:bash iv.sh counter_tb.v counter.v"
	exit 1
else
	echo  "Parameter OK  "
	iverilog -o counter_test $1 $2
	vvp -n counter_test -lxt2
	cp counter_test.vcd counter_test.lxt
fi 
if [ "$3" == "gtk" ]
then  
	gtkwave counter_test.lxt
fi

需要注意的是,这里的counter_test是因为之前的testbench里有对应的语句:

$dumpfile("counter_test.vcd");
$dumpvars(0,counter_test; 要记录的信号,level=0表示记录所有

它们表示记录对应的变量并保存,其中参数0表示记录所有变量。
initial begin
num=6;
power = 2;
rst = 1;
#100;
rst = 0;

#100000;
$finish;

end

坑1:testbench的顺序

在同步时序逻辑中,input的变量最好在rst复位之前声明如下:

initial begin
num=6;
power = 2;
rst = 1; 
#100;
rst = 0; 
#10000
$finish;
end

如果写成这样:

initial begin
rst = 1; 
#100;
rst = 0; 
num=6;
power = 2;
#10000
$finish;
end

看着也没什么毛病,但是本人仿真了一个晚上,跑出的波形,受影响的变量显示为X,也就是不定态。

坑2.verilog文件读写

摘自:https://blog.youkuaiyun.com/cxc19890214/article/details/41146531?utm_medium=distribute.pc_relevant.none-task-blog-title-3&spm=1001.2101.3001.4242

module read_write_file();
	integer fp_r,fp_w;
	integer count;
	reg [13:0] reg1;
	reg [13:0] reg2;
	reg [20:0] reg3;
	initial
		begin
			fp_r=$fopen("fntt.txt","r");//以读的方式打开文件
			fp_w=$fopen("data_out.txt","w");//以写的方式打开文件
 
			while(! $feof(fp_r))
				begin
					count=$fscanf(fp_r,"%d%d%d" ,reg1,reg2,reg3) ;//每次读一行
					$display("%d",reg1) ;//打印输出
					$fwrite(fp_w,"%d\t%d\t%d\n",reg1,reg2,reg3) ;//写入文件
				end
 
			$fclose(fp_r);//关闭已打开的文件
			$fclose(fp_w);
		end
endmodule		
  1. 注意这里与原链接中的代码略有不同,这里是一行读取三个数据,比如一行有三个数据,中间用“\t”隔开,就可以这样读取。
  2. 经本人踩坑,对于一行有三个数据,但是我只想读取其中的两个数据,还是要count=$fscanf(fp_r,"%d%d%d" ,reg1,reg2,reg3) ;//每次读一行三个都写上,处理的时候只处理两个就行了,倘若不三个一起读,而是改为count=$fscanf(fp_r,"%d%d" ,reg1,reg2) ;//每次读一行则读出的数据是错的。

坑3.@(negedge Clk)(没有always时)

代表等待一个下降沿?
http://forum.eepw.com.cn/thread/251730/1/

坑4.begin后的冒号?

begin:shift
XXXXXXXXXX
end

begin后面有个冒号代表对这个begin–end起个名字,没什么特殊含义

坑5.操作二维数组?

http://www.voidcn.com/article/p-thkupwlb-btg.html
转换成一维向量传输
读取ROM:http://cn.voidcc.com/question/p-znsrhazp-or.html
读ROM+写ROM:http://www.voidcn.com/article/p-chjjifpy-btx.html:$writememh $readmemh

坑六.case语句

原文:https://blog.youkuaiyun.com/fadbgfnbxb/article/details/89813526
case语句中有两种状态对就同一个电路?用逗号分开即可

reg [1:0]addr_cnt=2'b11;
reg read=1'b1;
always@(posedge clk_40M) begin
    addr_cnt <= addr_cnt + 1'b1;
    case(addr_cnt) 
      2'b00,2'b01: read <= 1'b0;//对某变量完全相同的操作,逗号隔开不同的分支
      2'b10:       read <= 1'b1;
      2'b11:       read <= 1'bz;//一个分支仅对一个变量赋值时,可以不用begin end
      default: ; //直接分号 等价于进行" read <= read;"操作
    endcase; 
end

1.Verilog描述

reg[7:0] mema[0:255] ;     声明一个数组mema为256*8bits寄存器,其索引为0~255,宽度为8
reg arrayb [7:0] [0:255];  声明一个二维数组,其数据为1位寄存器
time hist[1:1000];         有1000个时间值的数组

reg [1:n] rega;            一个n位的1个深度的寄存器(存储器)
reg mema [1:n];            一个1位的n个深度的寄存器(存储器)

2.操作符

==    :逻辑相等
===   :条件(case)相等
!==   :条件(case)不相等

~|    :规约或非

<<    :逻辑左移
<<<   :算术左移

a**b  :a的b次幂

3.延时

对门延时来讲

min:typical:maximum  最小值:典型值:最大值
eg:
	#(95:100:105) clk = 1;

4.assign && deassign

摘自:https://www.eefocus.com/xiaxing_fpga/blog/11-08/230004_7058d.html
assign用于对寄存器赋值(不可用于线网赋值),deassign用于取消之前由assign赋值给某寄存器的值,也就是说,使用assign给寄存器赋值之后,这个值将一直保持在这个寄存器上,直到遇到deassign为止。

module DEF(D,Clr,Clk,Q)
 input D,Clr,Clk;
 output Q;
 reg Q; 
 
 always@(negedge Clk)
  Q = D;
  
 always@(Clr)
  begin
   if(!Clr)
    assign Q = 0;
   else
    deassign Q;
  end
endmodule

以上的程序段,第一个always会将Q的值赋为D,第二个always语句在Clr的值发生变化时执行,若Clr是由高电平变为低电平,则assign有效,并一直保持这个赋值(直到遇到deassign),这时尽管第一个always也在执行(Clk的下降沿是不会起作用的),Q的值会一直保持“assign Q = 0;”,直到Clr来一个高电平为止(deassign Q语句执行)。

force-release(强制-释放,虽然它也可以用于对寄存器赋值,但主要用于线网赋值)
当force语句应用于寄存器时,寄存器当前值被force覆盖,当release语句应用于寄存器时寄存器当前值将保持不变,直到被重新赋值。

5.wait

摘自:https://www.cnblogs.com/ostien/p/3640816.html

Wait(var)

begin

  expression1;

  expression2;

  .....

end

other_expression;          //后续代码

当avr为真(非0)时,程序执行begin-end块里面的代码,然后继续执行other_expression代码。然而,当avr为假(0,x,z)时,程序暂停,一直等待avr变成真之后再继续执行,该语句不可以综合。可以像下面一样写代码:

6.fork ----join

fork -join结构之间的语句都是并发执行的

//下面这段语句将产生竞争条件
fork
	#5 a=b;
	#5 b=a;
join
//下面这段语句消除了竞争条件
//功能:数据交换
fork
	 a=#5b;
	 b=#5a;
join
//下面这段语句将产生竞争条件
//功能:数据移位
fork
	a=@(posedge clk) b;
	b=@(posedge clk) a;
join
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Greate AUK

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值