__________

Designing the Future with Circuits

반도체 회로설계 취준기

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

하만(Harman) 세미콘 아카데미 36일차 - Verilog HDL 설계(FSM)

semicon_circuitdesigner 2024. 4. 26. 13:45

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

 


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


FSM State Diagram


1. 버튼이 눌리면 STR_STP변수를 1과 0으로 변경하여 모드를 Start, Stop으로 변경하는 모듈 작성

  • Switch를 누르면 CLK의 rising edge에 맞춰 ss_1d를 1로
  • 다음 CLK의 rising edge에서도 switch가 1이면 ss_2d를 1로

Encoding Methods p.317


p.326

 

mealy finite state machine p.330

FSM Coding Guidlines p.341

Avoiding Race Conditions in Veriog p. 356


실습: FSM Demo


1. Vivado 실행 후 my_fsm 프로젝트 생성

2. INPUT은 RST, CLK, [1:0] SW / OUTPUT은 [1:0] LED로 설정

3. 코드 작성

`timescale 1ns / 1ps

module my_fsm(
    input RST,
    input CLK,
    input [1:0] SW,
    output reg [1:0] LED
    );
    
localparam [1:0] idle = 2'b00,
                 state_a =  2'b01,
                 state_b =  2'b10,
                 state_c =  2'b11;
              
reg [1:0] curr_state, next_state;

always @(posedge CLK)
begin
    if (RST)
        curr_state <= idle;
    else
        curr_state <= next_state;
end //always end

always @(curr_state, SW)
begin
    case (curr_state)
        idle : begin
            if(SW == 2'b01)
                next_state = state_a;
            else
                next_state = idle;
            LED = 2'b00;
        end
        state_a : begin
            if(SW == 2'b10)
                next_state = state_b;
            else
                next_state = state_a;
            LED = 2'b01;
        end
        state_b : begin
            if(SW == 2'b11)
                next_state = state_c;
            else
                next_state = state_b;
            LED = 2'b10;
        end
        state_c : begin
            if(SW == 2'b00)
                next_state = idle;
            else
                next_state = state_c;
            LED = 2'b11;
        end
        default: next_state = idle;
    endcase
end //always end
endmodule

 

4. 테스트벤치 파일 생성 후 코드 작성

  • parmaeter로 클록의 주기 설정: parameter CLK_PD = 10.0;
  • 위 코드의 INPUT은 변경 가능하므로 reg로, OUTPUT은 변경 불가하므로 wire로 선언
  • my_fsm uut ( );를 이용하여 포트 맵핑
    `timescale 1ns / 1ps
    
    module my_fsm_tb();
    parameter CLK_PD = 10.0;
    
    reg RST, CLK;
    reg [1:0] SW;
    wire [1:0] LED;
    
    
    my_fsm uut(
        .RST    (RST),
        .CLK    (CLK),
        .SW     (SW),
        .LED    (LED)
        );
    
    
    endmodule​
  • RST을 켰다 꺼준 뒤, CLK신호를 생성하기 위한 코드 작성
    initial begin
        RST = 1'b1;
        #(CLK_PD*20);
        RST = 1'b0;
    end
    
    initial CLK = 1'b0;
    always #(CLK_PD/2) CLK = ~CLK;​

 

 

  • 스위치를 주기적으로 바꾸기 위한 코드 작성
    initial begin
        SW = 2'b00;
        wait (RST == 1'b0);
        #(CLK_PD*10);
        SW = 2'b01;
        #(CLK_PD*10);
        SW = 2'b10;
        #(CLK_PD*10);
        SW = 2'b11;
        #(CLK_PD*10);
        SW = 2'b00;
    end​

5. Behavioral Simulation 진행 후 결과 확인

 

 

6. Board에 스위치를 연결하기 전에 my_fsm.v파일의 INPUT 파트 코드 수정

module my_fsm(
    input RST,
    input CLK,
    input [1:0] SW,
    output reg [1:0] LED,
    output          VCC,
    output          GND
    );
    
assign VCC = 1'b1;
assign GND = 1'b0;

 

7. Open Elaborated Design 수행 후 I/O Planning에서 포트 지정

8. Run Implementation - my_fsm으로 save

9. Generate Bitstream

10. Open H/W Manager -> Open Target -> Program Device

11. 핀 설정에서 오류(작동 x)로 인해 핀 재설정

  • OUTPUT의 GND 없애고, 스위치 장착 위치 변경 후 I/O Planning
  • Elaborated Design Reload - Generate Bitstream 후 Program Device

12. 동작 확인


실습: FSM Sequrity


  • SW가 00 -> 해제 / 11 -> 잠금

 

1. my_fsm_secure project 생성 후 my_fsm_secure.v 코드 작성

`timescale 1ns / 1ps

module my_fsm_secure(
    input CLK,
    input RST,
    input [1:0] KEY,
    input SENSOR,
    output reg ALARM_SIREN,
    output reg [1:0] FSM_STATE
    );
    
parameter CLK_FREQ = 125_000_000;
localparam [1:0]    disarmed = 2'b00,
                    armed = 2'b01,
                    wait_delay = 2'b10,
                    alarm = 2'b11;

reg [1:0]   curr_state, next_state;
wire        cnt_done;
reg         start_cnt;
reg [29:0]  cnt;

always @(posedge CLK)
    if(RST)
        curr_state <= disarmed;
    else
        curr_state <= next_state;
        
always @(curr_state, KEY, SENSOR, cnt_done)
begin
    start_cnt = 1'b0;
    ALARM_SIREN = 1'b0;
    
    case(curr_state)
        disarmed : begin
            if(KEY == 2'b11)
                next_state = armed;
            else
                next_state = disarmed;
            FSM_STATE = 2'b00;
        end
        armed : begin
            if(SENSOR == 1'b1)
                next_state = wait_delay;
            else if( KEY == 2'b00)
                next_state = disarmed;
            else
                next_state = armed;
            FSM_STATE = 2'b01;
        end
        wait_delay : begin
            start_cnt = 1'b1;
            if(cnt_done == 1'b1)
                next_state = alarm;
            else if( KEY == 2'b00)
                next_state = disarmed;
            else
                next_state = wait_delay;
            FSM_STATE = 2'b10;
        end
        alarm : begin
            if( KEY == 2'b00)
                next_state = disarmed;
            else
                next_state = alarm;
            FSM_STATE = 2'b11;
        end
        default : next_state = disarmed;
    endcase
end

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


assign cnt_done = cnt == (CLK_FREQ*5 - 1);

endmodule

 

2. 테스트벤치를 위해 my_secure_tb.v Simulation Source를 추가하고 코드 작성

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2024/04/26 15:34:55
// Design Name: 
// Module Name: my_fsm_security_tb
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module my_fsm_secure_tb();
parameter CLK_PD = 8.00;
reg RST, CLK;
reg [1:0] KEY;
reg SENSOR;
wire alarm_siren;
wire [1:0] fsm_state;

my_fsm_secure uut(
    .CLK            (CLK),
    .RST            (RST),
    .KEY            (KEY),
    .SENSOR         (SENSOR),
    .ALARM_SIREN    (alarm_siren),
    .FSM_STATE      (fsm_state)
    );

initial begin
    RST = 1'b1;
    #(CLK_PD*10);
    RST = 1'b0;
end

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

initial begin
    KEY = 2'b00;
    SENSOR = 1'b0;
    wait (RST == 1'b0);
    #(CLK_PD*10);
    KEY = 2'b01;    //armed
    #(CLK_PD*10);
    KEY = 2'b10;    //disarmed
    #(CLK_PD*10);
    KEY = 2'b11;    //armed
    #(CLK_PD*10);
    SENSOR = 1'b1;    
    wait (alarm_siren == 1'b1);
    #(CLK_PD*10);
    KEY = 2'b0;    //disarmed
    SENSOR = 1'b0;
    #(CLK_PD*10);
    $finish;
end
    
endmodule

 

3. Behavioral Simulation 결과 확인