学会使用Hdlbits网页版Verilog代码仿真验证平台

5 篇文章 0 订阅

给大家推荐一款网页版的 Verilog代码编辑仿真验证平台,这个平台是国外的一家开源FPGA学习网站,通过“https://hdlbits.01xz.net/wiki/Main_Page” 地址链接进入网页,在该网页上可以进行Verilog代码的编写、综合,而且最后还能够仿真出波形来验证设计代码的正确性,该验证平台是基于Icarus Verilog(简称iVerilog,比较著名的开源HDL仿真工具,也有对应的安装版本)的,让你随时随地只需登录网页就能够享受Verilog编程仿真的乐趣!

一、官方模板演示

1、首先打开“https://hdlbits.01xz.net/wiki/Main_Page” , 打开后的界面如下图所示,全英文显示。如果感觉自己的英文水平欠佳,可以使用谷歌浏览器打开该网页,并选择在线翻译功能,翻译的正确率还是很高的。
在这里插入图片描述
2、点击Simulation下的 ”Run a Simulation(lcarus Verilog)“。
在这里插入图片描述
3、打开后的界面如下图所示,代码编辑框中给出了一个简单的例子。
在这里插入图片描述
4、点击下面的“Submit(new window)“在新界面中进行仿真。
在这里插入图片描述
5、在新打开的界面中我们可以看到编译的信息和仿真波形图。
在这里插入图片描述

二、实例演示

虽然看完了官方的模板演示,但我们要想立刻仿真验证自己设计的代码并不是那么容易,需要进行一番摸索。下面就是大家进行一个呼吸灯的设计实例演示。
1、学习过FPGA的朋友都知道要想对FPGA逻辑进行仿真一定要具备两个文件,一个是RTL代码文件,用来综合生成硬件电路的部分;第二个就是Testbench文件,用来验证RTL代码功能的仿真文件,这两者缺一不可。
2、根据观察发现官方模板中的代码编辑部分有两个module,大家也都知道一个.v 文件中只能有一个模块,也就是只能有一个module,而这里面有两个,那肯定就不对了。再仔细观察会发现代码编辑区域中的上半部分就是Testbench,而下半部分则是RTL代码,再结合仿真出的波形来更看验证了这个想法。原来 RTL 代码和Testbench都写在了一个编辑框里。
3、但是我们在提供的模板中发现一些我们平时几乎没有见过的新语法,如第4行的

initial `probe_start;

第6行的

` probe(clk);

第26行的

`probe(in);

通过模板的注释和多次实验发现这是官方定义的一个”宏“,也就是通过这个”宏“调用“probe”探针的功能,我们不用管这个”宏“是如何定义的,我们只需要会调用就可以了。
4、下面我们通过该网页来仿真验证一下自己设计的呼吸灯的例子。详细代码如下(呼吸灯逻辑和Testbench代码的编写方法这里我们不做讲解,会在以后的文章中再进行详细说明),下面代码可以全部直接复制使用(代码中的注释请详细阅读)。

`timescale	1ns/1ns

//----------------Tesebench-----------------
module	top_module;		    //仿真文件名必须是“top_module”

reg		sclk;
reg		rst_n;

wire	led;
    
initial `probe_start;   	// Start the timing diagram

	`probe(sclk);       	// Probe signal "clk",这是加载的系统时钟,只能在Tesebench中加载    
    
//初始化
initial	begin
	sclk   = 1'b0;
	rst_n <= 1'b0;
	#200
	rst_n <= 1'b1;
    #5000					//一定要设置仿真停止时间,如果仿真结束时间太久会提示
    $finish; 
end

//产生20ns的时钟
always	#10	sclk =	~sclk;

//为了减少仿真时间我们在仿真中重定义参数,不影响RTL代码中参数的值
defparam	breath_led_inst.CNT_1US_MAX	 = 1;
defparam	breath_led_inst.CNT_1MS_MAX  = 2;
defparam	breath_led_inst.CNT_1S_MAX   = 2;

//----------------breath_led-----------------
breath_led	breath_led_inst(
	.sclk	(sclk	),	//input	    sclk	
	.rst_n	(rst_n	),	//input	    rst_n	
	                      
	.led    (led  	)	//output	led
);

endmodule	

