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; 语句,搜一下后还是没太懂:- 自动生成的testbench文件中包含一个全局寄存器eachvec,其包含一个语句@eachvec,记得把它注释掉,否则可能会因为它没有触发而导致仿真失败;
- 如果把@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名)
转载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: 和同学讨论一下,听听他们的看法,帮他们排排错真的很🆗!!