Verilog/CPLD代码之按键控制流水灯

实验现象:按键控制流水灯启停与移动方向,sw1_n控制流水灯启停,

     sw2_n控制流水灯左移,sw3_n控制流水灯右移,间隔1s

module Key_to_LED_verilog(
clk,rst_n,sw1_n,sw2_n,sw3_n,
led
);
input clk; //50MHZ时钟
input rst_n; //复位
input sw1_n,sw2_n,sw3_n; //按键,sw1_n启停,sw2_n左移,sw3_n右移
output[7:0] led; //LED 0-亮,1-灭

reg led_dir; //1--left, 0--right
reg led_on;  //1--on, 0--off

//////////////////////////////
//LED移位控制程序
reg [25:0]cnt; //计数寄存器
always @(posedge clk or negedge rst_n)
begin
if(!rst_n) cnt <= 26'd0;
else if(cnt == 26'd50000000) cnt <= 26'd0; //如果计数值达到50M(1s),计数归零
else cnt <= cnt + 1'b1;                    //计数值不到50M,自动加1
end

reg [7:0]led_r;//8位LED状态寄存器
always @(posedge clk or negedge rst_n)
begin
if(!rst_n) led_r <= 8'b11111110; //复位初值
else if(cnt == 26'd50000000 && led_on) //如果计数值达到50M(1s)且led_on=1,允许移位
begin
if(led_dir)led_r <= {led_r[0],led[7:1]}; //LED状态寄存器移位
else led_r <= {led_r[6:0],led[7]}; //LED状态寄存器移位
end
end

assign led = led_r;

///////////////////////////////
//3位按键程序
reg[19:0]  cntkey; //计数寄存器

always @ (posedge clk  or negedge rst_n)
    if (!rst_n) cntkey <= 20'd0; //异步复位
    else cntkey <= cntkey + 1'b1;
  
reg [2:0]low_sw;

always @(posedge clk  or negedge rst_n)
    if (!rst_n) low_sw <= 3'b111;
    else if (cntkey == 20'hfffff) //满20ms,将按键值锁存到寄存器low_sw中cnt == 20'hfffff
      low_sw <= {sw3_n,sw2_n,sw1_n};

reg [2:0]low_sw_r;       //每个时钟周期的上升沿将low_sw信号锁存到low_sw_r中

always @ ( posedge clk  or negedge rst_n )
    if (!rst_n) low_sw_r <= 3'b111;
    else low_sw_r <= low_sw;
 
wire [2:0]led_ctrl = low_sw_r[2:0] & (~low_sw[2:0]);

//////////////////////////////////////

//判断键值与功能
always @(posedge clk  or negedge rst_n)
if (!rst_n)
begin 
led_on = 1'b0;
led_dir = 1'b0;
end
else 
begin
if(led_ctrl[0]) led_on <= ~led_on; 
if(led_ctrl[1]) led_dir <= 1'b1;
if(led_ctrl[2]) led_dir <= 1'b0;
end

endmodule



你可能感兴趣的:(Verilog/CPLD)