반응형
  • 숨쉬는 공부방
    • Security
      • SHA
    • Hardware Security
    • Verilog HDL
    • ─── ✿ ───
      • IT
      • 이것저것

블로그 메뉴

  • 홈
  • 모든 글
  • 방명록

인기 글

최근 글

태그

  • SHA-256
  • 조합회로
  • C코드
  • Modelsim
  • Verilog
  • FSM
  • KISA
  • SHA256
  • 설계
  • 순차회로

hELLO · Designed By 정상우.
숨.

후하후하

[순차회로] 교통 신호 제어기 설계하기
Verilog HDL

[순차회로] 교통 신호 제어기 설계하기

2021. 8. 24. 12:21

사거리인 주요도로와 간선도로의 교차로에서 교통을 위한 제어기를 설계해보기로 한다.

순차회로에 대하여 알고 싶다면 다음 글을 참고하길 바란다!👇

 

순차회로와 FSM

순차 회로(Sequential logic Circuit)를 설계하기 전에 순차 회로에 대하여 간단히 알아보도록 하겠다. 순차 논리 회로란? - 순서(상태)를 가지고 있는 회로 - FSM으로 순서를 만들고 그에 따라 출력하는

s00m.tistory.com

 


교통 신호 제어기

교차로

다음과 같은 명제를 고려해야 한다.

  • 주요도로(Main Highway)는 차가 끊임없이 다니기 때문에 주요도로의 신호등은 가장 높은 우선순위를 가진다. 그러므로 주요도로의 신호는 기본적으로 녹색이다.
  • 간선도로(Counrty Road)에서는 때때로 차가 교차로를 지나간다. 이때 간선도로의 신호등은 녹색으로 바뀐다.
  • 간선도로에 차가 없으면, 간선도로의 신호등은 노란색으로 바뀌고 다시 빨간색으로 바뀌어야 한다. 주요도로의 신호등은 다시 녹색으로 바뀐다.
  • 간선도로에 차가 있는지 감지하는 센서가 있다. 센서는 제어기의 입력으로 신호 X를 보낸다. 간선도로에 차가 있으면 X=1, 없으면 X=0이다.

 

위의 명제를 가지고 FSM을 만든다.

- 입력(X)

  • 간선도로에 차가 있는가?
    → 있으면 X = 1, 없으면 X = 0

- 출력

  • 3가지 상태(녹색, 노란색, 빨간색)의 신호에 대한 2비트 출력
  • hwy, cntry 각각의 출력 신호에 대한 레지스터

- 초기화

  • 주요도로는 초록불, 간선도로는 빨간불인 상태

- 상태

  • 기본 상태: 주요도로가 초록불, 간선도로가 빨간불 (S0)
  • 간선도로에 차가 있을 때: 주요도로가 노란불로 바뀌고 다시 빨간불으로 바뀐다. (S1)
                                             주요도로가 빨간불일 때 간선도로는 초록불로 바뀐다. (S2)
  • 간선도로에 차가 없을 때: 간선도로가 노란불로 바뀌고 다시 빨간불으로 바뀐다. (S3)
                                            간선도로가 빨간불일 때 주요도로는 초록불로 바뀐다. (S4)

 

 

 

FSM을 만들면 다음과 같은 형태를 띠게 된다.

S0 → S1과 다르게 S1 → S2로 진행될 때는 조건이 없으므로 그냥(?) 진행하면 된다.

교통 신호 제어기에 대한 FSM

 


교통 신호 제어기를 Verilog 코드로 설계하기 위해 녹색, 노란색, 빨간색을 2비트 신호로 표현해야 한다.

각각의 신호를 다음과 같이 지정했다.

Red = 2'b00

Green = 2'b01

Yellow = 2'b10

 

※ 상태에 따른 신호등의 색깔을 이진수로 표현한 표

  MAIN_SIG CNTRY_SIG
S0 01 (G) 00 (R)
S1 10 (Y) 00 (R)
S2 00 (R) 00 (R)
S3 00 (R) 01 (G)
S4 00 (R) 10 (Y)

 


* RTL

`define TURE 1'b1
`define FALSE 1'b0

