久久精品精选,精品九九视频,www久久只有这里有精品,亚洲熟女乱色综合一区
    分享

    基于verilog 的很基礎的RS232串口收發代碼

     獨孤瑯嬛 2014-04-24
    寫代碼,記筆記,防忘記,須牢記。
    寫串口的Verilog代碼關鍵是要搞明白RS232串口的通信協議,它并不像單片機,直接讀寫SBUF就可實現串口的收發功能,收發整個字節。而FPGA要一位一位的收發,因此必須了解RS232的數據格式。
    起始位:RS232約定一位起始位“0”。
    停止位:約定停止位為“1”。可選一位或兩位停止位。
    奇偶校驗位:可選。
    通過串口發送數據時,要嚴格遵守RS232的數據格式,先發送起始位,然后是數據,最后是停止位(無奇偶校驗的情況)。
    通過串口接收數據時,若接收端無數據輸入,會一直處于高電平,若開始接收數據,會首先收到來自串口的起始位“0”,然后是要接收的數據,最后為停止位(無奇偶校驗的情況)。所以對于接收模塊,可如此設計,FPGA一直檢測接收端是否有下降沿到來,直到檢測到下降沿,才開始接收數據。
    波特率設置的重要性不言而喻,毋庸贅述。
    此設計為最基礎的串口收發代碼,控制邏輯簡單,適合編寫第一次編寫串口代碼的朋友。
    此設計收發的數據格式為1位起始位,1位停止位,無奇偶校驗位,8位數據位。波特率為19200,代碼中可隨意更改。
    具體Verilog代碼如下:
    頂層模塊
    `timescale 1ns / 1ps
    ////////////////////////////////////////////////////////////////////////////////
    // Company : 杭州電子科技大學
    // Engineer : 曉曉川
    // Create Date : 2012.08.26
    // Design Name : serial_test
    // Module Name : serial_test
    // Project Name: serial_test
    // Target Device: CycloneII EP2C5T144C8 
    // Tool versions: Quartus II 11.0
    // Revision : V1.0
    // Description : 一個極為簡單的串口收發工程,適于串口收發的入門。只能收發單個字節,沒有
    //                奇偶校驗位。
    //     工作流程為:串口發送數據給FPGA,以LED燈的亮滅直觀顯示接收到數據,按下
    //                         相應按鍵并彈起后,FPGA又將接收到的串口數據發送出去。
    // Additional Comments :  
    // 
    ////////////////////////////////////////////////////////////////////////////////
    module serial_test(clk,rst_n,ena,txd,rxd,data);
    input clk;         //系統輸入時鐘
    input rst_n;       //異步復位
    input ena;         //FPGA發送使能,即按鍵輸入端
    input rxd;         //FPGA接收端
    output txd;        //FPGA發送端
    output [7:0] data; //至LED顯示的數據
    wire   [7:0] data;
    wire   txd;
    wire   clk2;       //PLL輸出時鐘
    wire   clk_baud;   //波特率時鐘
    PLL  u1(.inclk0(clk),.c0(clk2));                                               //PLL輸出低頻時鐘
    clk_baud_gen  u2(.clk(clk2),.rst_n(rst_n),.clk_baud(clk_baud));                //產生波特率時鐘
    serial_txd  u3(.clk(clk_baud),.rst_n(rst_n),.ena(ena),.data(data),.txd(txd));  //FPGA發送模塊
    serial_rxd  u4(.clk(clk_baud),.rst_n(rst_n),.rxd(rxd),.data(data));            //FPGA接收模塊
    endmodule 
    接收模塊
    //此模塊是FPGA控制模塊從串口接收數據,不接收起始位“0”和停止位“1”
    //在接收端,若串口沒有數據發出,則一直處于高電平,有數據發出時,先發送起始位“0”,即如果
    //接收端出現由高到低的跳變,說明串口有數據發出,應開始接收
    module  serial_rxd(rst_n,clk,rxd,data);
    input   rst_n;          //全局復位
    input   clk;            //接收時鐘
    input   rxd;            //FPGA接收串口數據的接收端
    output  [7:0] data;     //FPGA接收的來自串口的數據,輸出至LED顯示

    reg     [3:0] cnt;      //接收數據計數器
    reg     rec_reg1;       //起始位檢測寄存器1
    reg     rec_reg2;       //起始位檢測寄存器2
    reg     [7:0] data;     //FPGA接收的數據
    always @(posedge clk or negedge rst_n)
          if(!rst_n)        
    begin
    rec_reg1<=1'b1;     //起始位檢測寄存器置1,
    rec_reg2<=1'b1;     //處于等待接收狀態
    data<=8'hzz;        //輸出復位,LED全滅
    end
    else if(rec_reg1&&rec_reg2)
    begin
    rec_reg1<=rxd;      //rec_reg1寄存rxd當前周期的值
    rec_reg2<=rec_reg1; //rec_reg2寄存rxd前一周期的值
    end
    else if(!rec_reg1&&rec_reg2)   //檢測rxd下降沿,也即是否有低電平到來
    case (cnt)
          4'd0:data[0]<=rxd;  //接收第一位數據
    4'd1:data[1]<=rxd;  //接收第二位數據
    4'd2:data[2]<=rxd;  //接收第三位數據
    4'd3:data[3]<=rxd;  //接收第四位數據
    4'd4:data[4]<=rxd;  //接收第五位數據
    4'd5:data[5]<=rxd;  //接收第六位數據
    4'd6:data[6]<=rxd;  //接收第七位數據
    4'd7:begin
        data[7]<=rxd;  //接收第八位數據
        rec_reg1<=1'b1;//數據接收完畢,起始位檢測寄存器復位, 
        rec_reg2<=1'b1;//以準備下次接收
        end
          default:begin
           data<=8'hzz;
              rec_reg1<=1'b1; 
           rec_reg2<=1'b1;
           end
    endcase
    always @(posedge clk or negedge rst_n)
          if(!rst_n)
    cnt<=4'd0;          //復位,接收數據技術器清零
    else if(!rec_reg1&&rec_reg2)
    cnt<=(cnt<4'd7)?cnt+4'd1:4'd0; //檢測到起始位后,接收數據計數器啟動
    endmodule 
    發送模塊
    //此模塊的作用是FPGA控制模塊向串口發送數據,起始位為“0”,停止位為“1”
    //延時電路的設計思想為按鍵按下彈起之后開始計時,時長為1010/11920秒
    //延時去抖結束后給出發送標志位,直至FPGA向串口發送完畢
    module  serial_txd(rst_n,clk,ena,data,txd);
    input    rst_n;           //全局復位
    input    clk;             //串口發送時鐘
    input    ena;             //串口發送使能輸入端,即按鍵輸入端
    input    [7:0] data;      //FPGA向串口發送的數據
    output   txd;             //FPGA向串口發送數據的發送端

    reg      txd;             
    reg      [3:0] cnt;       //發送數據計數器
    reg      [9:0] cnt_delay; //延時去抖計數器,延時時間為1010/11920秒
    reg      ena_reg1;        //按鍵狀態寄存器1
    reg      ena_reg2;        //按鍵狀態寄存器2
    wire     tx_flag;         //發送標志位,高電平表示正在發送串口數據
    always @(posedge clk or negedge rst_n)
          if(!rst_n)
    begin
    ena_reg1<=1'b1;
    ena_reg2<=1'b1;
    cnt_delay<=10'd0;
    end
    else if(ena_reg1&!ena_reg2)          //檢測按鍵按下后彈起,即ena的上升沿(因為無動作時連接按鍵的pin處于高電平)
    case (cnt_delay)            
    10'd1011:begin
           cnt_delay<=10'd0;            //延時去抖結束,計數器清零
     ena_reg1<=1'b1;              //按鍵狀態寄存器置1,等待下次ena上升沿的到來
           ena_reg2<=1'b1;
     end
    default:cnt_delay<=cnt_delay+10'd1;  //檢測到上升沿,延時去抖計數器啟動
    endcase
    else
    begin
    ena_reg1<=ena;                       //ena_reg1寄存ena當前周期的狀態
    ena_reg2<=ena_reg1;                  //ena_reg2寄存ena前一周期的狀態
    end
    assign  tx_flag=((cnt_delay>=10'd1000)&&   //延時去抖結束后給出發送忙標志,持續10
                     (cnt_delay<=10'd1010));   //個周期,以等待FPGA向串口發送完畢
    always @(posedge clk or negedge rst_n)
          if(!rst_n)
      cnt<=4'd0;                        //串口發送計數器復位
    else if(!tx_flag)                    
      cnt<=4'd0;                        //若沒有檢測到串口發送標志位,則計數器等待
          else
      cnt<=(cnt>=4'd10)?4'd11:cnt+4'd1; //檢測到串口發送標志位,啟動計數器
    always @(posedge clk or negedge rst_n)
          if(!rst_n)
       txd<=1'bz;              //發送端復位,高阻態        
    else 
          case (cnt)
    4'd0:txd<=1'bz;         
    4'd1:txd<=1'b0;         //發送起始位
    4'd2:txd<=data[0];      //發送第一位
    4'd3:txd<=data[1];      //發送第二位
    4'd4:txd<=data[2];      //發送第三位
    4'd5:txd<=data[3];      //發送第四位
    4'd6:txd<=data[4];      //發送第五位
    4'd7:txd<=data[5];      //發送第六位
    4'd8:txd<=data[6];      //發送第七位
    4'd9:txd<=data[7];      //發送第八位
    4'd10:txd<=1'b1;        //發送停止位
    default:txd<=1'bz;
    endcase
    endmodule 
    波特率產生模塊(此模塊的輸入時鐘來自PLL,頻率為12MHz,PLL模塊為宏功能函數)
    //此模塊為波特率生成模塊,修改BAUDRATE的值可改變波特率
    //串口波特率時鐘的高電平僅僅持續一個clk周期
    module   clk_baud_gen(clk,rst_n,clk_baud);
    input  clk;       //波特率基準時鐘,此時鐘來自PLL
    input  rst_n;     //全局復位
    output clk_baud;  //串口波特率時鐘
    wire   clk_baud;  
    reg    [9:0] cnt; //波特率時鐘計數器

    parameter  BAUDRATE=10'd625; 

    always @(posedge clk or negedge rst_n)
          if(!rst_n)
      cnt<=10'd0;
    else 
      cnt<=(cnt==BAUDRATE-10'd2)?10'd0:cnt+1'b1;  //波特率時鐘計數器啟動
    assign   clk_baud=(cnt==BAUDRATE-10'd2);
    endmodule 

      本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發布,不代表本站觀點。請注意甄別內容中的聯系方式、誘導購買等信息,謹防詐騙。如發現有害或侵權內容,請點擊一鍵舉報。
      轉藏 分享 獻花(0

      0條評論

      發表

      請遵守用戶 評論公約

      類似文章 更多

      主站蜘蛛池模板: 亚洲欧美综合人成在线| 日韩av片无码一区二区不卡| 又爽又黄又无遮挡的激情视频免费 | 噜噜噜噜私人影院| 国产日产欧产美韩系列麻豆| 波多野结衣中文字幕一区二区三区 | 国产69囗曝吞精在线视频| 人妻AV中文字幕一区二区三区 | 重口SM一区二区三区视频| 免费无码黄十八禁网站| 亚洲欧美成人综合久久久| 欧美日韩精品一区二区视频| 日韩精品国产二区三区| 又大又粗又硬放不进去了| 无码熟妇人妻AV在线电影| 成人3D动漫一区二区三区| 乱公和我做爽死我视频| 亚洲av免费成人在线| 成人无码影片精品久久久| 少妇高潮喷水正在播放| 亚洲日韩久久综合中文字幕| 亚洲男人第一无码av网站| 欧美孕妇变态孕交粗暴| 深夜福利资源在线观看| AV免费网址在线观看| 69天堂人成无码免费视频 | 377P欧洲日本亚洲大胆| 好深好爽办公室做视频| 国产不卡精品视频男人的天堂| 亚洲制服丝袜系列AV无码| 1000部拍拍拍18勿入免费视频 | 老色鬼久久亚洲AV综合| 国产中文三级全黄| 日产国产一区二区不卡| 亚洲国产成人精品女人久久久| 成人午夜看黄在线尤物成人| 中文字幕人妻精品在线| 好男人官网资源在线观看| 无码人妻丰满熟妇区毛片18| 日韩精品一区二区三区影院| 国产精品电影久久久久电影网 |