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

하만(Harman) 세미콘 아카데미 47일차 - Verilog HDL 설계(UART 실습)

semicon_circuitdesigner 2024. 5. 20. 16:24

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


실습 1: uart_rx


1. uart_rx_cntl.v Design Sources 생성

 

2. 코드 작성

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2024/05/20 12:06:26
// Design Name: 
// Module Name: uart_rx_cntl
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module uart_rx_cntl(
    input RST,
    input CLK,
    input RXD,
    input BAUD_X16_EN,
    input bit_cnt_done,
    output reg [1:0] fsm_state
    );
    
localparam [1:0]    idle = 2'b00,
                    start= 2'b01,
                    data = 2'b10,
                    stop = 2'b11;
                    
reg [1:0]   curr_state, next_state;
wire        over_sample_cnt_done;
reg [3:0]   over_sample_cnt;

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

always @(curr_state, over_sample_cnt_done, bit_cnt_done, RXD)
begin
    case (curr_state)
        idle : begin
            if(RXD == 1'b0)
                next_state = start;
            else
                next_state = idle;
            fsm_state = 2'b00;
        end
        start : begin
            if(over_sample_cnt_done) begin
                if(RXD)
                    next_state = idle;
                else
                    next_state = data;
                end
                fsm_state = 2'b01;
        end
        data : begin
            if(over_sample_cnt_done && bit_cnt_done)
                next_state = stop;
            else
                next_state = data;
            fsm_state = 2'b10;
        end
        stop : begin
            if(over_sample_cnt_done)
                next_state = idle;
            else
                next_state= stop;
            fsm_state = 2'b11;
        end
        default : next_state = idle;
    endcase
end
        

//over sample count
always @(posedge CLK)
begin
   if(RST || curr_state == idle)
        over_sample_cnt <= 4'd7;
    else if(BAUD_X16_EN) begin
        if (over_sample_cnt_done)
            over_sample_cnt <= 4'd15;
        else
            over_sample_cnt <= over_sample_cnt - 1;
        end
end

assign over_sample_cnt_done = (over_sample_cnt == 4'd0);

endmodule

 

3. 테스트벤치를 위한 my_uart_rx_cntl_tb.v Simulation Sources 생성

4. 테스트벤치 코드 작성

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2024/05/20 13:37:45
// Design Name: 
// Module Name: my_uart_rx_cntl_tb
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module my_uart_rx_cntl_tb();
parameter clk_pd = 8.0;
parameter clk_flq = 125_000_000;
parameter baud_rate = 9600;
parameter bit_pd = clk_flq / baud_rate;

reg rst, clk, DATA_rx;
reg oversample_done, bit_cnt_done;
wire [1:0] fsm_state;

my_uart_rx_cntl uut0(
    .clk                (clk),
    .rst                (rst),
    .DATA_rx            (DATA_rx),
    .oversample_done    (oversample_done),
    .bit_cnt_done       (bit_cnt_done),
    .fsm_state          (fsm_state)
    );
    
initial begin
    rst = 1'b0;
    #(clk_pd*10);
    rst = 1'b0;
end

initial clk = 1'b0;
always #(clk_pd/2) clk = ~clk;

initial begin
    DATA_rx = 1'b1;
    oversample_done = 1'b0;
    bit_cnt_done = 1'b0;
    wait (!rst);
    repeat (10)@ (posedge clk)
    DATA_rx = 1'b0;
    #(bit_pd/2);
    oversample_done = 1'b1;
    @(posedge clk)
    oversample_done = 1'b1;
    bit_cnt_done = 1'b1;
    DATA_rx = 1'b1;
    @(posedge clk)
    oversample_done = 1'b0;
    bit_cnt_done = 1'b0;
    #(bit_pd/2);
    oversample_done = 1'b1;
    @(posedge clk)
    oversample_done = 1'b0;
    $finish;
end
    
endmodule

 

5.  uart_rx.v Design Sources 생성

 

6. 코드 작성

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2024/05/20 12:31:27
// Design Name: 
// Module Name: uart_rx
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module uart_rx(
    input RST,
    input CLK,
    input RXD,
    input PARITY,
    input bit_cnt_done,
    output [7:0] RX_DATA,
    output [1:0] fsm_state
    );
    
wire    baud_x16_en;

uart_baud_gen uart_baud_gen (
    .RST            (RST),
    .CLK            (CLK),
    .BAUD_X16_EN    (baud_x16_en)    
    );

uart_rx_cntl uart_rx_cntl (
    .RST            (RST),
    .CLK            (CLK),
    .RXD            (RXD),
    .BAUD_X16_EN    (baud_x16_en),
    .bit_cnt_done   (bit_cnt_done),
    .fsm_state      (fsm_state)
    );
    
endmodule

 

7. uart_rx.v의 시뮬레이션을 위한 uart_rx_tb.v Simulation Sources 생성

 

8. 코드 작성

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2024/05/20 14:09:58
// Design Name: 
// Module Name: uart_rx_tb
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module uart_rx_tb();
parameter CLK_PD = 8.0;
reg rst, clk, rxd;
reg bit_cnt_done;
wire [7:0] rx_data;
wire [1:0] fsm_state; 

uart_rx uut(
    .RST            (rst),
    .CLK            (clk),
    .RXD            (rxd),
    .PARITY         (1'b0),
    .bit_cnt_done   (bit_cnt_done),
    .RX_DATA        (rx_data),
    .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
    rxd = 1'b1;
    bit_cnt_done = 1'b0;
    wait (!rst);
    #(CLK_PD * 5);
    rxd = 1'b0;
    wait (fsm_state == 2'b10);
    #(CLK_PD*10);
    rxd = 1'b1;
    bit_cnt_done = 1'b1;
    wait (fsm_state == 2'b00);
    #1000;
    $finish;
end

endmodule

 

 

9. uart_rx_tb.v 파일을 top으로 변경

 

 

10. Run Behavioral Simulation

 

11. uart_rx_cntl.v 코드 수정

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2024/05/20 12:06:26
// Design Name: 
// Module Name: uart_rx_cntl
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module uart_rx_cntl(
    input RST,
    input CLK,
    input RXD,
    input BAUD_X16_EN,
    input bit_cnt_done,
    output reg [1:0] fsm_state
    );
    
localparam [1:0]    idle = 2'b00,
                    start= 2'b01,
                    data = 2'b10,
                    stop = 2'b11;
                    
reg [1:0]   curr_state, next_state;
wire        over_sample_cnt_done;
reg [3:0]   over_sample_cnt;
reg [3:0]   bit_cnt;
wire        bit_cnt_done;

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

always @(curr_state, over_sample_cnt_done, bit_cnt_done, RXD)
begin
    case (curr_state)
        idle : begin
            if(RXD == 1'b0)
                next_state = start;
            else
                next_state = idle;
            fsm_state = 2'b00;
        end
        start : begin
            if(over_sample_cnt_done) begin
                if(RXD)
                    next_state = idle;
                else
                    next_state = data;
                end
                fsm_state = 2'b01;
        end
        data : begin
            if(over_sample_cnt_done && bit_cnt_done)
                next_state = stop;
            else
                next_state = data;
            fsm_state = 2'b10;
        end
        stop : begin
            if(over_sample_cnt_done)
                next_state = idle;
            else
                next_state= stop;
            fsm_state = 2'b11;
        end
        default : next_state = idle;
    endcase
end
        
 
//over sample count
always @(posedge CLK)
begin
   if(RST || curr_state == idle)
        over_sample_cnt <= 4'd7;
    else if(BAUD_X16_EN) begin
        if (over_sample_cnt_done)
            over_sample_cnt <= 4'd15;
        else
            over_sample_cnt <= over_sample_cnt - 1;
        end
end

assign over_sample_cnt_done = (over_sample_cnt == 4'd0);

//bit cnt generate
always @(posedge CLK)
begin
    if(RST || curr_state != data)
        bit_cnt <= 4'd0;
    else if(over_sample_cnt_done)
        bit_cnt <= bit_cnt + 1;
end

assign bit_cnt_done = (over_sample_cnt_done && (bit_cnt == 4'd8)); 


   


endmodule

 

12. uart_rx_tb.v 코드 수정

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2024/05/20 14:09:58
// Design Name: 
// Module Name: uart_rx_tb
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module uart_rx_tb();
parameter CLK_PD = 8.0;
reg rst, clk, rxd;
//reg bit_cnt_done;
wire [7:0] rx_data;
wire [1:0] fsm_state; 

uart_rx uut(
    .RST            (rst),
    .CLK            (clk),
    .RXD            (rxd),
    .PARITY         (1'b0),
//    .bit_cnt_done   (bit_cnt_done),
    .RX_DATA        (rx_data),
    .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
    rxd = 1'b1;
//    bit_cnt_done = 1'b0;
    wait (!rst);
    #(CLK_PD * 5);
    rxd = 1'b0;
    wait (fsm_state == 2'b10);
    #(CLK_PD*30);
    rxd = 1'b1;
//    bit_cnt_done = 1'b1;
    wait (fsm_state == 2'b00);
    #1000;
    $finish;
end

endmodule

 

13. Run Behavioral Simulation

 

 


시뮬레이션