단순 UART의 verilog 구현

5073 단어
다음은 내가 쓴 간단한 UART 코드를 발췌하여 유연성과 건장성에 대해 다음과 같이 설계하였다.
1. 시스템 시계와 직렬 포트율은 매개 변수로 입력하고 예화할 때 유연하게 설정할 수 있다.
2. 수용 모듈은 시작 위치에서 중점 레벨이 여전히 낮은지 검사하고 그렇지 않으면 떨림으로 판정한다
 
수신기 코드
`timescale 1ns/1ps

//     200MHz,   115200
module uart_rx  #(
    parameter BAUDRATE = 115200, 
    parameter FREQ = 200_000_000)(
    input clk, nrst,
    input rx,
    output reg [7:0] rdata,
    output reg vld
    );

    localparam T = FREQ / BAUDRATE;

    // flag       , 1          
    reg flag;
    always @(posedge clk or negedge nrst) begin
        if(nrst == 0)
            flag <= 0; 
        else if(flag == 0 && rx == 0)
            flag <= 1;
        else if(cnt_bit == 1 - 1 && cnt_clk == T / 2 - 1 && rx == 1)
            flag <= 0;
        else if(end_cnt_bit)
            flag <= 0;
    end
    
    //       ,cnt_clk           ,cnt_bit  1    ,8    ,     , 10 
    reg [3:0] cnt_bit;
    reg [31:0] cnt_clk;
    assign end_cnt_clk = cnt_clk == T - 1;
    assign end_cnt_bit = end_cnt_clk && cnt_bit == 10 - 1;
    
    always @(posedge clk or negedge nrst) begin
        if(nrst == 0)
            cnt_clk <= 0;
        else if(flag) begin
            if(end_cnt_clk)
                cnt_clk <= 0;
            else
                cnt_clk <= cnt_clk + 1'b1;
        end
        else
            cnt_clk <= 0;
    end
    
    always @(posedge clk or negedge nrst) begin
        if(nrst == 0)
            cnt_bit <= 0;
        else if(end_cnt_clk) begin
            if(end_cnt_bit)
                cnt_bit <= 0;
            else
                cnt_bit <= cnt_bit + 1'b1;
        end
    end    
    
    //             
    always @(posedge clk or negedge nrst) begin
        if(nrst == 0)
            rdata <= 0;
        else if(cnt_clk == T / 2 - 1 && cnt_bit != 1 - 1 && cnt_bit != 10 - 1)
            rdata[cnt_bit - 1] <= rx;
    end
    
    always @(posedge clk or negedge nrst) begin
        if(nrst == 0)
            vld <= 0;
        else if(end_cnt_bit)
            vld <= 1;
        else
            vld <= 0;
    end
    
endmodule

송신기 코드
`timescale 1ns/1ps

//     200MHz,   115200,       rdy
module uart_tx #(
    parameter BAUDRATE = 115200, 
    parameter FREQ = 200_000_000)(
    input clk, nrst,
    input wrreq,
    input [7:0] wdata,
    output reg tx,
    output reg rdy
    );
    
    reg [3:0] cnt_bit;
    reg [31:0] cnt_clk;
    
    localparam T = FREQ / BAUDRATE;

    //       rdy    ,             
    always @(posedge clk or negedge nrst) begin
        if(nrst == 0)
            rdy <= 1;
        else if(wrreq)
            rdy <= 0;
        else if(end_cnt_bit)
            rdy <= 1;
    end
    
    //       ,cnt_clk           ,cnt_bit  1    ,8    ,     , 10 
    wire end_cnt_clk;
    wire end_cnt_bit;
    assign end_cnt_clk = cnt_clk == T - 1;
    assign end_cnt_bit = end_cnt_clk && cnt_bit == 10 - 1;
    
    always @(posedge clk or negedge nrst) begin
        if(nrst == 0)
            cnt_clk <= 0;
        else if(rdy == 0) begin
            if(end_cnt_clk)
                cnt_clk <= 0;
            else
                cnt_clk <= cnt_clk + 1'b1;
        end
    end
    
    always @(posedge clk or negedge nrst) begin
        if(nrst == 0)
            cnt_bit <= 0;
        else if(end_cnt_clk) begin
            if(end_cnt_bit)
                cnt_bit <= 0;
            else
                cnt_bit <= cnt_bit + 1'b1;
        end
    end
    
    //         0,  8    ,      1
    always @(posedge clk or negedge nrst) begin
        if(nrst == 0)
            tx <= 1;
        else if(rdy == 0 && cnt_clk == 0) begin
            if(cnt_bit == 1 - 1)
                tx <= 0;
            else if(cnt_bit == 10 - 1)
                tx <= 1;
            else
                tx <= wdata[cnt_bit - 1];
        end
    end
    
endmodule

Xilinx Artix-7 플랫폼에서 검증된 최상위 레벨 코드
`timescale 1ns / 1ps

module uart_top(
    input clk_p, clk_n, nrst,
    input rx,
    output tx
    );
    
    localparam BAUDRATE = 115200;
    localparam FREQ = 200_000_000;
    
    //             
    IBUFGDS #(
        .DIFF_TERM("FALSE"),
        .IBUF_LOW_PWR("TRUE"),
        .IOSTANDARD("DEFAULT")
    )  IBUFGDS_inst(
        .O(clk),
        .I(clk_p),
        .IB(clk_n)
    );
    
    wire [7:0] data;
    wire vld;
    
    uart_rx #(BAUDRATE, FREQ) uart_rx_u(
    .clk    (clk    ),
    .nrst    (nrst    ),
    .rx        (rx        ),
    .rdata    (data    ),
    .vld    (vld    )
    );
    
    uart_tx #(BAUDRATE, FREQ) uart_tx_u(
    .clk    (clk    ),
    .nrst    (nrst    ),
    .wrreq    (vld    ),
    .wdata    (data    ),
    .tx        (tx        ),
    .rdy    (        )
    );
    
    ila_0 ila_0_u(
    .clk     (clk    ), 
    .probe0  (nrst   ),
    .probe1  ({tx,rx}),
    .probe2  (data   ),
    .probe3  (vld    )
    );
    
endmodule

좋은 웹페이지 즐겨찾기