장영현
2023. 6. 30. 02:59
728x90
교통신호등 제어기 설계
timescale 1ns / 1ps
module TrafficLightController(
input clk, reset, standby, test,
output reg [6:0] FND,
output reg G1en, Y1en, R1en, G2en, Y2en, R2en
);
parameter YY=3'b000, RY=3'b001, GR=3'b010, YR=3'b011, RG=3'b100; // 상태에 대한 매개 변수 정의
reg [2:0] state=YY; // 현재 상태 레지스터
parameter RGTime=10, RYTime=3, GRTime=15, YRTime=3, TESTTime=2; // 각 상태의 지속 시간을 정의하기 위한 매개 변수 정의
integer TimeCnt, onTime; // 시간 카운트 및 상태 전환에 사용되는 정수 변수 정의
reg [6:0] G1=7'b0000000, Y1=7'b0000000, R1=7'b0000000; // 신호등 1의 각 색상 상태를 나타내는 레지스터
reg [6:0] G2=7'b0000000, Y2=7'b0000000, R2=7'b0000000; // 신호등 2의 각 색상 상태를 나타내는 레지스터
reg clk1hz, clk100hz; // 1Hz 및 100Hz 클럭 신호 정의
integer cnt1hz, cnt100hz; // 1Hz 및 100Hz 클럭 분주에 사용되는 카운터 정의
reg [3:0] clkcnt; // FND 출력을 위한 클럭 카운터
// 1Hz 및 100Hz 주기의 클럭 신호 생성
always @ (posedge clk) begin
if (cnt1hz >= 49_999_999) begin // 1Hz로 분주
cnt1hz <= 0;
clk1hz <= ~clk1hz;
end else
cnt1hz <= cnt1hz+1;
if (cnt100hz >= 499_999) begin // 100Hz로 분주
cnt100hz <= 0;
clk100hz <= ~clk100hz;
end else
cnt100hz <= cnt100hz+1;
end
// 상태 전환 및 출력 제어
always @ (posedge clk1hz or posedge standby) begin
if (standby) begin
// 대기 상태일 때 초기화
state <= YY; // 상태 초기화
TimeCnt <= 0; // 시간 카운터 초기화
end else begin
case(state)
YY: begin
state <= RY; // YY 상태에서 RY 상태로 전환
end
RY: begin
if (!test) onTime <= RYTime; // 일반 운영 모드일 때 RY 상태의 지속 시간 설정
else onTime <= TESTTime; // 테스트 모드일 때 RY 상태의 지속 시간 설정
TimeCnt <= TimeCnt + 1; // 시간 카운터 증가
if (TimeCnt == onTime) begin
state <= GR; // RY 상태에서 GR 상태로 전환
TimeCnt <= 0; // 시간 카운터 초기화
end
end
GR: begin
if (!test) onTime <= GRTime; // 일반 운영 모드일 때 GR 상태의 지속 시간 설정
else onTime <= TESTTime; // 테스트 모드일 때 GR 상태의 지속 시간 설정
TimeCnt <= TimeCnt + 1; // 시간 카운터 증가
if (TimeCnt == onTime) begin
state <= YR; // GR 상태에서 YR 상태로 전환
TimeCnt <= 0; // 시간 카운터 초기화
end
end
YR: begin
if (!test) onTime <= YRTime; // 일반 운영 모드일 때 YR 상태의 지속 시간 설정
else onTime <= TESTTime; // 테스트 모드일 때 YR 상태의 지속 시간 설정
TimeCnt <= TimeCnt + 1; // 시간 카운터 증가
if (TimeCnt == onTime) begin
state <= RG; // YR 상태에서 RG 상태로 전환
TimeCnt <= 0; // 시간 카운터 초기화
end
end
RG: begin
if (!test) onTime <= RGTime; // 일반 운영 모드일 때 RG 상태의 지속 시간 설정
else onTime <= TESTTime; // 테스트 모드일 때 RG 상태의 지속 시간 설정
TimeCnt <= TimeCnt + 1; // 시간 카운터 증가
if (TimeCnt == onTime) begin
state <= RY; // RG 상태에서 RY 상태로 전환
TimeCnt <= 0; // 시간 카운터 초기화
end
end
endcase
end
end
always @ (state) begin
case (state)
YY: begin
// YY 상태일 때의 출력 제어
R1 <= 7'b1111111; Y1 <= 7'b1000000; G1 <= 7'b1111111;
R2 <= 7'b1111111; Y2 <= 7'b1000000; G2 <= 7'b1111111;
end
RY: begin
// RY 상태일 때의 출력 제어
R1 <= 7'b1111111; Y1 <= 7'b1000000; G1 <= 7'b1111111;
R2 <= 7'b0001000; Y2 <= 7'b0111111; G2 <= 7'b1111111;
end
GR: begin
// GR 상태일 때의 출력 제어
R1 <= 7'b0001000; Y1 <= 7'b0111111; G1 <= 7'b1111111;
R2 <= 7'b1111111; Y2 <= 7'b0111111; G2 <= 7'b1000010;
end
YR: begin
// YR 상태일 때의 출력 제어
R1 <= 7'b0001000; Y1 <= 7'b0111111; G1 <= 7'b1111111;
R2 <= 7'b1111111; Y2 <= 7'b1000000; G2 <= 7'b1111111;
end
RG: begin
// RG 상태일 때의 출력 제어
R1 <= 7'b1111111; Y1 <= 7'b0111111; G1 <= 7'b1000010;
R2 <= 7'b0001000; Y2 <= 7'b0111111; G2 <= 7'b1111111;
end
default:; // 기본 상태인 경우 아무 작업도 수행하지 않음
endcase
end
// 신호등 상태에 따른 출력 제어
always @ (clkcnt or G1, Y1, R1, G2, Y2, R2) begin
if(clkcnt[0]) begin // clkcnt[0]이 1인 경우
G1en <= 1'b0; // G1 출력 비활성화
R1en <= 1'b1; // R1 출력 활성화
G2en <= 1'b1; // G2 출력 활성화
R2en <= 1'b1; // R2 출력 활성화
Y1en <= Y1[6]; // Y1 출력 활성화 비트 설정
Y2en <= Y2[6]; // Y2 출력 활성화 비트 설정
FND <= G1; // FND 출력 설정
end else if(clkcnt[1]) begin // clkcnt[1]이 1인 경우
G1en <= 1'b1; // G1 출력 활성화
R1en <= 1'b0; // R1 출력 비활성화
G2en <= 1'b1; // G2 출력 활성화
R2en <= 1'b1; // R2 출력 활성화
FND <= R1; // FND 출력 설정
end else if(clkcnt[2]) begin // clkcnt[2]이 1인 경우
G1en <= 1'b1; // G1 출력 활성화
R1en <= 1'b1; // R1 출력 활성화
G2en <= 1'b0; // G2 출력 비활성화
R2en <= 1'b1; // R2 출력 활성화
FND <= G2; // FND 출력 설정
end else if(clkcnt[3]) begin // clkcnt[3]이 1인 경우
G1en <= 1'b1; // G1 출력 활성화
R1en <= 1'b1; // R1 출력 활성화
G2en <= 1'b1; // G2 출력 활성화
R2en <= 1'b0; // R2 출력 비활성화
FND <= R2; // FND 출력 설정
end else begin
G1en <= 1'b1; // G1 출력 활성화
R1en <= 1'b1; // R1 출력 활성화
G2en <= 1'b1; // G2 출력 활성화
R2en <= 1'b1; // R2 출력 활성화
end
end
endmodule
## Clock signal
set_property -dict { PACKAGE_PIN W5 IOSTANDARD LVCMOS33 } [get_ports clk]
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports clk]
## Switches
set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports {standby}]
set_property -dict { PACKAGE_PIN R2 IOSTANDARD LVCMOS33 } [get_ports {reset}]
##7 Segment Display
set_property -dict { PACKAGE_PIN W7 IOSTANDARD LVCMOS33 } [get_ports {FND[0]}]
set_property -dict { PACKAGE_PIN W6 IOSTANDARD LVCMOS33 } [get_ports {FND[1]}]
set_property -dict { PACKAGE_PIN U8 IOSTANDARD LVCMOS33 } [get_ports {FND[2]}]
set_property -dict { PACKAGE_PIN V8 IOSTANDARD LVCMOS33 } [get_ports {FND[3]}]
set_property -dict { PACKAGE_PIN U5 IOSTANDARD LVCMOS33 } [get_ports {FND[4]}]
set_property -dict { PACKAGE_PIN V5 IOSTANDARD LVCMOS33 } [get_ports {FND[5]}]
set_property -dict { PACKAGE_PIN U7 IOSTANDARD LVCMOS33 } [get_ports {FND[6]}]
set_property -dict { PACKAGE_PIN U2 IOSTANDARD LVCMOS33 } [get_ports {G1en}]
set_property -dict { PACKAGE_PIN U4 IOSTANDARD LVCMOS33 } [get_ports {R1en}]
set_property -dict { PACKAGE_PIN V4 IOSTANDARD LVCMOS33 } [get_ports {G2en}]
set_property -dict { PACKAGE_PIN W4 IOSTANDARD LVCMOS33 } [get_ports {R2en}]
##Buttons
set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 } [get_ports test]
코드 해석
- 모듈 인터페이스:
- clk, reset, standby, test: 입력 신호로서, 각각 클럭 신호, 리셋 신호, 대기 신호, 테스트 신호.
- FND: 7비트 출력 신호로서, 세그먼트 디스플레이에 표시될 값을 표시.
- G1en, Y1en, R1en, G2en, Y2en, R2en: 출력 신호로서, 각각 G1, Y1, R1, G2, Y2, R2의 활성화 여부를 나타낸다.
- 내부 변수 및 상수:
- FND: 7비트 레지스터로서, 세그먼트 디스플레이에 표시될 값을 저장.
- G1en, Y1en, R1en, G2en, Y2en, R2en: 레지스터로서, 각각 G1, Y1, R1, G2, Y2, R2의 활성화 여부를 저장.
- state: 3비트 레지스터로서, 현재 상태를 나타낸다.
- TimeCnt, onTime: 정수형 변수로서, 상태 변화 및 출력 제어에 사용되는 시간 카운트를 관리.
- G1, Y1, R1, G2, Y2, R2: 7비트 레지스터로서, 각 신호등의 상태를 나타낸다.
- clk1hz, clk100hz: 1Hz, 100Hz 주기의 클럭 신호를 생성하기 위한 레지스터.
- cnt1hz, cnt100hz: 1Hz, 100Hz 클럭 카운트를 관리.
- clkcnt: 4비트 레지스터로서, 상태별 클럭 카운트를 관리.
- 모듈 동작:
- 모듈은 주어진 클럭 신호 및 입력 신호에 따라 상태를 변경하고, 각 상태에 따른 출력을 제어한다.
- clk1hz 및 clk100hz 레지스터는 주어진 클럭 신호에 따라 1Hz 및 100Hz 주기의 클럭 신호를 생성한다.
- state 레지스터는 현재 상태를 나타내며, TimeCnt 변수는 각 상태에서의 시간 카운트를 관리한다.
- 입력 신호 standby에 따라 동작이 초기화되거나 대기 상태로 들어간다.
- 주어진 상태에 따라 각 신호등의 상태와 출력 신호를 설정한다.
- clkcnt 레지스터는 clk100hz 신호를 기반으로 클럭 카운트를 관리하며, 각 클럭 카운트에 따라 출력을 제어한다.