FPGA编写仿真信号

FPGA编写仿真信号

PWM测试信号1

  • 说明
    This program aims to simulate the generation of PWM.
    You can change the pulse width in PWM_test.vt file which is defined as a macro definitoin.
    In comparsion, varible clk is set to square wave with a frequency of 1MHz.
    ps:这个是固定了时钟频率,来改变脉宽;PWM测试信号2不同。

  • PWM_test.v

    /* Comments -- PWM_test.v
     The aim of this program is to generate PWM signal.
     So the main part is in the PWM_test.vt file.
     Thus the PWM_test.v file has no actual meaning, just to avoid errors.
    */
    module PWM_test
    (
    	input clk,
    	output pwm_reverse
    );		
    	assign pwm_reverse = 1'b0;
    endmodule
    //verilog在这没得语法高亮哇,这里编辑用的JavaScript
    
  • PWM_test.vt
    这个是testbench文件;

    `timescale 1 ns/ 1 ns	//1M = 10^6 ->  1us = 10^3ns
    
    `define PERIOD	1000  //Frenquency is 1MHz -> period is 1us, while the time Unit is 1ns in .vt file,
    `define PULSE_WIDTH 500 //change pulse width here,sacle:[0:1000]
    
    module PWM_test_vlg_tst();
    	reg eachvec;
    	
    	reg clk;//square wave,frenquency:1M
    	reg pwm;//
                                        
    	wire pwm_reverse;
                        
    	PWM_test i1 (
            .clk(clk),
            .pwm_reverse(pwm_reverse)
    	);
    	initial                                                
    		begin                                                  
    			clk = 1'b1;//initial high voltage						
    			pwm = 1'b1;                                                                                                     
    		$display("Running testbench");                       
    	end  
    
    	always
    		begin
    			#`PERIOD clk = ~clk;//square wave
    		end															  
    	always                                                              
    		begin                                                                      
    			case(pwm)
    				1'b0:
    					begin
    						#(`PERIOD -`PULSE_WIDTH) pwm <= ~pwm;//change into high voltage
    					end
    				1'b1:
    					begin
    						#`PULSE_WIDTH pwm <= ~pwm;//change into low voltage
    					end
    				default:
    					begin
    						pwm <= 1'b0;//default low voltage
    					end
    			endcase																				  
    		//@eachvec;  //in order to simulate longer period, delete this                                                                                   
    		end                                                    
    endmodule
    //这里编辑用的Java高亮
    
  • 仿真结果 – modelsim 手动仿真
    1. PULSE_WIDTH 宏定义为500时:

    2. PULSE_WIDTH 宏定义为300时:
    在这里插入图片描述

  • Comments
    1. 在testbench中可以有多个always语句,因为always是并行的,所以各自的延时不会相互干扰到(新手哈哈);
    2. 在.vt中的变量initial后,若是在.v中也是这个这个变量名,那么他们是一个东西呀!这里一开始和task的调用混了,把module调用了,反正就是还没清楚就各种混;
    3. testbench中的 @eachvec; 语句:
    一开始在仿真中发现PWM的波形只翻转了一次,debug看发现第二个always中只进去了一次,但是第一个always却一直可以进去,然后对比发现第二个always中有一个生成testbench文件时自带的 @eachvec; 语句,搜一下后还是没太懂:

    1. 自动生成的testbench文件中包含一个全局寄存器eachvec,其包含一个语句@eachvec,记得把它注释掉,否则可能会因为它没有触发而导致仿真失败;
    2. 如果把@eachvec;那一行注释掉的话你仿真才能得到一段很长的波形,不然你的仿真时间就非常短,如果在它之前有在这个always过程块里规定时钟信号的翻转的话,这个时钟信号也不会翻转;
      链接: 有关eachvec

    最后把它注释掉波形就好了;

    4. 在修改testbench后最好重新write一下,不仅仅是只编译一下,修改了的.v的东西好像加载不进去,不过注意把在testbench修改的东西先怎么保存一下,我用的NotePad++;
    5. ModelSim看波形时,犯了个错:修改了.v程序但是忘记重新加载它了,只记得重新加载.vt文件了!!!(因为把.v和.vt文件都复制放在了一个manual_modelsim文件夹中去存放仿真的东西,所以每次在Quartus改并编译后都要重新复制一下);
    6. (感觉上面两条都有点操作的麻烦ye~)
    ps: 在写博客的时候才发现自己原来注释有的地方标错了哈哈!

