博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
UART(串口通信)
阅读量:5877 次
发布时间:2019-06-19

本文共 8446 字,大约阅读时间需要 28 分钟。

     串口通信:是一种通用串行数据传输总线,可以实现全双工传输。是一种很常见的通信协议,此次写的程序在基于rs-232通信协议,以前在单片机里也用C51语言写过它的驱动程序,不过现在是用Verilog语言来写它的驱动程序,一种全新的思维模式来驱动它,和单片机大不一样。

   

//程序功能:在上位机(串口调试助手)上发送数据给下位机(PFGA),//下位机接收到数据后,控制LED灯亮灭,并且以原数据返回给上位机;module  uart_top        (         clk,         rst_n,         rs232_rx,         rs232_tx,         led              );input   clk;               //系统时钟,50MZH;input   rst_n;             //复位信号,低电平有效;input   rs232_rx;          //RS232数据接收信号;output  rs232_tx;          //RS232数据发送信号;output [3:0] led;          //LED 灯;wire      bps_start1, bps_start2;    //接收到数据后,波特率时钟信号启动位;  1:启动;0:停止;wire      clk_bps1,clk_bps2;         //波特率时钟; wire      rx_done ;                  //数据接收完毕信号,接收到数据期间始终为高电平;   wire[7:0] rx_data;                   //接收数据寄存器; speed_select   speed_rx              //波特率选择接收模块;                 (                   .clk(clk),                   .rst_n(rst_n),                   .bps_start(bps_start1),                   .clk_bps(clk_bps1)                                  );                    uart_rx     uart_rx                      //串口接收模块;               (                 .clk(clk),                 .rst_n(rst_n),                 .clk_bps(clk_bps1),                 .rs232_rx(rs232_rx),                 .bps_start(bps_start1),                 .rx_done(rx_done),                 .rx_data(rx_data),                 .led(led)                              );                 speed_select   speed_tx              // 波特率选择发送模块;                 (                   .clk(clk),                   .rst_n(rst_n),                   .bps_start(bps_start2),                   .clk_bps(clk_bps2)                                  );                  uart_tx      uart_tx               (                .clk(clk),                .rst_n(rst_n),                .clk_bps(clk_bps2),                .rx_done(rx_done),                .rx_data(rx_data),                .bps_start(bps_start2),                .rs232_tx(rs232_tx)                                             ); endmodule module speed_select             (              clk,              rst_n,              bps_start,              clk_bps                                    );input   clk;                   //系统时钟,50MZH;  input   rst_n;                 //复位信号,低电平有效;input   bps_start;             // 接收到数据后,波特率时钟信号启动位;  1:启动;0:停止;output  clk_bps;               //波特率时钟;wire   clk;wire   rst_n;wire   bps_start;wire   clk_bps;parameter  BPS  =5207;         //波特率为9600bps的分频计数值;  (10_0000_0000/9600)ns/20ns=5208parameter  BPS_2=2603;         //波特率为9600bps的一半,用于采样;reg [15:0] cnt;always @ (posedge clk or negedge rst_n)  begin        if(!rst_n)           cnt<=16'd0;        else if((!bps_start)||(cnt==BPS))           cnt<=16'd0;        else          cnt<=cnt+1'b1;                  end                   reg clk_bps_r;always @ (posedge clk or negedge rst_n)  begin        if(!rst_n)          clk_bps_r<=1'b0;        else if(cnt==BPS_2)            //clk_bps_r 高电平时为接收数据位的中间采样点,同时也作为发送数据的数据改变点;          clk_bps_r<=1'b1;        else          clk_bps_r<=1'b0;             end  assign clk_bps=clk_bps_r;                                  endmodule   module uart_rx            //接收模块,注:接收和发送是相对于下位机而言的;        (         clk,         rst_n,         clk_bps,         rs232_rx,         bps_start,         rx_done,         rx_data,         led                        );        input      clk;             //系统时钟:50MHZ;input      rst_n;           //复位信号,低电平有效;input      clk_bps;         //波特率时钟;input      rs232_rx;        //RS232数据接收信号;output      bps_start;      //接收到数据后,波特率时钟信号启动位;  1:启动;0:停止;output      rx_done;        //数据接收完毕信号,接收到数据期间始终为高电平;   output[7:0]  rx_data;        //接收数据寄存器;output[3:0]  led;reg rs232_rx0;always @ (posedge clk or negedge rst_n)  begin       if(!rst_n)         rs232_rx0<=1'b0;       else         rs232_rx0<=rs232_rx;    end  reg rs232_rx1;always @ (posedge clk or negedge rst_n)  begin       if(!rst_n)         rs232_rx1<=1'b0;       else         rs232_rx1<=rs232_rx0;    end    wire neg_rs232_rx;assign  neg_rs232_rx=rs232_rx1&(~rs232_rx0);  //当rs232_rx有1变到0时,说明起始位有效,开始启动串口接收;reg       bps_start_r;reg       rx_done;reg [3:0] num;always @ (posedge clk or negedge rst_n)  begin        if(!rst_n)          begin            bps_start_r<=1'bz;            rx_done<=1'b0;          end          else if(neg_rs232_rx)          begin              bps_start_r<=1'b1;   //启动串口准备接收数据;              rx_done<=1'b1;       //接收数据中断信号时能          end          else if(num==4'd12)        //接收完一帧数据;             begin                bps_start_r<=1'b0; //数据接收完毕,释放波特率启动信号;                rx_done<=1'b0;     //数据接收完毕,接收数据中断信号关闭;            end                end  assign  bps_start=bps_start_r;reg[7:0] rx_data_r;reg[7:0] rx_temp_data;always @ (posedge clk or negedge rst_n) begin       if(!rst_n)         begin           rx_data_r<=8'b0;           num<=4'd0;           rx_temp_data<=8'b0;         end         else if(rx_done)        //接收数据处理;          begin               if(clk_bps)     //读取并保存数据,接收数据为:一个起始位,8bit数据,1或2个结束位;                  begin                     num<=num+1'b1;                     case(num)                       4'h1   : rx_temp_data[0]<=rs232_rx;                       4'h2   : rx_temp_data[1]<=rs232_rx;                       4'h3   : rx_temp_data[2]<=rs232_rx;                       4'h4   : rx_temp_data[3]<=rs232_rx;                       4'h5   : rx_temp_data[4]<=rs232_rx;                       4'h6   : rx_temp_data[5]<=rs232_rx;                       4'h7   : rx_temp_data[6]<=rs232_rx;                       4'h8   : rx_temp_data[7]<=rs232_rx;                       default: ;                     endcase                   end                  else if(num==4'd12)                  begin                        num<=4'd0;                //接收到stop位后结束,num清0;                        rx_data_r<=rx_temp_data;  //把数据锁存到数据寄存器rx_data_r中                  end           end     end assign    rx_data=rx_data_r;assign    led=rx_data_r[3:0];    endmodule    module uart_tx          //发送模块,注:接收和发送是相对于下位机而言的      (       clk,       rst_n,       clk_bps,       rx_done,       rx_data,       bps_start,       rs232_tx              );input       clk;input       rst_n;input       clk_bps;input       rx_done;input[7:0]  rx_data;output bps_start;output rs232_tx;reg rx_done0;always @ (posedge clk or negedge rst_n)  begin        if(!rst_n)            rx_done0<=1'h0;        else           rx_done0<=rx_done;      endreg rx_done1;always @ (posedge clk or negedge rst_n)  begin        if(!rst_n)            rx_done1<=1'h0;        else           rx_done1<=rx_done0;      endwire  neg_rx_done;assign neg_rx_done=rx_done1&(~rx_done0);reg      bps_start_r;reg[7:0] tx_data;       //发送数据寄存器;reg      tx_en;         //发送使能信号;reg[3:0] num;always @(posedge clk or negedge rst_n)  begin        if(!rst_n)          begin              bps_start_r<=1'bz;              tx_en<=1'b0;              tx_data<=8'd0;          end        else if(neg_rx_done)          begin               bps_start_r<=1'b1;     //当rx_dnoe有1变为0时,表示接收数据已完毕,开始发送数据;               tx_data<=rx_data;               tx_en<=1'b1;          end        else if(num==4'd11)           begin               bps_start_r<=1'b0;               tx_en<=1'b0;                          end              end  assign   bps_start=bps_start_r;reg rs232_tx_r;always @ (posedge clk or negedge rst_n)  begin        if(!rst_n)          begin               rs232_tx_r<=1'b1;               num<=4'd0;          end        else if(tx_en)          begin              if(clk_bps)                 begin                     num<=num+1'b1;                     case(num)                       4'h0   :   rs232_tx_r<=1'h0;       //发送起始位;                       4'h1   :   rs232_tx_r<=tx_data[0];                       4'h2   :   rs232_tx_r<=tx_data[1];                       4'h3   :   rs232_tx_r<=tx_data[2];                       4'h4   :   rs232_tx_r<=tx_data[3];                       4'h5   :   rs232_tx_r<=tx_data[4];                       4'h6   :   rs232_tx_r<=tx_data[5];                       4'h7   :   rs232_tx_r<=tx_data[6];                       4'h8   :   rs232_tx_r<=tx_data[7];                       4'h9   :   rs232_tx_r<=1'b1;       //发送结束位;                      default:   rs232_tx_r<=1'b1;                    endcase                   end              else if(num==4'd11)                     num=4'd0;            end    end   assign rs232_tx=rs232_tx_r;endmodule

转载于:https://www.cnblogs.com/tphust/archive/2012/07/12/2588185.html

你可能感兴趣的文章
面试题28:字符串的排列
查看>>
GetParent( ) 和AfxGetMainWnd( )
查看>>
css important
查看>>
VUE -- 如何快速的写出一个Vue的icon组件?
查看>>
服务器的svnserver修改密码
查看>>
利用 fdisk进行分区
查看>>
WPF 实现窗体拖动
查看>>
来自维基百科程序员Brandon Harris
查看>>
NULL不是数值
查看>>
CentOS 5 全功能WWW服务器搭建全教程
查看>>
30个优秀的后台管理界面设计案例分享
查看>>
scala111
查看>>
模块化服务规范——OSGI
查看>>
劣质代码评析——猜数字问题(上)
查看>>
纸上谈兵: 栈 (stack)
查看>>
Windows phone8 基础篇(三) 常用控件开发
查看>>
Oracle学习笔记之五,Oracle 11g的PL/SQL入门
查看>>
大叔手记(3):Windows Silverlight/Phone7/Mango开发学习系列教程
查看>>
多功能表单填报系统V1.2.1-适用于在线报名系统、调查、数据收集等
查看>>
考拉消息中心消息盒子处理重构(策略模式)
查看>>