//----------------RTL-----------------
module	breath_led
#(
	parameter CNT_1US_MAX = 6'd49,
	parameter CNT_1MS_MAX = 10'd999,
	parameter CNT_1S_MAX  = 10'd999
)
(
	input   wire	sclk	,
	input   wire	rst_n	,
	
	output	reg		led
);

reg	[5:0] cnt_1us;	
reg	[9:0] cnt_1ms;	
reg	[9:0] cnt_1s;		
reg		  cnt_1us_flag;
reg		  cnt_1ms_flag;
reg		  cnt_1s_flag;

//cnt_1us:1us计数器
always@(posedge sclk or negedge	rst_n)
	if(rst_n == 1'b0)	
		cnt_1us <= 6'b0;	
	else	if(cnt_1us	== CNT_1US_MAX)	
		cnt_1us <= 6'b0;
	else
		cnt_1us <= cnt_1us + 1'b1;

//cnt_1us_flag:1us计数器标志信号
always@(posedge sclk or negedge	rst_n)
	if(rst_n == 1'b0)	
		cnt_1us_flag <= 1'b0;	
	else	if(cnt_1us	==	CNT_1US_MAX)	
		cnt_1us_flag <= 1'b1;
	else
		cnt_1us_flag <= 1'b0;

//cnt_1ms:1ms计数器
always@(posedge sclk or negedge	rst_n)
	if(rst_n == 1'b0)	
		cnt_1ms <= 10'b0;	
	else	if(cnt_1ms == CNT_1MS_MAX && cnt_1us_flag == 1'b1)	
		cnt_1ms <= 10'b0;
	else	if(cnt_1us_flag == 1'b1)
		cnt_1ms <= cnt_1ms + 1'b1;
		
//cnt_1ms_flag:1ms计数器标志信号
always@(posedge sclk or negedge	rst_n)
	if(rst_n == 1'b0)	
		cnt_1ms_flag <=	1'b0;	
	else	if(cnt_1ms == CNT_1MS_MAX && cnt_1us_flag == 1'b1)	
		cnt_1ms_flag <= 1'b1;
	else	
		cnt_1ms_flag <= 1'b0;

//cnt_1s:1s计数器
always@(posedge sclk or negedge	rst_n)
	if(rst_n == 1'b0)	
		cnt_1s	<=	10'b0;	
	else	if(cnt_1s == CNT_1S_MAX && cnt_1ms_flag == 1'b1)	
		cnt_1s	<=	10'b0;
	else	if(cnt_1ms_flag == 1'b1)
		cnt_1s	<=	cnt_1s	+ 1'b1;

//cnt_1s_flag:1s计数器标志信号
always@(posedge sclk or negedge	rst_n)
	if(rst_n == 1'b0)	
		cnt_1s_flag <= 1'b0;	
	else	if(cnt_1s == CNT_1S_MAX && cnt_1ms_flag == 1'b1)	
		cnt_1s_flag <= ~cnt_1s_flag;	
	
//led:一个LED灯
always@(posedge sclk or negedge	rst_n)
	if(rst_n == 1'b0)
		led	<= 1'b0;	
	else	if((cnt_1s_flag == 1'b1 && cnt_1ms <= cnt_1s) || (cnt_1s_flag == 1'b0 && cnt_1ms > cnt_1s))
		led	<= 1'b1;
	else	
		led	<= 1'b0;
	
//添加要观察的信号名
	`probe(rst_n		);	// Sub-modules can also have `probe()
    `probe(cnt_1us		);	// Sub-modules can also have `probe()
	`probe(cnt_1us_flag	);	// Sub-modules can also have `probe()
	`probe(cnt_1ms		);	// Sub-modules can also have `probe()
	`probe(cnt_1ms_flag	);	// Sub-modules can also have `probe()
	`probe(cnt_1s		);	// Sub-modules can also have `probe()
	`probe(cnt_1s_flag	);	// Sub-modules can also have `probe()
	`probe(led			);	// Sub-modules can also have `probe()

endmodule 

5、将上面编写好的Testbench代码和RTL代码放到一个文件中(Testbench在上面,RTL代码在下面,仅在该平台仿真时可以将两种文件放在一起,在其他平台仿真时要独立放到两个.v文件中),然后复制粘贴到代码编辑框中,点击“Submit(new window)“执行仿真。
在这里插入图片描述
6、也可以将写好的Testbench代码和RTL代码放到同一个.v文件中,然后点击下面的代码编辑框下面的“Upload a source file…”,在展开的界面中选择添加.v文件后,再点击”Upload and simulate”启动仿真。
在这里插入图片描述
在这里插入图片描述
7、仿真波形如下所示,因为界面空间有限,拖动波形显示框下面的滚动条,可以看到后面的波形显示。
在这里插入图片描述
8、在波形显示框中右击鼠标可以选择保存为PNG格式或SVG格式,将完整的波形信息保存下来。
在这里插入图片描述
9、保存为SVG格式后的完整波形图如下所示。
在这里插入图片描述
10、如果我们在第58行处代码设置一个错误后,再点击执行仿真,此时在仿真窗口中不会显示波形,而是提示错误的内容,将错误修改后再执行仿真即可。
在这里插入图片描述在这里插入图片描述
11、该网页还有其他更多有趣的功能,如组合逻辑代码编写训练、时序逻辑代码编写训练、单片机嵌入式仿真等等,有兴趣的朋友可以自己探索,这里不再一一演示。
  欢迎加入FPGA技术学习交流群,本群致力于为广大FPGAer提供良好的学习交流环境,不定期提供各种本行业相关资料!QQ交流群号:450843130
在这里插入图片描述

### 回答1: 要对ADS8688的Verilog代码进行仿真,需要以下步骤: 1. 创建一个新的Verilog项目。可以使用任何常见的Verilog仿真工具,如ModelSim、Vivado等。 2. 下载ADS8688的Verilog代码,并将其添加到项目文件夹中。 3. 打开仿真工具,并创建一个新的仿真项目或工程。 4. 将ADS8688的Verilog代码添加到仿真项目中。可以使用仿真工具提供的“添加文件”选项,选择ADS8688的Verilog代码文件。 5. 打开仿真设置窗口,并设置仿真的时钟周期和仿真时长。可以根据需要调整这些参数。 6. 添加仿真测试台以测试ADS8688的各种功能。测试台在仿真工具中一般是使用Verilog或SystemVerilog语言编写,被用于对被仿真的设计进行输入激励,以及对输出结果进行验证。 7. 在仿真工具中启动仿真,等待仿真运行结束。 8. 检查仿真结果,并根据需要进行调试。可以检查输出信号是否与预期一致,以及是否有任何潜在的错误或异常情况发生。 9. 如果仿真运行顺利且仿真结果符合预期,则可以认为ADS8688的Verilog代码仿真成功。 需要注意的是,由于缺乏ADS8688的具体代码仿真环境的信息,这只是一个一般性的步骤指南。具体的仿真过程可能因为实际情况而略有不同。对于特定的仿真需求和问题,应该查阅ADS8688的文档或参考相关资料,以获取更准确的指导。 ### 回答2: 为了回答你的问题,以下是ads8688的Verilog代码的简单仿真示例: module ads8688_sim; //定义输入输出端口 reg clk; reg reset; wire [15:0] data; wire data_ready; //实例化ADS8688模块 ads8688 DUT ( .clk(clk), .reset(reset), .data(data), .data_ready(data_ready) ); //时钟生成器 always #5 clk = ~clk; //设置5个时间单位的时钟周期 //复位信号生成器 initial begin reset = 1; #10; //给足够的时间来保持复位状态 reset = 0; #10; //给足够的时间来进入正常工作状态 end //数据读取和处理 always begin if (data_ready) $display("读取到的数据为 %d", data); end endmodule 上述代码中,我们首先定义了输入输出端口。其中clk和reset是reg类型的信号,data和data_ready是wire类型的信号。然后我们实例化了ads8688模块,并将输入输出端口连接到模块的对应信号上。 接下来,我们使用always块定义了一个简单的时钟生成器。我们设置时钟信号clk在5个时间单位内进行一次正/反相的切换。 然后,我们使用initial块定义了一个复位信号生成器。我们首先将reset信号置为1,然后等待10个时间单位,再将reset信号置为0,再等待10个时间单位。 最后,我们使用always块定义了一个数据读取和处理过程。在每个时间单位中,检查data_ready是否为1。如果是1,我们使用$display打印读取到的数据。 以上是一个基本的ads8688的Verilog代码仿真示例。你可以根据需要进行修改和扩展来满足你的实际需求。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值