PWM测试信号2

  • 说明
    ps:这个是模仿单片机PWM信号:先设置一个主频,然后再设置period,pulse_width,通过计数来产生PWM信号。

  • 主要变量说明

    • main_clk_value:作主频大小,在initial中赋值为10,(仿真时间定位1ns),所以对应100MHz;
    • main_clk_sig:实际产生主频的信号;
    • pwm_period
      pwm_pulse_width
  • PWM_test_v2.v

    module PWM_test_v2
    ( 
    	input [3:0] main_clk_value,
    	input main_clk_sig,
    
        input [31:0] pwm_period,
        input [31:0] pwm_pulse_width,
    	 
    	 output reg pwm	  
    );
    reg [26:0]  time_cnt = 27'd0;//直接赋初值就行
    
    always  @ (posedge main_clk_sig)//main_clk_sig是在testbench中产生的时钟信号
    	begin
    		time_cnt <= time_cnt + 27'd1;
    
    	 	if((time_cnt >= ((pwm_period - pwm_pulse_width)/main_clk_value)) &&(time_cnt < (pwm_period/main_clk_value)))
    			begin
    				pwm <= 1'b1;
    			end
    	 	else if (time_cnt >= (pwm_period/main_clk_value))
    			begin
    				pwm <= 1'b0;
    				time_cnt <= 27'd1;
    			end       
    	 	else
    			begin
    				pwm <= 1'b0;	
    			end
        end
    endmodule
    //verilog在这没得语法高亮哇,这里编辑用的JavaScript
    
  • PWM_test_v2.vt
    这个是testbench文件;

    `timescale 1 ns/ 1 ns
    module PWM_test_v2_vlg_tst();
    	reg eachvec;
    	
    	reg [3:0] main_clk_value;
    	reg main_clk_sig;//相当于主频,用于产生一下基本测试信号
    	
    	reg [31:0]  pwm_period;//这里位宽也记得
    	reg [31:0]  pwm_pulse_width;
                                               
    	wire pwm;
                         
    PWM_test_v2 i1 (  
    	.main_clk_sig(main_clk_sig),
    	.pwm_period(pwm_period),
    	.pwm_pulse_width(pwm_pulse_width),
    	.pwm(pwm),
    	.main_clk_value(main_clk_value)	
    );
    	initial                                                
    		begin                                                                          
    			main_clk_value = 4'd10;//注意这里和.v文件里的位宽!		  
    			main_clk_sig = 1'b0;		
    			
    			pwm_period = 32'd100; 
    			pwm_pulse_width = 32'd30;                    
                            
    			$display("Running testbench");                       
    		end  		
    	always //genreate 主频                                                      
    		begin                                                                        
    			#(main_clk_value>>1) main_clk_sig = ~main_clk_sig;                                                  
    		//@eachvec;                                                                                       
    		end                                                    
    endmodule
    //这里编辑用的Java高亮
    
  • 仿真结果 – modelsim 手动仿真
    pwm_pulse_width赋初值为30,pwm_period为100时(仿真时间单位设置的1ns):
    在这里插入图片描述

  • Comments
    1. 有关赋初值:

    • 变量time_cnt,定义为reg型(因为要在always语句中对它赋值,所以必须是reg型);reg型直接在定义时赋初值🆗;(看到有人说用rst信号去赋初值,不知道直接这么赋值在实际电路中行不行)
    • assign time_cnt = 27'd0; 这个只是网型变量(wire)才能这么赋值,代表用线连接起来,默认类型是wire型(如input,input就是input,不可以定义为 input reg),若把output定义为reg型才不是wire型;

    2. 有关testbench文件:
    之前对这个文件没什么认知(虽然现在也就多了一点点haha);
    .vt 文件中的PWM_test_v2 i1(); 就是在例化写的module PWM_test_v2!

    Testbench name :grey_even_tst(testbench的文件名)
    Top level module :grey_even_vlg_tst(testbench的module名)
    Design instance module name:i1(待测试module 在testbench的例化module名)
    转载

    ps: .vt文件中定义为wire、reg型,之前具体什么型还不会判断,就让testbenhc自动生成了,从上面链接的文章中可以知道:

    input 端口在xxx_vlg_tst();中要定义为同名reg变量,output 端口要定义为同名wire变量

  • 小错误
    1. 一开始在testbench中写了一个空always语句!因为testbench自动生成时带有一个always,但是自己又添加了一个,就没有在那个always里改,但也没有删哈哈,然后就没有波形出来检验一下

    2.

    #(`MY_BASIC_CLK_100M/2) //延时,,MY_BASIC_CLK_100M 是个宏定义,不过后来换掉没用这个了;
    

    这里一开始写成了:

    #`(MY_BASIC_CLK_100M/2)//haha
    

    然后给我报错xxx in macro expansion来着;

    3.input [31:0] pwm_period,中,一开始忘记改的位宽了!testbench中特是要加位宽的!reg [31:0] pwm_period;

    4. 左右移:a>>2,是将a左移2位,相当于除4!左移一位才是除2!(左右移比直接用乘除号速度快些)

    移位之后空出来的位用0来填充。进行移位运算之后要注意移位前后变量的位数:
    转载

      4'h1001<<1  移位之后的变量为5'b10010
      4'b1001 <<2 移位之后的变量为6'b10010
      1<<6 移位之后为32'b1000000 //6是默认的32位,所以再左移最大也是32位  
      4'b1001 >>1 移位之后为4'b0100
      4'b1001>>4 移位之后为4'b0000</font>	
    

    ps: 和同学讨论一下,听听他们的看法,帮他们排排错真的很🆗!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值