本学习笔记主要参考小梅哥B站教学视频,网址如下:
https://www.bilibili.com/video/BV1va411c7Dz?p=1
使用的编译器为Vivado,HDL语言为verilog
一、从计数器到可控线性序列机
1.1 让LED按照亮0.25s,灭0.75s的状态循环亮灭。
思路:设置计数器计数到1s才清零。不用取反操作,而是在相应位置处拉高或者拉低电平。
设计文件:
module counter_led_0(
Clk,
Reset_n,
Led
);
input Clk;
input Reset_n;
output reg Led;
reg [25:0] counter;
parameter MCNT = 50000000;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
counter <= 0;
else if(counter == MCNT-1)
counter <=0;
else
counter <= counter + 1'b1;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
Led <= 0;
else if(counter == (MCNT/2+MCNT/4)-1) //0.75s处
Led <= 1;
else if(counter == MCNT-1)
Led <= 0;
endmodule
测试文件:
`timescale 1ns/1ns
module counter_led_0_tb;
reg Clk;
reg Reset_n;
wire Led;
counter_led_1
#(
.MCNT(125000) //将参数调小一些
)
counter_led_1(
.Clk(Clk),
.Reset_n(Reset_n),
.Led(Led)
);
initial Clk = 1;
always #10 Clk = !Clk; //~按位取反,单位信号时与!等价
initial begin
Reset_n = 0;
# 201; //避开时钟上升沿,方便观察
Reset_n = 1;
#2000000000; //两秒钟
$stop;
end
endmodule
仿真结果:
1.2 让LED灯按照指定的亮灭模式亮灭,亮灭模式未知,由用户随机指定。以0.25s为一个变化周期,8个变化状态为一个循环
思路:2秒为一个循环周期,拿出一个ctrl(输入端口)来控制LED的亮灭模式,
设计文件:
module counter_led_2(
Clk,
Reset_n,
Ctrl,
Led
);
input Clk;
input Reset_n;
input [7:0]Ctrl;
output reg Led;
reg [26:0] counter;
parameter MCNT = 100000000;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
counter <= 0;
else if(counter == MCNT-1)
counter <=0;
else
counter <= counter + 1'b1;
// always@(posedge Clk or negedge Reset_n)
// if(!Reset_n)
// Led <= 0;
// else if(counter == MCNT/8-1)
// Led <= Ctrl[0];
// else if(counter == MCNT*2/8-1)
// Led <= Ctrl[1];
// else if(counter == MCNT*3/8-1)
// Led <= Ctrl[2];
// else if(counter == MCNT*4/8-1)
// Led <= Ctrl[3];
// else if(counter == MCNT*5/8-1)
// Led <= Ctrl[4];
// else if(counter == MCNT*6/8-1)
// Led <= Ctrl[5];
// else if(counter == MCNT*7/8-1)
// Led <= Ctrl[6];
// else if(counter == MCNT-1)
// Led <= Ctrl[7];
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
Led <= 0;
else case(counter)
MCNT*1/8-1:Led <= Ctrl[0];
MCNT*2/8-1:Led <= Ctrl[1];
MCNT*3