目录
设计定义
- 以设备50Mhz频率为例
- 50ms led翻转一次
设计输出(画出设计图)
注:本图主要分析计数器,led的反相器和低电平复位与计数器无关故先不看
代码编写(根据上面设计图设计代码)
设计图解析
- clk 根据设备频率控制时间
- cnt 记载时钟周期个数
- 输入数控制反转时间
- cnt 与输入数相等时led反转
- led 控制选择器输出
- led 未反转时 选择器选择 cnt+1
- led 反转时 选择器选择 cnt=0
控制时间的计算
- 设备50Mhz,则一个周期为20ns
- 50ms里有 50000000/20 个 20ns,即为2500000个20ns
- 故要想50ms反转一次,则输入数应为 2499999
- 将2499999(10进制)转换为 26259F(16进制)
- 故cnt中位数为 4*5+2=22 故cnt应定义为 reg [21:0]cnt
由以上分析编写代码
注:模块名必须和项目名称一致否则会有错误
module counter (clk,rst,led);//时钟周期,低电平复位,灯 input clk;//系统时钟 ,50M input rst;//全局复位, 低电平复位 output led;//led输出 reg led;//计数要用到22位寄存器,25_000_00(10进制)-> 26 259F(16进制) =4*5+2=22 reg [21:0]cnt; //计数器的自加进程 always@(posedge clk or negedge rst)//时序逻辑过程赋值写法 begin if(rst == 1'b0)//低电平复位 cnt <= 22'b0;//非阻塞类型 <= else if(cnt == 2499_999) cnt <= 0; else cnt <= cnt+1; end //led输出控制进程 always@(posedge clk or negedge rst)/verilog always块并行运行 begin if(rst == 1'b0) led <= 1'b1; else if(cnt == 2499_999) led=~led; end endmodule
功能仿真
`timescale 1ns/1ns//单位/精度
`define clock_period 20 //宏定义,便于修改(根据设备频率而修改)
module counter_tb;
reg clk; //激励 reg 观测 wire
reg rst;
wire led;
counter counter0( //端口例化,括号里要写东西!!!
.clk(clk),
.rst(rst_n),
.led(led)
);
initial clk = 1; //个人习惯都可以,设置时钟周期
always #(`clock_period/2) clk = ~clk; //随系统时钟的改变而改变,故定义为宏定义通用性更强
initial //激励例化端口
begin
rst_n = 1'b0; //复位
#(`clock_period*200) //200个时钟周期
rst_n = 1'b1;
#20000000
$stop;
end
endmodule