1. 程式人生 > 實用技巧 >FPGA——9600波特率UART串列埠收發

FPGA——9600波特率UART串列埠收發

一、RTL Viewer

二、引腳描述

三.波特率計算

系統時鐘50MHz

(1bit/波特率bit/s)秒 / (1/50MHz)秒

四.verilog程式碼

 1 module uart_rx(
 2     clk     ,
 3     rst_n   ,
 4     rx_uart ,
 5     rx_data
 6 );
 7 
 8 parameter   DATA_R =    8;
 9 parameter   DATA_0 =   13;
10 parameter   DATA_1 =    4;
11 input                               clk;
12 input rst_n; 13 input rx_uart; 14 output [DATA_R-1:0] rx_data; 15 16 reg [DATA_R-1:0] rx_data; 17 18 reg [DATA_0-1:0] cnt0; 19 wire add_cnt0; 20 wire end_cnt0;
21 22 reg [DATA_1-1:0] cnt1 ; 23 wire add_cnt1; 24 wire end_cnt1; 25 26 wire nedge; 27 reg flag_add; 28 29 //9600位元率計數 30 always @(posedge clk or negedge rst_n)begin 31 if
(!rst_n)begin 32 cnt0 <= 0; 33 end 34 else if(add_cnt0)begin 35 if(end_cnt0) 36 cnt0 <= 0; 37 else 38 cnt0 = cnt0 + 1'b1; 39 end 40 end 41 assign add_cnt0 = flag_add; 42 assign end_cnt0 = add_cnt0 && cnt0 == 5208 - 1; 43 44 //9位元串列埠資料計數 45 always @(posedge clk or negedge rst_n)begin 46 if(!rst_n)begin 47 cnt1 <= 0; 48 end 49 else if(add_cnt1)begin 50 if(end_cnt1) 51 cnt1 <= 0; 52 else 53 cnt1 <= cnt1 + 1'b1; 54 end 55 end 56 assign add_cnt1 = end_cnt0; 57 assign end_cnt1 = add_cnt1 && cnt1 == 9 - 1; 58 59 60 61 //邊沿檢測,接D觸發器 62 //非同步訊號同步化,防止亞穩態,打兩拍 63 reg[2:0] uart_sync; 64 always @(posedge clk or negedge rst_n)begin 65 if(!rst_n)begin 66 uart_sync <= 3'b111; 67 end 68 else 69 uart_sync <= {uart_sync[1:0],rx_uart}; 70 end 71 assign nedge = uart_sync[2:1] == 2'b10; 72 73 //當接收到的串列埠由1變0時,flag_add置位 74 //當計數結束時,flag_add復位 75 always @(posedge clk or negedge rst_n)begin 76 if(!rst_n)begin 77 flag_add <= 0; 78 end 79 else if(nedge)begin 80 flag_add <= 1; 81 end 82 else if(end_cnt1)begin 83 flag_add <= 0; 84 end 85 end 86 87 //cnt1 == 0時,接收的是起始位0,1-8才是資料位 88 always @(posedge clk or negedge rst_n)begin 89 if(!rst_n)begin 90 rx_data <= 8'h00; 91 end 92 else if (add_cnt0 && cnt0 == 5208/2 - 1 && cnt1 > 0) begin 93 rx_data[cnt1 - 1] <= rx_uart; 94 end 95 end 96 97 endmodule
UART_RX
  1 module uart_tx(
  2     clk     ,
  3     rst_n   ,
  4     tx_vld  ,
  5     tx_data ,
  6     uart_tx
  7 // tx_rdy  
  8 );
  9 
 10 parameter   DATA_T =            8;
 11 parameter   DATA_0 =           13;
 12 parameter   DATA_1 =            4;
 13 
 14 input                         clk;
 15 input                       rst_n;
 16 input                      tx_vld;
 17 input       [DATA_T-1:0]  tx_data;
 18 output                    uart_tx;
 19 // output                     tx_rdy;
 20 
 21 reg                          uart_tx;
 22 // reg                        tx_rdy;
 23 
 24 reg         [DATA_0-1:0]     cnt0;
 25 wire                     add_cnt0;
 26 wire                     end_cnt0;
 27 
 28 reg         [DATA_1-1:0]     cnt1;
 29 wire                     add_cnt1;
 30 wire                     end_cnt1;
 31 
 32 reg                      add_flag;
 33 
 34 reg         [9:0]    tx_data_temp;
 35 wire                    load_data;
 36 
 37 wire                      en_send;
 38 
 39 //9600波特率計數器
 40 always @(posedge clk or negedge rst_n)begin
 41     if(!rst_n)begin
 42         cnt0 <= 0;
 43     end
 44     else if(add_cnt0)begin
 45         if(end_cnt0)
 46             cnt0 <= 0;
 47         else
 48             cnt0 <= cnt0 + 1'b1;
 49     end
 50 end
 51 assign add_cnt0 = add_flag;
 52 assign end_cnt0 = add_cnt0 && cnt0 == 5208 - 1;
 53 
 54 //10位元資料傳送計數器
 55 always @(posedge clk or negedge rst_n)begin
 56     if(!rst_n)begin
 57         cnt1 <= 0;
 58     end
 59     else if(add_cnt1)begin
 60         if(end_cnt1)
 61             cnt1 <= 0;
 62         else
 63             cnt1 <= cnt1 + 1'b1;
 64     end
 65 end
 66 assign add_cnt1 = end_cnt0;
 67 assign end_cnt1 = add_cnt1 && cnt1 == 10 - 1;
 68 
 69 //add_flag
 70 always @(posedge clk or negedge rst_n)begin
 71     if(!rst_n)begin
 72         add_flag <= 0;
 73     end
 74     else if(tx_vld)begin
 75         add_flag <= 1;
 76     end
 77     else if(end_cnt1)begin
 78         add_flag <= 0;
 79     end
 80 end
 81 
 82 //裝載資料
 83 always @(posedge clk or negedge rst_n)begin
 84     if(!rst_n)begin
 85         tx_data_temp <= 0;
 86     end
 87     else if(load_data)begin
 88         tx_data_temp <= {1'b1,tx_data,1'b0};
 89     end
 90 end
 91 assign load_data = tx_vld && !add_flag;
 92 
 93 //傳送資料
 94 always @(posedge clk or negedge rst_n)begin
 95     if(!rst_n)begin
 96         uart_tx <= 1;//1空閒位
 97     end
 98     else if(en_send)begin
 99         uart_tx <= tx_data_temp[cnt1];
