$$ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Self-defined math definitions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Math symbol commands \newcommand{\intd}{\,{\rm d}} % Symbol 'd' used in integration, such as 'dx' \newcommand{\diff}{{\rm d}} % Symbol 'd' used in differentiation ... $$

【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倍速)

 

 

 

 

 

posted @ 2023-03-20 09:18  素衣叹风尘  阅读(123)  评论(0)    收藏  举报