교통신호기
다시 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
Schematic
'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 |