step fpga上实现呼吸灯和交通灯

it2022-05-05  75

呼吸灯

呼吸灯:我们将通过脉宽调制技术来实现“呼吸灯”,实现LED的亮度由最暗逐渐增加到最亮,再逐渐变暗的过程。 脉冲宽度调制。它是利用微控制器的数字输出调制实现,是对模拟电路进行控制的一种非常有效的技术,广泛应用于测量、通信、功率控制与变换等众多领域。 硬件设计 实现原理:如上图所示,脉冲信号的周期为T,高电平脉冲宽度为t,占空比为t/T。为了实现PWM脉宽调制,我们需要保持周期T不变,调整高电平脉宽t的时间,从而改变占空比。

当t = 0时,占空比为0%,因为我们的LED硬件为低电平点亮,所以为最亮的状态。 当t = T时,占空比为100%,LED灯为最暗(熄灭)的状态。 结合呼吸灯的原理,整个呼吸的周期为最亮→最暗→最亮的时间,即t的值的变化:0→T→0逐渐变化,这个时间应该为2s。 呼吸灯设计要求呼吸的周期为2s,也就是说LED灯从最亮的状态开始,第一秒时间内逐渐变暗,第二秒的时间内再逐渐变亮,依次进行。 本设计中需要两个计数器cnt1和cnt2,cnt1随系统时钟同步计数(系统时钟上升沿时cnt1自加1)范围为0-T,cnt2随cnt1的周期同步计数(cnt1等于T时,cnt2自加1)范围也是0-T,这样每次cnt1在0-T的计数时,cnt2为一个固定值,相邻cnt1计数周期对应的cnt2的值逐渐增大,我们将cnt1计数0~T的时间作为脉冲周期,cnt2的值作为脉冲宽度,则占空比 = cnt2/T,占空比从0%到100%的时间 = cnt2*cnt1 = T^2 = 1s = 12M个系统时钟,T = 2400,我们定义CNT_NUM = 2400作为两个计数器的计数最大值。 2.verilog程序设计

module breath_led(clk,rst,led); input clk; //系统时钟输入 input rst; //复位输出 output led; //led输出 reg [24:0] cnt1; //计数器1 reg [24:0] cnt2; //计数器2 reg flag; //呼吸灯变亮和变暗的标志位 parameter CNT_NUM = 2400; //计数器的最大值 period = (2400^2)*2 = 24000000 = 2s //产生计数器cnt1 always@(posedge clk or negedge rst) begin if(!rst) begin cnt1<=13'd0; end else if(cnt1>=CNT_NUM-1) cnt1<=1'b0; else cnt1<=cnt1+1'b1; end //产生计数器cnt2 always@(posedge clk or negedge rst) begin if(!rst) begin cnt2<=13'd0; flag<=1'b0; end else if(cnt1==CNT_NUM-1) begin //当计数器1计满时计数器2开始计数加一或减一 if(!flag) begin //当标志位为0时计数器2递增计数,表示呼吸灯效果由暗变亮 if(cnt2>=CNT_NUM-1) //计数器2计满时,表示亮度已最大,标志位变高,之后计数器2开始递减 flag<=1'b1; else cnt2<=cnt2+1'b1; end else begin if(cnt2<=0) //当标志位为高时计数器2递减计数 flag<=1'b0; //计数器2级到0,表示亮度已最小,标志位变低,之后计数器2开始递增 else cnt2<=cnt2-1'b1; end end else cnt2<=cnt2; //计数器1在计数过程中计数器2保持不变 end //比较计数器1和计数器2的值产生自动调整占空比输出的信号,输出到led产生呼吸灯效果 assign led = (cnt1<cnt2)?1'b0:1'b1; endmodule

交通灯

1.有限状态机 FSM:一种由寄存器组和组合逻辑构成硬件时序电路,堪称FPGA硬件设计的灵魂。 在同一时钟跳变沿由当前状态(现态)转移到下一状态(次态) 究竟转向哪一状态不但取决于各个输入值,还取决于当前状态。 在时钟跳变沿时刻进行复杂组合逻辑控制 包含时序、组合逻辑电路 非常有用模型,可以模拟大部分事物。如按键命令、自动门控制、通信时序等

1)状态总数state是有限的 2)任何一个时刻,只能处于一个状态 3)在条件满足时,由一个状态转变到另一个状态

分类:1)moore型:输出逻辑只由当前状态决定 下一个状态 = F(当前状态,输入信号); 输出信号 = G(当前状态); 2)mealy型:输出逻辑不但与当前状态有关还与当前输入值有关 下一个状态 = F(当前状态,输入信号); 输出信号 = G(当前状态,输入信号); 有限状态机要素 状态:当前状态、次态 输入:触发状态转移的输入条件 输出:输入所触发的动作

