Menu Close

UART 组装与仿真

UART 组装与仿真

上几节内容介绍了UART的组成部分发送(tx.v), 接收(rx.v)以及波特率发生器(bd_rate_en.v)等原理及代码,本节内容介绍如何将各个模块组装在一起形成一个完整的UART收发系统UART.v。

一、rx采用中心对齐的模块。

  1. UART组装的程序


module UART
#(
    parameter BAUD_RATE = 115200,
    parameter PARITY    = "ODD"
)
(
    input        inclk,
    input        tx_req,
    input  [7:0] tx_data,
    output       tx_ack,
    output       tx,

    input        rx,
    input        rx_ack,
    output       rx_rdy,
    output [7:0] rx_data,

    output       rst,
    output       sys_clk		
);

wire   	tx_bd_en;
wire   	rx_bd_en;
wire   	locked;

assign   rst = !locked;

uart_pll  uart_pll_inst
(
    .areset   (1'b0),
    .inclk0   (inclk),
    .c0       (sys_clk),   //sys_clk 72Mhz
    .locked   (locked)
);

baud_rate_en
#(
    .BAUD_RATE (115200),
    .FREQUENCY (72000000)
)   
bau_rate_en_inst
(
    .clk      (sys_clk),
    .rst      (rst),
    .tx_bd_en (tx_bd_en),
    .rx_bd_en (rx_bd_en)
);


tx
#(
    .PARITY   (PARITY),
    .STOP_BIT (1)
)
txd_inst
(
    .rst      (rst),
    .clk      (sys_clk),
    .tx_bd_en (tx_bd_en),
    .tx_data  (tx_data),
    .tx_rdy   (tx_req),
    .tx_ack   (tx_ack),
    .tx	      (tx)
);


rx_center
#(
    .PARITY    (PARITY),   //"ODD"--odd parity, "EVEN"--even parity, others-->  no parity
    .STOP_BIT  (1)
)
rx_certer_inst
(
    .sys_clk   (sys_clk),
    .rst       (rst),
    .rx        (rx),
    .bd8_rate  (rx_bd_en),
    .rx_data   (rx_data),
    .rx_rdy    (rx_rdy)
);

endmodule


  
  1. 仿真程序

