verilog hdl语言学习笔记
作业1:
程序语言VerilogHDL,用FPGA板完成要求:
用点亮4盏LED灯;
4盏LED灯在1秒内轮流点亮,即每盏LED灯的点亮时间是250毫秒;
一个轮流完成后,用一个4位的加法器累加LED循环的次数;
即当每一轮第四盏LED熄灭后,这四盏LED灯将以点亮的方式表示出加法器中的16进制的数值 (全灭为0,灭灭灭亮为1,灭灭亮灭为2,灭灭亮亮为3,依次类推),点亮时间为2秒;
加法器的数值从0~F循环。
我完成的代码:
`timescale 1ns / 1ps
module led_test
(
input clk, // system clock 50Mhz on board
input rst_n, // reset ,low active
output reg[3:0] led // LED,use for control the LED signal on board
);
//define the time counter
reg [31:0] timer;
reg [3:0] count;
//integer i;
// cycle counter:from 0 to 4 sec
always@(posedge clk or negedge rst_n)
begin
if (rst_n == 1'b0)
timer <= 32'd0; //when the reset signal valid,time counter clearing
else if (timer == 32'd149_999_999) //4 seconds count(50M*4-1=199999999)
timer <= 32'd0; //count done,clearing the time counter
else
timer <= timer + 4'd1; //timer counter = timer counter + 1
end
// LED control
always@(posedge clk or negedge rst_n)
begin
if (rst_n == 1'b0)
led <= 4'b0001;
else if (timer == 32'd0) //time counter count to 1st sec,LED1 lighten
led <= 4'b0001; //when the reset signal active
else if (timer == 32'd12_499_999) //time counter count to 1st sec,LED1 lighten
led <= 4'b0010;
else if (timer == 32'd24_999_999) //time counter count to 2nd sec,LED2 lighten
led <= 4'b0100;
else if (timer == 32'd37_499_999) //time counter count to 3rd sec,LED3 lighten
led <= 4'b1000;
else if (timer == 32'd49_999_999) //time counter count to 4th sec,LED4 lighten
led <= 4'b0000;
else if (timer == 32'd62_499_999) //time counter count to 4th sec,LED4 lighten
// i= (count[0]+(count{1}&2)+(count{2}&4)+(count{3}&8));
case(count)
4'b0000 : led <=4'b0000;
4'b0001 : led <=4'b1000;
4'b0010 : led <=4'b0100;
4'b0011 : led <=4'b1100;
4'b0100 : led <=4'b0010;
4'b0101 : led <=4'b1010;
4'b0110 : led <=4'b0110;
4'b0111 : led <=4'b1110;
4'b1000 : led <=4'b0001;
4'b1001 : led <=4'b1001;
4'b1010 : led <=4'b0101;
4'b1011 : led <=4'b1101;
4'b1100 : led <=4'b0011;
4'b1101 : led <=4'b1011;
4'b1110 : led <=4'b0111;
4'b1111 : led <=4'b1111;
endcase
end
always@(posedge clk or negedge rst_n)
begin
if (rst_n == 1'b0)
count <= 4'd0;
else if (timer == 32'd149_999_999)
count <= count + 4'd1;
end
endmodule
更新代码(改进了最后led灯的赋值方式):
`timescale 1ns / 1ps
module led_test
(
input clk, // system clock 50Mhz on board
input rst_n, // reset ,low active
output reg[3:0] led // LED,use for control the LED signal on board
);
//define the time counter
reg [31:0] timer;
reg [3:0] o_cnt;
// cycle counter:from 0 to 4 sec
always@(posedge clk or negedge rst_n)
begin
if (rst_n == 1'b0)
begin
timer <= 32'd0;
o_cnt <= 4'd0; //when the reset signal valid,time counter clearing
end
else if (timer == 32'd99_999_999) //4 seconds count(50M*4-1=199999999)
begin
timer <= 32'd0; //count done,clearing the time counter
o_cnt = o_cnt + 4'd1;
end
else
timer <= timer + 32'd1; //timer counter = timer counter + 1
end
// LED control
always@(posedge clk or negedge rst_n)
begin
if (rst_n == 1'b0)
led <= 4'b0000; //when the reset signal active
else if (timer == 32'd12_499_999) //time counter count to 1st sec,LED1 lighten
led <= 4'b0001;
else if (timer == 32'd24_999_999) //time counter count to 2nd sec,LED2 lighten
led <= 4'b0010;
else if (timer == 32'd37_499_999) //time counter count to 3rd sec,LED3 lighten
led <= 4'b0100;
else if (timer == 32'd49_999_999) //time counter count to 4th sec,LED4 lighten
led <= 4'b1000;
else if (timer == 32'd62_499_999)
led = o_cnt;
// else if (timer == 32'd74_999_999)
// led <= o_cnt;
// else if (timer == 32'd87_499_999)
// led <= o_cnt;
// else if (timer == 32'd99_999_999)
// led <= o_cnt;
end
endmodule
作业2:
在第一次作业的基础上,增加按键功能:
功能按键1——功能按键1按下后,暂停计数器计数,4盏LED持续循环点亮;当再次按下功能按键1后,计数器恢复计数功能。
复位按键2——复位按键2按下后,计数器将复位;
我感觉难点在于按键的消抖上,下面代码按键消抖有问题,但又没想明白错在哪?有大佬路过指点一下!!
`timescale 1ns / 1ps
module led_test
(
input clk, // system clock 50Mhz on board
input rst_n, // reset ,low active
input [0:0] key,
output reg[3:0] led // LED,use for control the LED signal on board
);
reg [31:0] timer;
reg [3:0] count;
reg [0:0] flag;
reg [31:0] t1;
//reg [31:0] t2;
localparam delay_param = 32'd499_999;
wire delay_10ms =((timer - t1) >= delay_param)?1'b1:1'b0; //本意是通过按键操作前与按后的时间差达到10ms,但是这样是有问题的?
always@(posedge clk or negedge rst_n)
begin
if (rst_n == 1'b0)
timer <= 32'd0;
else if (timer == 32'd149_999_999)
timer <= 32'd0;
else if((timer == 32'd49_999_999) &&(flag== 1'd1))
timer <= 32'd0;
else
timer <= timer + 32'd1;
end
// LED control
always@(posedge clk or negedge rst_n)
begin
if (rst_n == 1'b0)
begin
led <= 4'b0000;
count <= 4'd0; flag <= 1'd0;
end
else if (key==1'd0)
begin //按键的部分
if(delay_10ms)
flag <= ~flag; //标志位翻转
end
else if (timer == 32'd0)
led <= 4'b0001;
else if (timer == 32'd12_499_999)
led <= 4'b0010;
else if (timer == 32'd24_999_999)
led <= 4'b0100;
else if (timer == 32'd37_499_999)
led <= 4'b1000;
else if (timer == 32'd49_999_999)
led <= 4'b0000;
else if ((timer == 32'd62_499_999)&& (flag == 0) )
begin
count <= count + 4'd1;
led = count;
end
else
t1 = timer; //这个地方注意一下
end
endmodule
参考了网上消抖后,没有问题的代码:
`timescale 1ns / 1ps
module led_test
(
input clk, // system clock 50Mhz on board
input rst_n, // reset ,low active
input [0:0] key,
output reg[3:0] led // LED,use for control the LED signal on board
);
//define the time counter
reg [31:0] timer;
reg [3:0] count;
reg [0:0] flag;
reg cnt_full;
reg [19:0] cnt;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt <= 20'd0;
else if(cnt == 20'd999_999)
cnt <= 20'd0;
else
cnt <= cnt + 1'b1;
end
//计数满信号
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt_full <= 1'b0;
else if(cnt == 20'd999_999)
cnt_full <= 1'b1;
else
cnt_full <= 1'b0;
end
reg [0:0] key_in_r;
reg [0:0] key_in_r_next;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
key_in_r_next <= 1'b1;
else if(cnt_full)
key_in_r_next <= key;
else
key_in_r_next <= key_in_r_next;
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
key_in_r <= 1'b1;
else
key_in_r <= key_in_r_next;
end
wire [0:0] key_out;
assign key_out = key_in_r & (~key_in_r_next);
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
flag <= 1'd0;
else if (key_out==1'd1)
flag <= ~flag;
end
/
always@(posedge clk or negedge rst_n)
begin
if (rst_n == 1'b0)
timer <= 32'd0;
else if (timer == 32'd149_999_999)
timer <= 32'd0;
else if((timer == 32'd49_999_999) &&(flag== 1'd1))
timer <= 32'd0;
else
timer <= timer + 32'd1;
end
// LED control
always@(posedge clk or negedge rst_n)
begin
if (rst_n == 1'b0)
begin
led <= 4'b0000;
count <= 4'd0;
end
else if (timer == 32'd0)
led <= 4'b0001;
else if (timer == 32'd12_499_999)
led <= 4'b0010;
else if (timer == 32'd24_999_999)
led <= 4'b0100;
else if (timer == 32'd37_499_999)
led <= 4'b1000;
else if (timer == 32'd49_999_999)
led <= 4'b0000;
else if ((timer == 32'd62_499_999)&& (flag == 0) )
begin
count <= count + 4'd1;
led = count;
end
end
endmodule