有限状态机的样式 一段式 整个状态机在一个always模块中,模块中既包含状态转移也含有组合逻辑输入输出。 二段式 状态机使用两个always描述,一个采用同步时序实现状态转移,一个采用组合逻辑判断转移条件和逻辑输出。需要定义两个状态——现态和次态 三段式 状态机使用三个always描述,一个采用同步时序实现状态转移,一个采用组合逻辑判断转移条件,一个实现状态同步输出 2.交通灯的设计 设计流程: 上图为十字路口交通示意图分之路与主路,要求如下: * 交通灯主路上绿灯持续15s的时间,黄灯3s的时间,红灯10s的时间; * 交通灯支路上绿灯持续7s的时间, 黄灯持续3秒的时间,红灯18秒的时间; 根据上述要求,状态机设计框架分析如下: * S1:主路绿灯点亮,支路红灯点亮,持续15s的时间; * S2:主路黄灯点亮,支路红灯点亮,持续3s的时间; * S3:主路红灯点亮,支路绿灯点亮,持续10s的时间; * S4:主路红灯点亮,支路黄灯点亮,持续3s的时间; 程序设计 时钟分频:

module divide ( //INPUT clk , rst_n , //OUTPUT clkout ); //******************* //DEFINE PARAMETER //******************* parameter WIDTH = 3; parameter N = 5; //******************* //DEFINE INPUT //******************* input clk,rst_n; //******************* //DEFINE OUTPUT //******************* output clkout; //******************** //OUTPUT ATTRIBUTE //******************** //REGS reg [WIDTH-1:0] cnt_p,cnt_n; reg clk_p,clk_n; assign clkout = (N==1)?clk:(N[0])?(clk_p&clk_n):clk_p; //Sequential logic style always @ (posedge clk) begin if(!rst_n) cnt_p<=0; else if (cnt_p==(N-1)) cnt_p<=0; else cnt_p<=cnt_p+1; end always @ (negedge clk) begin if(!rst_n) cnt_n<=0; else if (cnt_n==(N-1)) cnt_n<=0; else cnt_n<=cnt_n+1; end always @ (posedge clk) begin if(!rst_n) clk_p<=0; else if (cnt_p<(N>>1)) clk_p<=0; else clk_p<=1; end always @ (negedge clk) begin if(!rst_n) clk_n<=0; else if (cnt_n<(N>>1)) clk_n<=0; else clk_n<=1; end endmodule

交通灯通过利用有限状态机的三段式模型的程序设计:

module traffic ( clk , //时钟 rst_n , //复位 out //三色led代表交通灯 ); input clk,rst_n; output reg[5:0] out; parameter S1 = 4'b00, //状态机状态编码 S2 = 4'b01, S3 = 4'b10, S4 = 4'b11; parameter time_s1 = 4'd15, //计时参数 time_s2 = 4'd3, time_s3 = 4'd10, time_s4 = 4'd3; //交通灯的控制 parameter led_s1 = 6'b101011, // LED2 绿色 LED1 红色 led_s2 = 6'b110011, // LED2 蓝色 LED1 红色 led_s3 = 6'b011101, // LED2 红色 LED1 绿色 led_s4 = 6'b011110; // LED2 红色 LED1 蓝色 reg [3:0] timecont; reg [1:0] cur_state,next_state; //现态、次态 wire clk1h; //1Hz时钟 //产生1秒的时钟周期 divide #(.WIDTH(32),.N(12000000)) CLK1H ( .clk(clk), .rst_n(rst_n), .clkout(clk1h)); //第一段 同步逻辑 描述次态到现态的转移 always @ (posedge clk1h or negedge rst_n) begin if(!rst_n) cur_state <= S1; else cur_state <= next_state; end //第二段 组合逻辑描述状态转移的判断 always @ (cur_state or rst_n or timecont) begin if(!rst_n) begin next_state = S1; end else begin case(cur_state) S1:begin if(timecont==1) next_state = S2; else next_state = S1; end S2:begin if(timecont==1) next_state = S3; else next_state = S2; end S3:begin if(timecont==1) next_state = S4; else next_state = S3; end S4:begin if(timecont==1) next_state = S1; else next_state = S4; end default: next_state = S1; endcase end end //第三段 同步逻辑 描述次态的输出动作 always @ (posedge clk1h or negedge rst_n) begin if(!rst_n==1) begin out <= led_s1; timecont <= time_s1; end else begin case(next_state) S1:begin out <= led_s1; if(timecont == 1) timecont <= time_s1; else timecont <= timecont - 1; end S2:begin out <= led_s2; if(timecont == 1) timecont <= time_s2; else timecont <= timecont - 1; end S3:begin out <= led_s3; if(timecont == 1) timecont <= time_s3; else timecont <= timecont - 1; end S4:begin out <= led_s4; if(timecont == 1) timecont <= time_s4; else timecont <= timecont - 1; end default:begin out <= led_s1; end endcase end end endmodule

最新回复(0)