`timescale 1 ns / 1 ps

module test_UART
(

);

parameter PARITY = "none";
parameter PERIOD = 20;

reg  inclk;
reg  rx_ack;

wire       rx_rdy;
wire [7:0] rx_data;

initial 
begin
    inclk = 0;
end

always #(PERIOD/2) inclk = ~inclk;

wire      rst;
wire      sys_clk;

reg       tx_req;
reg [7:0] tx_data;

wire      tx_ack;
wire      tx_rx;

reg [1:0] tx_st; 


//模拟发送协议,生成数据


always@(posedge sys_clk or posedge rst)
if(rst) 
begin
    tx_st <= 0;
    tx_req <= 0;
    tx_data <= 0;
end
else 
begin
    case(tx_st)
    0:
    begin
        tx_data <= 0;
        tx_req <= 0;
        tx_st <= 1;
    end
    1:
    begin
        tx_req <= 1'b1;
        tx_st <= 2;
    end
    2:
    begin
        if(tx_ack) 
        begin
            tx_req <= 1'b0;
            tx_st <= 3;
        end
    end
    3:
    begin
        tx_data <= tx_data + 1;
        tx_st <= 1;
    end	
    default: tx_st <= 0;
    endcase

end

always@(posedge sys_clk or posedge rst)
if(rst) 
begin
    rx_ack = 0;
end
else 
begin
    rx_ack = 0;

    if(rx_rdy)
        rx_ack = 1'b1;
end

UART
#(
    .BAUD_RATE (115200),
    .PARITY    (PARITY)
)

UART_inst
(
    .inclk    (inclk),
    .tx_req   (tx_req),
    .tx_data  (tx_data),
    .tx_ack   (tx_ack),
    .tx	      (tx_rx),      //利用tx_rx,进行回环测试

    .rx	      (tx_rx),
    .rx_ack   (rx_ack),
    .rx_rdy   (rx_rdy),
    .rx_data  (rx_data),

    .rst      (rst),
    .sys_clk  (sys_clk)
);

endmodule


  
  1. 仿真波形(Modelsim)

%title插图%num

图1

从图1的波形可以看出,经过回环测试,接收数据可以正确接收数据。

2. RXD部分用判多替代中心对齐方式


module UART
#(
    parameter BAUD_RATE = 115200,
    parameter PARITY    = "ODD"
)
(
    input        inclk,
    input        tx_req,
    input  [7:0] tx_data,
    output       tx_ack,
    output       tx,

    input        rx,
    input        rx_ack,
    output       rx_rdy,
    output [7:0] rx_data,
    output       rst,
    output       sys_clk
);

wire   	tx_bd_en;
wire   	rx_bd_en;
wire   	locked;

assign   rst = !locked;

uart_pll  uart_pll_inst
(
    .areset  (1'b0),
    .inclk0  (inclk),
    .c0      (sys_clk),   //sys_clk 72Mhz
    .locked  (locked)
);

baud_rate_en
#(
    .BAUD_RATE  (115200),
    .FREQUENCY  (72000000)
)   
bau_rate_en_inst
(
    .clk      (sys_clk),
    .rst      (rst),
    .tx_bd_en (tx_bd_en),
    .rx_bd_en (rx_bd_en)
);

tx
#(
    .PARITY    (PARITY),
    .STOP_BIT  (1)
)
txd_inst
(
    .rst       (rst),
    .clk       (sys_clk),
    .tx_bd_en  (tx_bd_en),
    .tx_data   (tx_data),
    .tx_rdy    (tx_req),
    .tx_ack    (tx_ack),
    .tx        (tx)
);

rx_more_one
#(
    .PARITY    (PARITY),   //"ODD"--odd parity, "EVEN"--even parity, others--&gt;  no parity
    .STOP_BIT  (1)
)
rx_more_one_inst
(
    .sys_clk   (sys_clk),
    .rst       (rst),
    .rx        (rx),
    .bd8_rate  (rx_bd_en),
    .rx_data   (rx_data),
    .rx_rdy    (rx_rdy)
);

endmodule


  

仿真波形:仿真程序依然采用上面的仿真程序,得到波形如图2

%title插图%num

图2

加载rx_more_one 变量到仿真波形中,观察其中一位的接收,移位,求和,判多的结果看看是否与预期的设计相符,图3,4显示了停止位的解码过程。

%title插图%num

图3

%title插图%num

图4

图4的红框标注了sample_bit,count_one,rx_bit与状态机及sam[le_count_cs之间的逻辑与时序关系。最终测试在停止位解码时,count_one得到8个1,提高了判决的冗余度。

练习题:

  1. 将奇偶校验设为奇校验,重新仿真,并验证接收数据的正确性。
  2. 分析对照仿真波形rx_r[1],sample_st_cs, sample_count_cs,sample_bit,count_one,rx_bit的时序关系,并分析在判多时为什么要如下语句出现:
sample_count_cs_r <= sample_count_cs;


if(sample_count_cs_r == 7)
begin //delay one clock
    case(sample_st_cs)
    FIRST_BIT: rx_data_tmp[0] = rx_bit;
    SEC_BIT:   rx_data_tmp[1] = rx_bit;
    THIRD_BIT: rx_data_tmp[2] = rx_bit;
    FOUTH_BIT: rx_data_tmp[3] = rx_bit;
    FIF_BIT:   rx_data_tmp[4] = rx_bit;
    SIX_BIT:   rx_data_tmp[5] = rx_bit;
    SEVN_BIT:  rx_data_tmp[6] = rx_bit;
    EIGTH_BIT: 
    begin
        rx_data_tmp[7] = rx_bit;
        rx_rdy_tmp = 1'b1;    
    end
    default:;
    endcase

而不是直接采用if(sample_count_cs == 7)begin 的方式实现 ?

 

附件下载

Posted in FPGA, FPGA, Quartus II, Verilog, Verilog, Vivado, 教材与教案, 文章, 编程语言

发表评论

相关链接