FPGA学习【番外】从vivado移植到modelsim

模块是模块,测试是测试

无论是在vivado或者是modelsim,模块声明文件和测试文件都是分开的,模块声明文件主要负责功能上的所有逻辑,测试文件主要负责产生合适的时钟和合适的输入,就像数电实验一样,模块文件就是老师给的各种芯片,测试文件就是搭建的电路和时钟时序,搭建完了之后看时序。
所以如果不是为了仿真,测试文件是一点用都没有,如果不是下载的话,vivadoli的引脚约束文件(也就是xdc文件)也是一点用都没有。

按道理来说可以是直接复制黏贴就可以直接运行的,但是在移植的时候发现还是有细微的改动。
首先在vivado里有一个工程是流水灯的,他的模块文件内容如下:

//===========================================================================
// Module name: led_test.v
//===========================================================================
`timescale 1ns / 1ps

module led_test 
(             
  sys_clk_p,      // Differentia system clock 200Mhz input on board
  sys_clk_n,
  rst_n,          // reset ,low active            
  led,             // LED,use for control the LED signal on board
  fan_pwm           //fan control
 );
             
//===========================================================================
// PORT declarations
//===========================================================================

input         sys_clk_p;
input         sys_clk_n;
input         rst_n;
output [3:0]  led;
output fan_pwm;
//define the time counter
reg [31:0]   timer;                  
reg [3:0]    led;
assign fan_pwm =1'b0;
//===========================================================================
//Differentia system clock to single end clock
//===========================================================================
wire        sys_clk;
 IBUFGDS u_ibufg_sys_clk   //专用原语,差分信号输入
     (
      .I  (sys_clk_p),            
      .IB (sys_clk_n),          
      .O  (sys_clk  )        
      );          
//===========================================================================
// cycle counter:from 0 to 1 sec
//===========================================================================
  always @(posedge sys_clk or negedge rst_n)    
    begin
      if (~rst_n)                           
          timer <= 32'd0;                     // when the reset signal valid,time counter clearing
      else if (timer == 32'd199_999_999)    //1 seconds count(200M-1=199999999) 系统时钟200Mhz,周期5ns,计数0-199_999_999,共2*10^8个周期
          timer <= 32'd0;                       //count done,clearing the time counter
      else
		    timer <= timer + 1'b1;            //timer counter = timer counter + 1,每周期上升沿计数
    end

//===========================================================================
// LED control
//===========================================================================
  always @(posedge sys_clk or negedge rst_n)   
    begin
      if (~rst_n)                      
          led <= 4'b0000;                  //when the reset signal active         
      else if (timer == 32'd49_999_999)    //time counter count to 0.25 sec,LED1 lighten
    
          led <= 4'b0001;                 
      else if (timer == 32'd99_999_999)    //time counter count to 0.5 sec,LED2 lighten
      begin
          led <= 4'b0010;                  
        end
      else if (timer == 32'd149_999_999)   //time counter count to 0.75 sec,LED3 lighten
          led <= 4'b0100;                                          
      else if (timer == 32'd199_999_999)   //time counter count to 1 sec,LED4 lighten
          led <= 4'b1000;                         
    end
    
endmodule


测试文件内容则是

`timescale 100ps / 1ps
//
// Module Name: vtf_led_test
//

module vtf_led_test;
	// Inputs
	reg sys_clk_p;
	wire sys_clk_n;
	reg rst_n;

	// Outputs
	wire [3:0] led;

	// Instantiate the Unit Under Test (UUT)
	led_test uut (
		.sys_clk_p(sys_clk_p), 
		.sys_clk_n(sys_clk_n), 		
		.rst_n(rst_n), 
		.led(led)
	);

	initial begin
		// Initialize Inputs
		sys_clk_p = 0;
		rst_n = 0;

		// Wait 100 ns for global reset to finish
		#1000;
          rst_n = 1;        
		// Add stimulus here
		#20000;
      //  $stop;
	 end
   
    always #25 sys_clk_p = ~ sys_clk_p;   //5ns一个周期,产生200MHz时钟源
    assign sys_clk_n=~sys_clk_p;
   
endmodule



上面的文件在vivado里是能够完全运行的,没有错误,但是在移植的时候,将模块文件复制移植到name.v文件,测试文件内容复制移植到name_tb.v文件里,在compile all的时候就会有错误。
①首先在模块声明文件中报错

 IBUFGDS u_ibufg_sys_clk   //专用原语,差分信号输入
     (
      .I  (sys_clk_p),            
      .IB (sys_clk_n),          
      .O  (sys_clk  )        
      );  
 //说是这个模块没有声明,找不到,所以首先把这个模块删除掉

②然后能compile了,也能start simulation了,但是没有波形,仔细查看后问题出在