module sig_control(hwy, cntry, X, clock, clear);
	input X;	// cntry에 차가 있을 경우 1, cntry에 차가 없을 경우 0
	input clock;
	input clear;

	output [1:0] hwy;
	output [1:0] cntry;

	reg 	[1:0] hwy;
	reg 	[1:0] cntry;
	
	parameter RED = 2'b00;
	parameter GREEN = 2'b01;
	parameter YELLOW = 2'b10;

	parameter S0 = 3'b000;
	parameter S1 = 3'b001;
	parameter S2 = 3'b010;
	parameter S3 = 3'b011;
	parameter S4 = 3'b100;

	reg 	[2:0] state;

	// main fsm
	always @(posedge clock) begin
		if (clear == 1'b1)
			state <= S0;
		else
			case (state)
				S0 : 	state <= (X) ? S1 : S0;
				S1 : 	state <= S2;
				S2 : 	state <= S3;
				S3 : 	state <= (X) ? S3 : S4;
				S4 : 	state <= S0;
				default : state <= S0;
			endcase
	end

	// hwy output
	always @(*) begin
		case (state)
			S0 : 	hwy = GREEN;  	// 2'b01;
			S1 : 	hwy = YELLOW; 	// 2'b10;
			S2 : 	hwy = RED; 	// 2'b00;
			S3 : 	hwy = RED; 	// 2'b00;
			S4 : 	hwy = RED; 	// 2'b00;
			default : hwy = GREEN;  // 2'b01;
		endcase
	end

	// cntry output
	always @(*) begin
		case (state)
			S0 : 	cntry = RED; 	// 2'b00;
			S1 : 	cntry = RED; 	// 2'b00;
			S2 : 	cntry = RED; 	// 2'b00;
			S3 : 	cntry = GREEN; 	// 2'b01;
			S4 : 	cntry = YELLOW; // 2'b10;
			default : cntry = RED;	// 2'b00;
		endcase
	end

endmodule

※ testbench에서만 forever, repeat를 쓰는 것을 권하기 때문에 RTL에서는 forever, repeat를 쓰지 않는다.

 

 

* TestBench

`timescale 1ns/1ps
`define TRUE 	1'b1
`define FALSE 	1'b0

// 차가 간선도로에 도착했을 때 교통 신호가 올바르게 작동하는 지 검사
module tb_sig_control;
	wire 	[1:0] 	MAIN_SIG, CNTRY_SIG;
	reg		CAR_ON_CNTRY_RD;	// 참이면 간선도로에 차가 있음
	reg		CLOCK, CLEAR;

	// 신호 제어기 파생
	sig_control SC(MAIN_SIG, CNTRY_SIG, CAR_ON_CNTRY_RD, CLOCK, CLEAR);

	// 모니터 구성
	initial
		$monitor($time, " Main Sig = %b Country Sig = %b Car_on_cntry = %d",
				MAIN_SIG, CNTRY_SIG, CAR_ON_CNTRY_RD);

	// 클럭의 구성
	initial
	begin
		CLOCK = `FALSE;
		forever #5 CLOCK = ~CLOCK;
	end

	// 클럭의 구성2
/*	initial begin
		CLOCK = `FALSE;
	end

	always #5 CLOCK = ~CLOCK;  */

	// clear 신호의 제어
	initial
	begin
		CLEAR = `TRUE;
		repeat(5) @(negedge CLOCK); // #(50);
		CLEAR = `FALSE;
	end

	// 스티뮬러스 적용
	initial
	begin
		CAR_ON_CNTRY_RD = `FALSE;	// 1'b0

		repeat(20) @(negedge CLOCK); // #(200); 
		CAR_ON_CNTRY_RD = `TRUE;
		repeat(10) @(negedge CLOCK); // #(100); 
		CAR_ON_CNTRY_RD = `FALSE;

		repeat(20) @(negedge CLOCK); // #(200); 
		CAR_ON_CNTRY_RD = `TRUE;
		repeat(10) @(negedge CLOCK); // #(100); 
		CAR_ON_CNTRY_RD = `FALSE;

		repeat(10) @(negedge CLOCK); // #(100); 
		$stop;
	end

endmodule
repeat(20) @(negedge CLOCK);

CLOCK의 하향 엣지(negedge)를 20번 반복하라! 라는 의미이다.

 

    forever #5 CLOCK = ~CLOCK; 는

CLOCK 신호가 5ns마다 0과 1을 반복한다는 코드로, CLOCK의 주기가 10ns라는 것을 알 수 있다.

즉, 하향 엣지를 한 번 반복하면 10ns가 경과한다.

그러므로 하향 엣지를 20번 반복하면 200ns가 경과한다.

 

 


출력 결과

wave
$monitor 화면과 FSM

   0ns : X

   5ns : CLR -> S0

200ns : X=1

205ns :  S1

215ns : S2

225ns : S3

300ns : X=0

305ns : S4

315ns : S0

500ns : X=1

... 반복

 

 


- 참고 -

Verilog HDL 디지털 설계와 합성의 길잡이 (한국어판)

https://disasmain.tistory.com/84

 

'Verilog HDL' 카테고리의 다른 글

[ModelSim] 프로그램 내의 필요한 창이 없어졌을 때 해결법  (0) 2021.09.29
순차회로와 FSM  (0) 2021.08.23
[조합회로] 4비트 전가산기 설계하기  (0) 2021.07.28
[조합회로] 4:1 멀티플렉서 설계하기  (0) 2021.07.28
[ModelSim] Verilog 조합회로 설계 방법  (0) 2021.07.28
    'Verilog HDL' 카테고리의 다른 글
    • [ModelSim] 프로그램 내의 필요한 창이 없어졌을 때 해결법
    • 순차회로와 FSM
    • [조합회로] 4비트 전가산기 설계하기
    • [조합회로] 4:1 멀티플렉서 설계하기
    숨.
    숨.

    티스토리툴바