교통신호기

 

다시 FSM을 이용하여 RED, GREEN, YELLOW가 있는 신호등을 만들어 볼 것입니다. PED는 보행자가 요청하면 건널 수 있는 스위치를 설치한다는 가정입니다. 각각의 신호의 시간 계산을 따로하지 않고 하나의 함수를 이용하여 계산을 진행할 예정입니다.

 


my_signal

`timescale 1ns / 1ps

module my_signal(
    input RST,
    input CLK,
    input [6:0] time_slot,
    input start,
    output [6:0]        curr_slot,
    output done
    );
    
parameter CLK_FREQ = 125_000_000;
wire [29:0] MAX_CNT = time_slot + CLK_FREQ / 10;                        //make a time slot more useful at the each situation
reg [29:0] cnt;

always @(posedge CLK)
begin
        if(RST)
        cnt <= 30'd0;
        else if(start)
        cnt <= cnt + 1;
        else
        cnt <= 30'd0;
end

assign done = (cnt == MAX_CNT - 1);
assign curr_slot = (cnt/CLK_FREQ) + 10;


endmodule

traffic_cnt

`timescale 1ns / 1ps

module traffic_cnt(
    input RST,
    input CLK,
    input PED_SW,
    output reg RED,
    output reg GREEN,
    output reg YELLOW,
    output reg WORK
    );
parameter CLK_FREQ = 125_000_000;
localparam [1:0] sYEL = 2'd0,                   //state declare
                                sRED = 2'd1,
                                sGRN = 2'd2,
                                sPED = 2'd3;
reg [1:0] curr_state, next_state;
reg start_cnt;
wire cnt_done;
reg [6:0] time_slot;
wire [6:0] curr_slot;
reg [6:0] curr_time;
reg pd_sw_1d, pd_sw_2d;
wire pd_sw_rising;


always @(posedge CLK)                                   
begin
        if(RST)
                curr_state <= sYEL;
        else
                curr_state <= next_state;
end
always @ (RST, curr_state, cnt_done)
begin
        if(RST) begin
                next_state = sYEL;
                start_cnt = 1'b0;
                time_slot = 0;
                RED = 1'b0;
                GREEN = 1'b0;
                YELLOW = 1'b0;
                WORK = 1'b0;
        end else begin
                RED = 1'b0;
                GREEN = 1'b0;
                YELLOW = 1'b0;
                WORK = 1'b0;
        case (curr_state)
                sYEL : begin
                        start_cnt = 1'b1;
                        time_slot = 10;
                        if(cnt_done) begin
                                next_state = sRED;
                                start_cnt = 1'b1;
                        end else begin
                                next_state = sYEL;
                                start_cnt = 1'b1;
                        end
                        YELLOW = 1'b1;
                end
                sRED :  begin
                        time_slot = 7'd80;
                        if(cnt_done) begin
                                next_state = sGRN;
                                start_cnt = 1'b0;                       // start_cnt clear per 1 CLK
                        end else if(pd_sw_rising) begin
                                next_state = sPED;
                                start_cnt = 1'b0;
                        end else begin
                                start_cnt = 1'b1;
                                next_state = sRED;
                        end
                        RED = 1'b1;
                end
                sGRN :  begin
                        time_slot = 80;
                        if(cnt_done) begin
                                next_state = sYEL;
                                start_cnt = 1'b0;
                        end else begin
                                time_slot = 80;
                                start_cnt = 1'b1;
                                next_state = sGRN;
                        end
                        GREEN = 1'b1;
                        WORK = 1'b1;
                end
                sPED :  begin
                        if(curr_state < 20) begin
                                time_slot = 20;
                        end else begin
                                time_slot = 12;
                        end
                        if(cnt_done) begin
                                next_state = sGRN;
                                start_cnt = 1'b0;
                        end else begin
                                start_cnt = 1'b1;
                                next_state = sPED;
                        end
                        RED = 1'b1;
                end
                default : next_state = sYEL;
        endcase
        end
end 

my_signal #(.CLK_FREQ(CLK_FREQ))
        u0(
        .RST    (RST),
        .CLK    (CLK),
        .time_slot      (time_slot),
        .start  (start_cnt),
        .curr_slot      (curr_slot),
        .done   (cnt_done)
        );
always @ (posedge CLK)
begin
        pd_sw_1d <= PED_SW;
        pd_sw_2d <= pd_sw_1d;
end

assign pd_sw_rising = pd_sw_1d & ~pd_sw_2d;
always @ (posedge CLK)
begin
        if(curr_state == sYEL)
                curr_time<= 30'd0;
        else if (pd_sw_rising)
                curr_time <= curr_slot;
end

endmodule

Testbench


traffic_tb

`timescale 1ns / 1ps

module traffic_tb();

parameter CLK_PD = 10;
reg RST, CLK, PED_SW;
wire RED, GREEN, YELLOW, WORK;

traffic_cnt #(.CLK_FREQ(100))
        uut     (
        .RST    (RST),
        .CLK    (CLK),
        .PED_SW (PED_SW),
        .RED    (RED),
        .GREEN  (GREEN),
        .YELLOW (YELLOW),
        .WORK   (WORK)
        );
        
initial begin 
        RST = 1'b1;
        #(CLK_PD* 20);
        RST = 1'b0;
end

initial CLK = 1'b0;
always #(CLK_PD/2) CLK = ~CLK;

initial begin
        PED_SW = 1'b0;
        wait (RST == 1'b0);
        wait (RST == 1'b1);
        wait (RST == 1'b0);
        wait (RST == 1'b1);
        #(CLK_PD*12)
        PED_SW =1'b1;
        #(CLK_PD*3)
        PED_SW = 1'b0;
        wait (GREEN == 1'b1);
        wait (GREEN == 1'b0);
        wait (YELLOW == 1'b1);
        wait (YELLOW == 1'b0);
        $finish;
end

endmodule

Testbench Pulse


Schematic

traffic_cnt Schematic
u0(my_signal) Schematic
I/O Port

'Circuit Design > 🔥HDL' 카테고리의 다른 글

[Verilog] 9. RAM(Random Access Memory)  (0) 2024.05.27
[Verilog] 8. Uart  (0) 2024.05.27
[Verilog] 6.FSM Security  (0) 2024.04.29
[Verilog] 5. FSM Demo.  (1) 2024.04.26
[Verilog] 4. 1 Sec Counter- (Cora-z7)  (0) 2024.04.01