zoukankan      html  css  js  c++  java
  • 基于fpga uart学习笔记

    2018年7月24日

    uart 接收 部分测试成功,多谢开源骚客 邓堪文老师 ,想学的同学可以微信公众号搜索开源骚客

    好啦!言归正传。

    1.先附上老师的时序图,自己有点懒不想画,rx_t、rx_tt、rx_ttt分别对应源码中的rx_r1、rx_r2、rx_r2。

    认真理解时序图,代码具体怎么实现就好理解了。

    2.需要说明的是baud_cnt这个计数器,他是波特率的计数器,计数原理了解这个公式

    3.剩下的就自己结合一下源码

      1 `define SIM
      2 
      3 module  uart_rx(
      4           //system signale
      5           input                       sclk            ,            
      6           input                        s_rst_n            ,
      7           //uart interface
      8           input                        rs232_rx        ,
      9           //other
     10           output    reg        [7:0]    rx_data            ,
     11           output    reg                po_flag
     12 
     13 );
     14 
     15 //-----------------------------------------------------------------\
     16 //***********Difine Parameter and Internal signals*****************
     17 //-----------------------------------------------------------------/
     18 `ifndef SIM
     19 localparam        BAUD_END            =    5207        ;
     20 `else
     21 localparam        BAUD_END            =    55            ;
     22 `endif
     23 localparam        BAUD_M                =    BAUD_END/2-1    ;
     24 localparam        BIT_END                =    8            ;
     25 
     26 
     27 reg                                    rx_r1            ;
     28 reg                                    rx_r2            ;
     29 reg                                    rx_r3            ;
     30 reg                                    rx_flag            ;
     31 reg            [12:0]                    baud_cnt        ;
     32 reg                                    bit_flag        ;
     33 reg            [3:0]                    bit_cnt            ;
     34 
     35 //==================================================================\
     36 //****************Main   Code *********************************
     37 //==================================================================/
     38 
     39 //捕获起始位下降沿
     40 assign rx_neg   =        ~rx_r2    & rx_r3;
     41 
     42 always @(posedge sclk ) begin
     43         rx_r1    <=        rs232_rx;
     44         rx_r2    <=        rx_r1;
     45         rx_r3    <=        rx_r2;
     46 end 
     47 
     48 //接收数据标志
     49 always @(posedge sclk or negedge s_rst_n) begin
     50         if(s_rst_n == 1'b0)
     51                 rx_flag <=    1'b0;
     52         else if(rx_neg == 1'b1)
     53                 rx_flag    <=    1'b1;
     54         else if(bit_cnt == 4'd0 && baud_cnt    == BAUD_END)
     55                 rx_flag    <=  1'b0;
     56 end
     57 
     58 //波特率生成
     59 always @(posedge sclk or negedge s_rst_n ) begin
     60         if(s_rst_n == 1'b0)
     61                 baud_cnt <= 13'd0;
     62         else if(baud_cnt == BAUD_END)
     63                 baud_cnt <= 13'd0;
     64         else if(rx_flag == 1'b1)
     65                 baud_cnt <= baud_cnt + 1'b1;
     66         else
     67                 baud_cnt <= 13'd0;
     68 end
     69 
     70 //位接收有效
     71 always @(posedge sclk or negedge s_rst_n) begin
     72         if(s_rst_n == 1'b0)
     73                 bit_flag <= 1'b0;
     74         else if (baud_cnt == BAUD_M)
     75                 bit_flag <= 1'b1;
     76         else
     77                 bit_flag <= 1'b0;
     78 end
     79  
     80 //位计数
     81 always @(posedge sclk or negedge s_rst_n) begin
     82         if(s_rst_n == 1'b0)
     83                 bit_cnt <= 4'd0;
     84         else if(bit_flag == 1'b1 && bit_cnt == BIT_END )
     85                 bit_cnt <= 4'd0;
     86         else if(bit_flag == 1'b1)
     87                 bit_cnt <= bit_cnt + 1'b1;
     88         
     89 end
     90 
     91 //串转并
     92 always @(posedge sclk or s_rst_n) begin
     93         if(s_rst_n == 1'b0)
     94                 rx_data <= 8'd0;
     95         else if (bit_flag == 1'b1 && bit_cnt >= 4'd1)
     96                 rx_data <= {rx_r2, rx_data[7:1]};
     97 end 
     98 //一位接收完成
     99 always @(posedge sclk or s_rst_n) begin
    100         if(s_rst_n == 1'b0)
    101                 po_flag <= 1'b0;
    102         else if(bit_cnt == BIT_END && bit_flag == 1'b1)
    103                 po_flag <= 1'b1;
    104         else
    105                 po_flag <= 1'b0;
    106 end
    107 
    108 endmodule

    4.源码这儿需要理解一下 `ifndef ,`else,`endif。这个是预编译处理,详情可以看这位大佬

    https://blog.csdn.net/hision_fpgaer/article/details/50909653

    5.测试文件,这里需要理解tast使用,以及外部数据文件的的用法(第26行)以及将文件里的数据如何存入二维数组中,tx_data文件就是一般的文本文件,这里设计的技巧太多,可以自己去查询一下。

     1 `timescale            1ns/1ns
     2 module    tb_uart_rx;
     3 
     4 reg                sclk;
     5 reg                s_rst_n;
     6 reg                rs232_tx;
     7 
     8 wire            po_flag;
     9 wire    [7:0]    rx_data;
    10 
    11 reg [7:0] mem_a[4:0];
    12 
    13 initial begin
    14         sclk     = 1;
    15         s_rst_n     = 0;
    16         rs232_tx = 1;
    17         #100
    18         s_rst_n     = 1;
    19         #100
    20         tx_tyte();
    21 end
    22 
    23 always # 10 sclk = ~sclk;
    24 
    25 
    26 initial  $readmemh("./tx_data.txt",mem_a);
    27 
    28 task  tx_tyte();
    29         integer i ;
    30         for(i = 0;i < 4; i = i +1)  begin
    31            tx_bit(mem_a[i]);
    32         end
    33 
    34 endtask
    35 
    36 
    37 task    tx_bit(
    38                 input        [7:0] data
    39                 );
    40         integer i;
    41         for(i = 0; i < 10; i = i+1)begin
    42             case(i)
    43                 0:        rs232_tx <= 1'b0;
    44                 1:        rs232_tx <= data[0];
    45                 2:        rs232_tx <= data[1];
    46                 3:        rs232_tx <= data[2];
    47                 4:        rs232_tx <= data[3];
    48                 5:        rs232_tx <= data[4];
    49                 6:        rs232_tx <= data[5];
    50                 7:        rs232_tx <= data[6];
    51                 8:        rs232_tx <= data[7];
    52                 9:        rs232_tx <= 1'b1;
    53             endcase
    54             #560;
    55         end
    56 endtask
    57 
    58 uart_rx        uart_rx_inst(
    59           //system signale
    60           .sclk                (sclk        ),            
    61           .s_rst_n            (s_rst_n    ),
    62           //uart interface
    63           .rs232_rx            (rs232_tx    ),
    64           //other
    65           .rx_data            (rx_data    ),
    66           .po_flag            (po_flag    )
    67 
    68 );
    69 
    70 
    71 endmodule

     

    总结一些自己,大一下学期期末左右接触到fpga,自己就爱好电子设计,大一一来就学了51单片机,下学期看着自己同学都报班32,学的都很好,而自己呢还在玩51,弄3D打印机,那个时候挺迷的。

    后来不小心看到了fpga,自己仔细去查了,也与32做了比较,斟酌了很久,最后还是下决心学fpga,但是那个我是什么处境呢,同级的一起玩的32都会做很多东西了,自己有小小羞耻感,关键是学校没有人学fpga或者说没有人学的可以的,如果要学的话只能孤军奋战。

    后来还是下决心买了板子,自学了一段时间,刚好暑假国赛,我也参加了,打击很大啊,最后还用51做,太丢人了。国赛完,我就自己瞎学fpga,一直因为对fpga的真正的喜爱,以及他那强大而又神秘能力支撑着我学到现在。

    刚开始都是看着大佬们的博客一路学习过来,这学期终于翻身了开始自己写博客了,虽然技术含量有点低,哈哈哈,但是还是很开心。到现在差不多学fpga一年了,说实话fpga也让我害怕,不光是她太难驾驭还有的是没啥成就,看其他人啪啪啪的一下子做一堆东西,而自己控制个舵机都吃力。

    现在这个暑假,马上又要大三了,趁着时间很多,好好重头在干一次,或许注定是孤独的,我爱你fpga,希望你也爱我,啦啦啦啦啦啦啦!!!!!!!!!!!!!!

    完工回去睡觉,fpga等我明天再来宠幸你!

    2018年7月26日

    uart发送部分以及收发整合,其实是昨天就完事儿了,有事给耽搁了,今天再补来得及。

    先说发送部分

    1.还是先看时序图,信号都不用解释,直接看图。

    2.仔细的同学发现bit_flag这个信号和接收的不一样,这次是baud_cnt波特率计数器记完再触发,而接收的是计数到一半触发,这两种方式作用相同,只是后者稳定一下,自己也可以改。

    下面附上接收的源码

      1// `define SIM
      2 module uart_tx(
      3         //system signal
      4         input                sclk            ,
      5         input                s_rst_n            ,
      6         //uart interface
      7         output        reg        rs232_tx        ,
      8         //other
      9         input                tx_trig            ,
     10         input        [7:0]    tx_data
     11  );
     12 
     13 //-----------------------------------------------------------------\
     14 //***********Difine Parameter and Internal signals*****************
     15 //-----------------------------------------------------------------/
     16 
     17 `ifndef SIM
     18 localparam        BAUD_END            =    5207        ;
     19 `else
     20 localparam        BAUD_END            =    56            ;
     21 `endif
     22 
     23 localparam        BAUD_M                =    BAUD_END/2-1    ;
     24 localparam        BIT_END                =    8            ;
     25 
     26 reg             [7:0]            tx_data_r            ;
     27 reg                                tx_flag                ;
     28 reg                [12:0]            baud_cnt            ;
     29 reg                                bit_flag            ;
     30 reg                [3:0]            bit_cnt                ;
     31 
     32 
     33 //==================================================================\
     34 //****************Main   Code *********************************
     35 //==================================================================/
     36 //tx_data_r
     37 always @(posedge sclk or negedge s_rst_n) begin
     38         if(s_rst_n == 1'b0)
     39                 tx_data_r    <=    8'd0;
     40         else if (tx_trig == 1'b1 && tx_flag == 1'b0)
     41                 tx_data_r    <=    tx_data;
     42 end
     43 
     44 //tx_flag
     45 always @(posedge sclk or negedge s_rst_n) begin
     46         if(s_rst_n == 1'b0)
     47                 tx_flag        <=    1'b0;
     48         else if(tx_trig == 1'b1 )
     49                 tx_flag        <=    1'b1;
     50         else if (bit_cnt == BIT_END && bit_flag == 1'b1)
     51                 tx_flag        <= 1'b0;
     52 end
     53 
     54 //波特率计数器
     55 always @(posedge sclk or negedge s_rst_n) begin
     56         if(s_rst_n == 1'b0)
     57                 baud_cnt    <= 13'd0;
     58         else if (baud_cnt  == BAUD_END)
     59                 baud_cnt    <= 13'd0;
     60         else if(tx_flag == 1'b1)
     61                 baud_cnt    <= baud_cnt +1'b1;
     62         else    
     63                 baud_cnt     <= 13'd0;
     64 end
     65 
     66 //bit_flag
     67 always @(posedge sclk or negedge s_rst_n) begin
     68         if(s_rst_n == 1'b0)
     69                 bit_flag <= 1'b0;
     70         else if(baud_cnt == BAUD_END)
     71                 bit_flag <= 1'b1;
     72         else
     73                 bit_flag <= 1'b0;    
     74 end
     75 
     76 //bit_cnt
     77 always @(posedge sclk or negedge s_rst_n) begin
     78         if(s_rst_n == 1'b0)
     79                 bit_cnt  <= 4'd0;
     80         else if(bit_flag == 1'b1 && bit_cnt == BIT_END)
     81                 bit_cnt <= 4'd0;
     82         else if (bit_flag == 1'b1)
     83                 bit_cnt <= bit_cnt +1'b1;
     84                 
     85 end
     86 
     87 //rs232_tx
     88 always @(posedge sclk or negedge s_rst_n) begin
     89         if(s_rst_n == 1'b0)
     90                 rs232_tx <= 1'b1;
     91         else if(tx_flag == 1'b1)
     92                 case(bit_cnt)
     93                         0:        rs232_tx    <=    1'b0;
     94                         1:        rs232_tx    <=    tx_data_r[0];
     95                         2:        rs232_tx    <=    tx_data_r[1];
     96                         3:        rs232_tx    <=    tx_data_r[2];
     97                         4:        rs232_tx    <=    tx_data_r[3];
     98                         5:        rs232_tx    <=    tx_data_r[4];
     99                         6:        rs232_tx    <=    tx_data_r[5];
    100                         7:        rs232_tx    <=    tx_data_r[6];
    101                         8:        rs232_tx    <=    tx_data_r[7];
    102                         default:rs232_tx    <=    1'b1;
    103                 endcase
    104         else
    105                 rs232_tx    <=    1'b1;
    106 end
    107 
    108 endmodule

    3.下面附上接收部分的激励源码

     1 `timescale        1ns/1ns
     2 
     3 module tb_uart_tx;
     4 
     5 reg                sclk;
     6 reg                s_rst_n;
     7 reg                tx_trig;
     8 reg        [7:0]    tx_data;
     9 wire            rs232_tx;
    10 //----------------------------------difine system signales-----------------
    11 initial begin
    12         sclk    =    1;
    13         s_rst_n    =    0;
    14         #100
    15         s_rst_n    =    1;
    16 end
    17 
    18 always #10    sclk    =    ~sclk;
    19 
    20 //-----------------------------------------------------------------------
    21 initial begin
    22         tx_data <= 8'd0;
    23         tx_trig <= 0;
    24         
    25         #200
    26         tx_trig <= 1'b1;
    27         tx_data <= 8'h55;
    28         #20
    29         tx_trig <= 1'b0;
    30         
    31         #20000
    32         tx_trig <= 1'b1;
    33         tx_data <= 8'h78;
    34         #20
    35         tx_trig <= 1'b0;
    36         
    37         #20000
    38         tx_trig <= 1'b1;
    39         tx_data <= 8'h53;
    40         #20
    41         tx_trig <= 1'b0;
    42 
    43 end
    44 
    45 uart_tx        uart_tx_inst(
    46         //system signal
    47         .sclk                (sclk        ),
    48         .s_rst_n            (s_rst_n    ),
    49         //uart interface
    50         .rs232_tx            (rs232_tx    ),
    51         //other
    52         .tx_trig            (tx_trig    ),
    53         .tx_data            (tx_data    )
    54  );
    55 
    56 endmodule

    最后收发整合前面接收和发送部分都做好的话,这个就很简单了,但是这儿注意一个细节,把模块第一行的   ” `define SIM“给注释掉,这个是仿真用的,不然烧写到板卡不对

     1 module  uart_top(
     2     //system signals
     3     input            sclk        ,
     4     input            s_rst_n        ,
     5     //UART Interface
     6     input            rs232_rx    ,
     7     output  wire    rs232_tx
     8 );
     9 
    10 //-----------------------------------------------------------------\
    11 //***********Difine Parameter and Internal signals*****************
    12 //-----------------------------------------------------------------/
    13 wire    [7:0]        rx_data        ;
    14 wire                tx_trig        ;
    15 //==================================================================\
    16 //****************Main   Code *********************************
    17 //==================================================================/
    18 
    19 uart_rx        uart_rx_inst(
    20           //system signale
    21           .sclk                (sclk        ),            
    22           .s_rst_n            (s_rst_n    ),
    23           //uart interface
    24           .rs232_rx            (rs232_rx    ),
    25           //other
    26           .rx_data            (rx_data    ),
    27           .po_flag            (tx_trig    )
    28 
    29 );
    30 
    31 
    32 uart_tx        uart_tx_inst(                                
    33         //system signal                                  
    34         .sclk                (sclk        ),               
    35         .s_rst_n            (s_rst_n    ),               
    36         //uart interface                                 
    37         .rs232_tx            (rs232_tx    ),               
    38         //other                                          
    39         .tx_trig            (tx_trig    ),               
    40         .tx_data            (rx_data    )
    41  );
    42  
    43  
    44 endmodule
    uart_top

    uart学习到此为止了,已完成

  • 相关阅读:
    [android]Xutils具体介绍
    2015:WPS笔试-Android开发岗位
    BZOJ1355: [Baltic2009]Radio Transmission
    HDU 1421 搬寝室 (线性dp 贪心预处理)
    【独立开发人员er Cocos2d-x实战 009】Cocos2dx 菜单项CCMenu使用
    Error configuring application listener of
    SVN分支/合并原理及最佳实践
    SVN创建分支/合并分支/切换分支
    如何转载别人的文章
    让div自适应浏览器窗口居中显示
  • 原文地址:https://www.cnblogs.com/hqz68/p/9362964.html
Copyright © 2011-2022 走看看