完整代码:
module johnson(
clk,
rst_n,
led,
sw1_n,
sw2_n,
sw3_n
);
input clk; //时钟信号,50MHz
input rst_n; //复位信号,低电平有效
output[3:0] led; //LED控制,1--灭,0--亮
input sw1_n,sw2_n,sw3_n; //三个独立按键,低表示按下
reg led_dir; //1'b1--left,1'b0--right
reg led_on; //1'b1--on,1'b0--off
//------------------------------------
reg[23:0] cnt24;
always @(posedge clk or negedge rst_n)
if(!rst_n) cnt24 <= 24'd0;
else cnt24 <= cnt24+1'b1;
//------------------------------------
reg[3:0] led_r;
always @(posedge clk or negedge rst_n)
if(!rst_n) led_r <= 4'b0001;
else if(cnt24 == 24'hffffff && led_on) begin
if(led_dir) led_r <= {led_r[0],led_r[3:1]}; //left
else led_r <= {led_r[2:0],led_r[3]}; //right
end
assign led = led_r;
//------------------------------------
//---------------------------------------------------------------------------
reg[2:0] key_rst;
always @(posedge clk or negedge rst_n)
if (!rst_n) key_rst <= 3'b111;
else key_rst <= {sw3_n,sw2_n,sw1_n};
reg[2:0] key_rst_r; //每个时钟周期的上升沿将low_sw信号锁存到low_sw_r中
always @ ( posedge clk or negedge rst_n )
if (!rst_n) key_rst_r <= 3'b111;
else key_rst_r <= key_rst;
//当寄存器key_rst由1变为0时,led_an的值变为高,维持一个时钟周期
wire[2:0] key_an = key_rst_r & (~key_rst);
/*
key_rst 1 1 1 0 0 1
~key_rst 0 0 0 1 1 0
key_rst_n 1 1 1 0 0 1
key_an 0 0 1 0 0
*/
//---------------------------------------------------------------------------
reg[19:0] cnt; //计数寄存器
always @ (posedge clk or negedge rst_n)
if (!rst_n) cnt <= 20'd0; //异步复位
else if(key_an) cnt <=20'd0;
else cnt <= cnt + 1'b1;
reg[2:0] low_sw;
always @(posedge clk or negedge rst_n)
if (!rst_n) low_sw <= 3'b111;
else if (cnt == 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;
/* clk clk clk clk clk clk
low_sw 111 111 111 110 110 110
~low_sw 000 000 000 001 001 001
low_sw_r 111 111 111 110 110 110
led_ctrl 000 000 000 001 000 000
*/
//当寄存器low_sw由1变为0时,led_ctrl的值变为高,维持一个时钟周期
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 //某个按键值变化时,LED将做亮灭翻转
if ( led_ctrl[0] ) led_on <= ~led_on;
if ( led_ctrl[1] ) led_dir <= 1'b0;
if ( led_ctrl[2] ) led_dir <= 1'b1;
end
endmodule
让代码开口说话!