//首先观察模块声明文件中的以下这一段代码
  always @(posedge sys_clk or negedge rst_n)    
    begin
      if (~rst_n)                           
          timer <= 32'd0;                     // when the reset signal valid,time counter clearing
      else if (timer == 32'd199_999_999)    //1 seconds count(200M-1=199999999) 系统时钟200Mhz,周期5ns,计数0-199_999_999,共2*10^8个周期
          timer <= 32'd0;                       //count done,clearing the time counter
      else
		    timer <= timer + 1'b1;            //timer counter = timer counter + 1,每周期上升沿计数
    end
//---------------------------------------------//
//再看看测试文件中的时钟代码
always #25 sys_clk_p = ~ sys_clk_p;   //5ns一个周期,产生200MHz时钟源
assign sys_clk_n=~sys_clk_p;

你会发现在模块声明文件中的激励信号是sys_clk,而测试文件里则是sys_clk_p,这就导致了声明中的功能块得不到激励信号,所以也就没有波形,接下来就知道怎么改了,在模块声明文件中修改那两个always块,修改成下面这个样子。我这里把流水灯的频率也给改了。

  always @(posedge sys_clk_p or negedge rst_n)    
    begin
      if (~rst_n)                           
          timer <= 32'd0;                     // when the reset signal valid,time counter clearing
      else if (timer == 32'd199_999_999)    //1 seconds count(200M-1=199999999) ????200Mhz???5ns???0-199_999_999,?2*10^8???
          timer <= 32'd0;                       //count done,clearing the time counter
      else
		    timer <= timer + 1'b1;            //timer counter = timer counter + 1?????????
    end

//===========================================================================
// LED control
//===========================================================================
  always @(posedge sys_clk_p or negedge rst_n)   
    begin
      if (~rst_n)                      
          led <= 4'b0000;                  //when the reset signal active         
      else if (timer == 32'd4_999_999)    //time counter count to 0.25 sec,LED1 lighten
    
          led <= 4'b0001;                 
      else if (timer == 32'd9_999_999)    //time counter count to 0.5 sec,LED2 lighten
      begin
          led <= 4'b0010;                  
        end
      else if (timer == 32'd14_999_999)   //time counter count to 0.75 sec,LED3 lighten
          led <= 4'b0100;                                          
      else if (timer == 32'd19_999_999)   //time counter count to 1 sec,LED4 lighten
          led <= 4'b1000;                         
    end

测试文件不需要改动,但是需要将时钟精度修改一下,首先在模块声明和测试文件的第一个没有注释的代码都是

`timescale 100ps / 1ps
//我们不需要那个高的仿真时钟精度,把它改成下面的这个代码,两个文件都要改
`timescale 1ns / 1ns

然后就能仿真了(注意仿真的时候不要使能这里)。
在这里插入图片描述
然后看一下波形:
在这里插入图片描述

这下对了。但是很奇怪的是,在原来的代码中明明在模块声明文件里的always里的激励信号和原测试文件的输入是不一样的,为什么在vivado里也能运行仿真。
移植后的代码:
模块声明文件:

`timescale 1ns / 1ns

module led_test 
(             
  sys_clk_p,      // Differentia system clock 200Mhz input on board
  sys_clk_n,
  rst_n,          // reset ,low active            
  led,             // LED,use for control the LED signal on board
  fan_pwm           //fan control
 );
             
//===========================================================================
// PORT declarations
//===========================================================================

input         sys_clk_p;
input         sys_clk_n;
input         rst_n;
output [3:0]  led;
output fan_pwm;
//define the time counter
reg [31:0]   timer;                  
reg [3:0]    led;
assign fan_pwm =1'b0;
//===========================================================================
//Differentia system clock to single end clock
//===========================================================================
wire        sys_clk;
       
//===========================================================================
// cycle counter:from 0 to 1 sec
//===========================================================================
  always @(posedge sys_clk_p or negedge rst_n)    
    begin
      if (~rst_n)                           
          timer <= 32'd0;                     // when the reset signal valid,time counter clearing
      else if (timer == 32'd199_999_999)    //1 seconds count(200M-1=199999999) ????200Mhz???5ns???0-199_999_999,?2*10^8???
          timer <= 32'd0;                       //count done,clearing the time counter
      else
		    timer <= timer + 1'b1;            //timer counter = timer counter + 1?????????
    end

//===========================================================================
// LED control
//===========================================================================
  always @(posedge sys_clk_p or negedge rst_n)   
    begin
      if (~rst_n)                      
          led <= 4'b0000;                  //when the reset signal active         
      else if (timer == 32'd4_999_999)    //time counter count to 0.25 sec,LED1 lighten
    
          led <= 4'b0001;                 
      else if (timer == 32'd9_999_999)    //time counter count to 0.5 sec,LED2 lighten
      begin
          led <= 4'b0010;                  
        end
      else if (timer == 32'd14_999_999)   //time counter count to 0.75 sec,LED3 lighten
          led <= 4'b0100;                                          
      else if (timer == 32'd19_999_999)   //time counter count to 1 sec,LED4 lighten
          led <= 4'b1000;                         
    end
    
endmodule


测试文件代码:

`timescale 1ns / 1ns
//
// Module Name: vtf_led_test
//



module vtf_led_test;
	// Inputs
	reg sys_clk_p;
	wire sys_clk_n;
	reg rst_n;

	// Outputs
	wire [3:0] led;

	// Instantiate the Unit Under Test (UUT)
	led_test uut (
		.sys_clk_p(sys_clk_p), 
		.sys_clk_n(sys_clk_n), 		
		.rst_n(rst_n), 
		.led(led)
	);

	initial begin
		// Initialize Inputs
		sys_clk_p = 0;
		rst_n = 0;

		// Wait 100 ns for global reset to finish
		#1000;
          rst_n = 1;        
		// Add stimulus here
		#20000;
      //  $stop;
	 end
   
    always #25 sys_clk_p = ~ sys_clk_p;   //5ns???????200MHz???
    assign sys_clk_n=~sys_clk_p;
   
endmodule


结束

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值