하만(Harman) 세미콘 반도체 설계 과정/Verilog를 이용한 RTL 시스템 반도체 설계

하만(Harman) 세미콘 아카데미 37일차 - Verilog HDL 설계(FSM security, 신호등 FSM)

semicon_circuitdesigner 2024. 4. 29. 11:34

[2024.04.29.월] 인천인력개발원 하만 세미콘 아카데미


Verilog를 이용한 RTL 시스템 반도체 설계


FSM_SECURITY


 

1.36일차의 my_fsm_secure 프로젝트를 열고 Design Sources로 my_fsm_secure_top 추가

 

2. my_seg.v파일을 Design Sources로 추가 후 포트 정의

 

3. my_secure_top.v 코드 작성

`timescale 1ns / 1ps

module my_fsm_secure_top(
    input RST,
    input CLK,
    input [1:0] KEY,
    input SENSOR,
    output ALARM_SIREN,
    output CA,
    output [6:0] AN
    );
    
wire [1:0] fsm_state;

my_fsm_secure u0 (.RST (RST), .CLK (CLK), .KEY (KEY), .SENSOR (SENSOR),
                .ALARM_SIREN (ALARM_SIREN), .FSM_STATE (fsm_state));
my_seg u1(.SW (fsm_state), .CA (CA), .AN(AN));

endmodule

 

4. my_seg.v 코드 작성

`timescale 1ns / 1ps

module my_seg(
    input [1:0] SW,
    output CA,
    output reg [6:0] AN
    );
parameter CLK_FREQ = 125_000_000;    
    
assign CA = 1'b0;

always @(SW)
begin
    case (SW)
        2'b00 : AN = 7'h7c;
        2'b01 : AN = 7'h60;
        2'b10 : AN = 7'h6d;
        2'b11 : AN = 7'h79;
    endcase    
end 
endmodule

 

5. Open Elaborated Design 후 포트 할당

 

6. my_fsm_secure_top.v 코드 수정

module my_fsm_secure_top(
    input RST,
    input CLK,
    input [1:0] KEY,
    input SENSOR,
    output ALARM_SIREN,
    output CA,
    output [6:0] AN,
    output VCC
    );
    
wire [1:0] fsm_state;

assign VCC = 1'b1;

 

7. VCC포트 추가 후 재할당

 

8. 위 과정 재수행 후 동작 확인


실습 2: 교통 신호기 FSM


1. my_traffic 프로젝트 생성

2. Add Design Sources로 time_chk.v 생성

 

3. 코드 작성

`timescale 1ns / 1ps


module time_chk(
    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 [39:0] MAX_CNT = time_slot * CLK_FREQ / 10;
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;

    
endmodule

 

4. Add Sources-Design Sources로 traffic_cnt 형성 후 포트 설정

 

5. 코드작성

`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]   //sIDLE   = 3'd0
                    sYEL    = 2'd0,
                    sRED    = 2'd1,
                    sGREEN  = 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 [8: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, PED_SW)
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
                time_slot = 10;
                if (cnt_done) begin
                    next_state = sRED;
                    start_cnt = 1'b0;
                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
                    start_cnt = 1'b0;
                    next_state = sGREEN;
                end
                else if(PED_SW)   begin
                    next_state = sPED;
                    start_cnt = 1'b0;
                end
                else begin
                    start_cnt = 1'b1;
                    next_state = sRED;
                end
                RED = 1'b1;
            end
            sGREEN: begin
                time_slot = 80;
                if (cnt_done) begin
                    start_cnt = 1'b0;
                    next_state = sYEL;
                end
                else begin
                    start_cnt = 1'b1;
                    next_state = sGREEN;
                end
                GREEN = 1'b1;
                WORK = 1'b1;
            end
            sPED: begin
                if(curr_slot < 20 )
                begin
                    time_slot = 20;
                    curr_time = 7'd0;
                end
                else begin
                    time_slot = 12;
                    curr_time = 7'd0;
                end                
                if (cnt_done) begin
                    start_cnt = 1'b0;
                    next_state = sGREEN;
                end
                else begin
                    start_cnt = 1'b1;
                    next_state = sPED;
                end
                RED = 1'b1;
            end                                               
            default : next_state = sYEL;
        endcase
    end //if-else
end          //always

time_chk #(.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 <= 7'd0;
        else if (pd_sw_rising)
            curr_time <= curr_slot;
end    
endmodule

 

 

6. 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(RED == 1'b1);
    wait(RED == 1'b0);
    wait(RED == 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

 

7. Behavioral Simulation 결과 확인

 

8. 포트 설정

 

 

9. 동작 확인