100     end
101 end
102 assign en_send = add_cnt0 && cnt0 == 0;
103 
104 
105 // always @(*)begin
106 //     if(add_flag || tx_vld)
107 //         tx_rdy = 0;
108 //     else
109 //         tx_rdy = 1;
110 // end
111 
112 endmodule
UART_TX
 1 module UART_PORT(
 2     clk        ,
 3     rst_n    ,
 4     rx_uart    ,
 5     tx_vld    ,
 6     tx_data    ,    
 7     rx_data    ,
 8     uart_tx
 9 );
10 input                      clk;
11 input                        rst_n;
12 input                      rx_uart;
13 input                    tx_vld;
14 input    [8-1:0]        tx_data;
15 output[8-1:0]        rx_data;
16 output               uart_tx;
17 
18 wire     [8-1:0]         rx_data;
19 wire                     uart_tx;
20 
21 uart_rx UART_RX(
22     .clk    (clk),
23     .rst_n    (rst_n),
24     .rx_uart(rx_uart),
25     .rx_data(rx_data)
26 );
27 
28 uart_tx UART_TX(
29     .clk    (clk),
30     .rst_n    (rst_n),
31     .tx_vld    (tx_vld),
32     .tx_data(tx_data),
33     .uart_tx(uart_tx)
34 );
35 
36 endmodule
UART_PORT