笔记1 简单的蜂鸣器实验<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
实验的开始就是蜂鸣器的实验,作为入门实验,掌握VerilogDHL语言的概念确实很不错。这章笔记主要是分析Verilog DHL的源码,因为这就是实验的目的。其他的东西就不详谈了。
module lesson01 (clk, rst_n, clk_div);
input clk;
input rst_n;
output clk_div;
reg[19:0] count;
reg clk_div_r;
//---------------------------------------------------
always @ (posedge clk or negedge rst_n)
if(!rst_n)
count <= 20'd0;
else
count <= cnt+1'b1;
//----------------------------------------------------
always @ (posedge clk or negedge rst_n)
if(!rst_n)
clk_div_r <= 1'b0;
else if(count == 20'hffffff)
clk_div_r <= ~clk_div_r;
//----------------------------------------------------
assign clk_div = clk_div_r;
endmodule
以上的模块引入了clk,rst_n,,clk_div wire型的引脚,前两者为输入,后者为输出。该模块建立了两个寄存器,一个是20位的counter寄存器,和一个(默认32位)clk_div_r的寄存器。前者用来计数,后者原来记录某种状态。
Always块的作用,大家估计都知道了吧!?只要@内的条件触发都会执行一次always里面的代码。
我们先看第一个always块,该always块是每个时钟的上升沿都会使count寄存器递增。而第二个always块的功能是每个时钟的上升沿都检查count寄存器的值是否等于0xfffff,如果等于条件成立,那么clk_div_r就会赋予自己求反的结果。最后利用clk_div_r的结果来设置clk_div的逻辑。(assign是用来建立逻辑表达式)
在这里,有几个容易犯错的概念。CDPL不像单片机那样都是顺序执行代码,而它会因不同的代码编辑方法,而执行不一样的功能。如上题:寄存器的建立是一开始就完成。always块是都时同是执行的。而且寄存器的初始化在always块的rst_n下降沿完成。
那么蜂鸣器的频率是多少呢?使用晶振是50Mhz,那么该表示计数器每20ns递增一次。Count寄存器的最大值是20位,也就是说...
( 2^20 ) - 1 = 1045876 ;
14045875 * 20ns = 20.97152 ms
蜂鸣器每20.97142 ms翻转一次,一个周期是 2* 20.97142ms ,大约是40 ms。
所以蜂鸣器的频率是 25Hz。
结束语:
我错了,我一开始把它当着单片机来看,害了自己走了很大的弯路,CDPL真的很强大(我开始学AVR的时候,也说AVR很强大)。最后还有一个重点就是,那个 <= 阻塞赋值运算符,要好好理清他的作用,不然是读不明白该代码的。
用户1609127 2010-2-23 13:25
用户146077 2010-2-19 18:30