= CU_state;
end
end
WRITE_DATA_3 : begin
if ( iHREADY ) begin
CU_state <= READ_DATA_RO;
end else begin
CU_state <= CU_state;
end
end
default: CU_state <= CONFIG_0;
endcase
end
end
4.2 LED控制方法
LED灯的亮灭改变,是通过配置GPIO内的寄存器实现的,
具体来说,是借助总线信号HWDATA对GPIO的reg_DATA[7:4]寄存器进行配置,
在绪论章节中,我们介绍过LED_mode的编码方式:
// LED_mode Parameters
parameter MODE0 = 4'b0001,
parameter MODE1 = 4'b0010,
parameter MODE2 = 4'b0100,
parameter MODE3 = 4'b1000,
LED_mode采用了One-hot编码,这是为了对HWDATA进行assign赋值的时候,判断条件写起来简便一些,
现在我们就可以设计出各种流水灯模式下的组合逻辑了,
各模式下的LED亮灭随时间改变是通过计时器辅助的,
也就是下面代码中的timer,timer是一个32位寄存器:
reg [31:0] timer ;
always @ (posedge iHCLK or negedge iHRESETn) begin
if ( !iHRESETn )
timer <= 32'd0; // when the reset signal valid,time counter clearing
else if (timer == 32'd199_999_999) // 4 seconds count(50M*4-1=199999999)
timer <= 32'd0; // count done,clearing the time counter
else
timer <= timer + 1'b1; // timer counter = timer counter + 1
end
本质是将每一秒分成了50M帧(系统工作时钟频率为50MHz),
我们用assign语句给不同的帧下的HWDATA赋不同的值就行了,
首先是普通流水灯模式(工作模式0):
(注意,下面的LED[3:0]在WRITE_DATA_0~3状态下将会作为HWDATA[7:4]对GPIO_DATA寄存器进行配置)
assign LED[3:0] =
// mode0 普通流水灯模式
( led_mode[0] && timer >= 32'd149_999_999 ) ? 4'b0111 : // LED4亮
( led_mode[0] && timer >= 32'd99_999_999 ) ? 4'b1011 : // LED3亮
( led_mode[0] && timer >= 32'd49_999_999 ) ? 4'b1101 : // LED2亮
( led_mode[0] ) ? 4'b1110 : // LED1亮
....(其他模式)
这里就体现出One-hot编码的好处了,可以用( led_mode[0] )作为是否处于模式0的判定,
否则需要写成( led_mode == MODE_0 ),
接下来是加速流水灯模式(工作模式1):
assign LED[3:0] =
// mode1 加速流水灯模式
( led_mode[1] && timer >= 32'd174_999_999 ) ? 4'b0111 : // LED4亮
( led_mode[1] && timer >= 32'd149_999_999 ) ? 4'b1011 : // LED3亮
( led_mode[1] && timer >= 32'd124_999_999 ) ? 4'b1101 : // LED2亮
( led_mode[1] && timer >= 32'd99_999_999 ) ? 4'b1110 : // LED1亮
( led_mode[1] && timer >= 32'd74_999_999 ) ? 4'b0111 : // LED4亮
( led_mode[1] && timer >= 32'd49_999_999 ) ? 4'b1011 : // LED3亮
( led_mode[1] && timer >= 32'd24_999_999 ) ? 4'b1101 : // LED2亮
( led_mode[1] ) ? 4'b1110 : // LED1亮
....(其他模式)
心跳模式(工作模式2):
assign LED[3:0] =
// mode2 心跳模式
( led_mode[2] && timer >= 32'd189_999_999 ) ? 4'b0000 : // 全亮
( led_mode[2] && timer >= 32'd179_999_999 ) ? 4'b1111 : // 全灭
( led_mode[2] && timer >= 32'd169_999_999 ) ? 4'b0000 : // 全亮
( led_mode[2] ) ? 4'b1111 : // 全灭
....(其他模式)
最后是呼吸灯模式(工作模式3),
该模式相对复杂一些,前面提到过是通过改变占空比控制LED灯亮度的,
占空比的改变是通过对timer的判断实现的,
举个例子:
assign LED[3:0] =
// 占空比 1/4 = 25%
( led_mode[3] && (timer >= 32'd89_999_999 ) && (timer[1:0] == 2'b00 ) ) ? 4'b0000 :
( led_mode[3] && (timer >= 32'd89_999_999 ) ) ? 4'b1111 :
....(其他模式)
(timer[1:0] == 2'b00 )的判定,在timer的值每增加4的过程中,必定出现且只出现1次,
这样在 (timer >= 32'd89_999_999 )的这段期间内,
LED灯的驱动引脚就会在25%的时间里处于低电平(点亮),剩下的75%时间里处于高电平(熄灭),
同理,(timer[2:0] == 3'b0 )就能得到1/8的占空比,也就是12.5%,
这样就有:
assign LED[3:0] =
// mode3 呼吸灯模式
// 占空比 0%
( led_mode[3] && (timer >= 32'd189_999_999) ) ? 4'b1111 :
// 占空比 1/64 = 1.56%
( led_mode[3] && (timer >= 32'd169_999_999) && (timer[5:0] == 6'b000) ) ? 4'b0000 :
( led_mode[3] && (timer >= 32'd169_999_999) ) ? 4'b1111 :
// 占空比 1/32 = 3.12%
( led_mode[3] && (timer >= 32'd149_999_999) && (timer[4:0] == 5'b000) ) ? 4'b0000 :
( led_mode[3]