【FPGA学习】- FPGA实验篇(进阶的LED灯)
交通灯设计
此次LED灯的设计将会在状态机一节中的经典摩尔型状态机-交通灯 的基础上,进行设计。
设计的基本功能:交通灯按照“红->绿->黄->红”的顺序依次交替运行。其中红灯亮10秒,绿灯亮8秒,黄灯亮4秒。该交通灯设计状态转移图及端口描述表如下。


由于设计过程中,时间单位是以秒计算,所以首先产生一个每秒的时钟信号,之后所有的周期都在每秒的基础之上进行判断。
设计代码。
module traffic_light(sys_clk, rst_n, led); input sys_clk; //system clock-50MHZ input rst_n; //reset signal, low-effective output reg [2:0] led; //led[2]-red, led[1]-green, led[0]-yellow //define reg reg clk_1HZ; //second signal reg [31:0] time_cnt; //clock cycle count reg [3:0] second_cnt, state_time; reg [1:0] current_state, next_state; //define parameter parameter red_state = 2'b00, green_state = 2'b01, yellow_state = 2'b10, red_time = 4'd10, green_time = 4'd8, yellow_time = 4'd4; //generate clk_1HZ, high_effective always @(posedge sys_clk, negedge rst_n) begin if(!rst_n) begin clk_1HZ <= 1'b0; time_cnt <= 32'd0; end else if(time_cnt >= 32'd49_999_999) begin clk_1HZ <= 1'b1; time_cnt <= 32'd0; end else begin clk_1HZ <= 1'b0; time_cnt <= time_cnt + 1; end end //state transfer always @(posedge clk_1HZ, negedge rst_n) begin if(!rst_n) current_state <= red_state; else current_state <= next_state; end //define next state always @(*) begin case(current_state) red_state:begin state_time = red_time; if(second_cnt == state_time) next_state = green_state; else next_state = current_state; end green_state:begin state_time = green_time; if(second_cnt == state_time) next_state = yellow_state; else next_state = current_state; end yellow_state:begin state_time = yellow_time; if(second_cnt == state_time) next_state = red_state; else next_state = current_state; end default: begin next_state = red_state; end endcase end //define output-led always @(posedge clk_1HZ, negedge rst_n) begin if(!rst_n) led <= 3'b011; else begin case(current_state) red_state: led <= 3'b011; green_state: led <= 3'b101; yellow_state: led <= 3'b110; default: led <= 3'b011; endcase end end //second count always @(posedge clk_1HZ, negedge rst_n) begin if(!rst_n) second_cnt <= 4'd0; else if(second_cnt == state_time) second_cnt <= 4'd0; else second_cnt <= second_cnt + 1; end //ila_0 ila_inst ( // .clk(sys_clk), // input wire clk // .probe0(clk_1HZ), // input wire [0:0] probe0 // .probe1(led) // input wire [2:0] probe1 // ); endmodule
约束代码。
set_property PACKAGE_PIN N15 [get_ports rst_n] set_property IOSTANDARD LVCMOS33 [get_ports rst_n] set_property IOSTANDARD LVCMOS33 [get_ports {led[0]}] set_property IOSTANDARD LVCMOS33 [get_ports {led[1]}] set_property IOSTANDARD LVCMOS33 [get_ports {led[2]}] set_property PACKAGE_PIN M14 [get_ports {led[2]}] set_property PACKAGE_PIN M15 [get_ports {led[1]}] set_property PACKAGE_PIN K16 [get_ports {led[0]}] create_clock -period 20.000 -name clk -waveform {0.000 10.000} [get_ports clk] set_property IOSTANDARD LVCMOS33 [get_ports sys_clk] set_property PACKAGE_PIN U18 [get_ports sys_clk]
testbench。(由于设计中49999999个时钟周期之后,clk_1HZ才翻转一次,所以测试时,可以将设计代码中“generate clk_1HZ, high_effective”中的 32'd49_999_999 调小,以便测试,观察波形图)
module traffic_light_testbench; reg sys_clk; reg rst_n; wire [2:0]led; traffic_light t1(sys_clk, rst_n, led); initial sys_clk = 1'b0; always #1 sys_clk = ~sys_clk; initial begin rst_n = 0; #1 rst_n = 1; #100000; #100 $stop; end endmodule
仿真波形。(将设计代码中的 32'd49_999_999 调小为 32’d5) 我们可以看到每5个时钟周期,信号clk_1HZ就会产生一个上升沿。并且输出也在按照按照“红->绿->黄->红”的顺序依次交替运行。


板上验证。(将设计代码中的 32'd49_999_999 恢复,视频已4倍速)


浙公网安备 33010602011771号