这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » FPGA » 串口通信系列2——发送模块

共9条 1/1 1 跳转至

串口通信系列2——发送模块

菜鸟
2014-09-25 19:51:46     打赏

        串口通信系列2——发送模块

        上篇文章介绍了一下UART接收模块,这篇我们谈一谈发送模块。

        发送模块将需要传输的8位数据以字符帧格式发送出去。那我们就开门见山,发送模块由哪些模块组成?

        由上图可知,波特率定时模块在发送模块中依然扮演着非常重要的角色。

        波特率定时模块:当bps_start信号为低电平时,波特率定时模块不工作。当bps_start信号为高电平时,波特率定时模块使能工作,然后定时产生一个高脉冲bps_clk给发送模块。

        发送控制模块:当tx_en_sig信号使能时,发送模块同时把bps_start信号置高电平,使能波特率定时模块。发送控制模块按波特率定时模块产生的定时tx_data数据,有时间规律的发送给rs232_tx,当数据发送完毕,发送控制模块产生一个脉冲信号tx_done_sig

        我们先来看一看bps_module.v

module bps_module(
                  clk,rst_n,
                  bps_start,
                  bps_clk
                  );       
input  clk,rst_n;
input  bps_start;
output bps_clk;
`define BPS_PARA 5207
`define  BPS_PARA_2 2603
reg[12:0] cnt;
always@(posedge clk or negedge rst_n)
begin
   if(!rst_n)  
       cnt <= 13'd0;
   else if(cnt == `BPS_PARA)
       cnt <= 13'd0;
   else if(bps_start)
       cnt <= cnt + 1'b1;
   else
       cnt <= 13'd0;      
end                 
assign bps_clk = (cnt == `BPS_PARA_2)? 1'b1 : 1'b0;                         
endmodule



        其实我们可以发现发送波特率定时模块与接收模块的波特率定时模块完全一样。接收模块中波特率定时模块在每一帧中数据位的中间进行“定时”,而发送模块应该在每一帧中数据位的起始进行“定时”,怎么会发送和接收模块中的波特率定时模块完全一样了?

 

        这里很多人会搞不清楚,那我再问一个问题,波特率两个定时之间相差了多少个计数(时间)?答案显而易见是5028(0~5027),第一次定时波特率模块计2604个数(0~2603)产生一个脉冲,到第二次定时中间相差5208个数,这不就是一个数据位所占的时间。

        发送控制模块tx_control_module.v

module tx_control_module(
                          clk,rst_n,
                          tx_en_sig,tx_data,bps_clk,
                          bps_start,rs232_tx, tx_done_sig
                        );                        
input clk,rst_n;
input tx_en_sig, bps_clk;
input [7:0]tx_data;
output bps_start,tx_done_sig, rs232_tx;
reg [3:0]i;
reg bps_start_r;
reg tx_done_sig_r;
reg rs232_tx_r;
always@(posedge clk or negedge rst_n)
begin
      if(!rst_n)
      begin
                      i <= 1'd0;
            bps_start_r <= 1'b0;
          tx_done_sig_r <= 1'b0;
             rs232_tx_r <= 1'b1;
      end
      else if(tx_en_sig)
           case(i)
           4'd0:begin
                          i <= i+1'b1;
                   bps_start_r <= 1'b1;
               end
           4'd1:if(bps_clk)
                begin
                           i <= i+1'b1;
                  rs232_tx_r <= 1'b0;
                end
           4'd2, 4'd3, 4'd4, 4'd5, 4'd6, 4'd7, 4'd8, 4'd9:
                if(bps_clk)
                begin
                              i <= i+1'b1;
                  rs232_tx_r <= tx_data[i-2];      
                end
           4'd10:if(bps_clk)
                 begin
                     i <= i+1'b1;
                 rs232_tx_r <= 1'b1; 
                 end
           4'd11:if(bps_clk)
                 begin
                     i <= i+1'b1;
                 rs232_tx_r <= 1'b1; 
                 end
           4'd12:if(bps_clk)
                 begin
                                    i <= i+1'b1; 
                      bps_start_r <= 1'b0;
                    tx_done_sig_r <= 1'b1;
                end
           4'd13: begin
                                    i <= 4'd0; 
                        tx_done_sig_r <= 1'b0;
                  end
           default: ;
           endcase
end
assign bps_start = bps_start_r;
assign tx_done_sig = tx_done_sig_r;
assign rs232_tx = rs232_tx_r;
endmodule

 

        串口发送模块(顶层模块)tx_module.v

module tx_module(
                 clk,rst_n,
                 tx_en_sig,tx_data,
                 rs232_tx,tx_done_sig
                );
input clk,rst_n;
input tx_en_sig;
input [7:0]tx_data;
output tx_done_sig, rs232_tx;
wire bps_clk;
wire bps_start;
bps_module U1(
              .clk       (clk      ),
              .rst_n     (rst_n    ),
              .bps_start (bps_start),  //  form  U2
              .bps_clk   (bps_clk  )   //  to U2
             );
 
tx_control_module U2(
                      .clk           (clk        ),
                      .rst_n         (rst_n      ),
                      .tx_en_sig     (tx_en_sig  ),
                      .tx_data       (tx_data    ),
                      .bps_clk       (bps_clk    ),
                      .bps_start     (bps_start  ),
                      .rs232_tx      (rs232_tx   ), 
                      .tx_done_sig   (tx_done_sig)  
                    );
endmodule
testbench代码tx_module_tb.v
`timescale 1ns / 1ps
module tx_module_tb;
reg    clk;
reg    rst_n;                           
reg    tx_en_sig;
reg [7:0]tx_data;  
wire   rs232_tx;
wire   tx_done_sig;
tx_module i_tx_module(
                      .clk        (clk        ),
                      .rst_n      (rst_n      ),
                      .tx_en_sig  (tx_en_sig  ),
                      .tx_data    (tx_data    ),
                      .rs232_tx   (rs232_tx   ),
                      .tx_done_sig(tx_done_sig)
                     );
initial begin   clk = 0; forever  #10 clk = ~clk; end
initial begin
     rst_n = 0;tx_en_sig = 0;
     #1000;
     rst_n = 1;
     tx_en_sig = 1;
     #1000;
     tx_data = 8'b10101010;
     #1000000000;
     $stop;
    end
 
endmodule

 

        modelsim仿真波形:

        此次实验的重点在于理解波特率定时模块与tx_control_module.v红色字体部分,modelsim仿真由于跑的时间较长,只是贴出大概波形,有兴趣的朋友可以跑一跑modelsim分析一下具体的信号,以便更好的理解。


未完待续……


(本文章转载自博客,作者wiliamzhou



院士
2014-09-26 22:24:51     打赏
2楼

fpga的时序啊~~

好难啊~


专家
2015-01-10 21:05:35     打赏
3楼

我晕菜了


高工
2020-05-12 14:29:00     打赏
4楼

继续学习


工程师
2020-05-12 21:29:30     打赏
5楼

Verilog HDL 语言写的吧?!

很像C语言


高工
2020-07-11 15:59:20     打赏
6楼

感谢楼主分享


高工
2020-07-11 21:08:37     打赏
7楼

代码写的很简洁


工程师
2020-07-13 20:49:46     打赏
8楼

学到知识了


高工
2020-12-01 16:38:00     打赏
9楼

谢谢分享


共9条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]