<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                [TOC] > # 說明 由于fpga的系統時鐘可能會存在差異,之前搜索的一些串口模塊都是要經過修改才能更好的適配當前的項目,為了之后可以更快的實現項目串口的添加,在這里首先寫了一個**通用串口發送模塊**,根據系統的時鐘和需要的波特率,可自行設置。 > # 實現如下 ```verilog `timescale 1ns / 1ps // ******************************************************************** // FileName : uart_tx.v // Author :hpy // Email :yuan_hp@qq.com // Date :2020年12月06日 // Description :串口發送模塊,該模塊使用時必須先復位一次,否則無法工作 // 這是因為設計的時候使用了獨熱碼,狀態沒有全零的。 // -------------------------------------------------------------------- /*------------------------------------------- uart_tx #( .CLK_FREQ(12000000), //時鐘頻率 .BSP(9600) // 波特率 ) u1 ( .clk(clk), .rst_n(), .start() , // 發送觸發標志,上升沿有效 .sdata(), //要發送的數據 .tx(), //串口tx .busy(), //忙標志 .interrupt() //發送一個字節完畢的中斷信號,數據發送完畢后會產生一個clk的上升沿脈沖 ); --------------------------------------------*/ module uart_tx#( parameter CLK_FREQ = 12000000, //時鐘頻率 BSP = 9600 // 波特率 )( input clk, input rst_n, input start , // 發送觸發標志,上升沿有效 input [7:0]sdata, //要發送的數據 output reg tx, output reg busy, //忙標志 output interrupt //中斷信號 ); localparam CNT_MAX = CLK_FREQ / BSP; //根據時鐘頻率和波特率計算分頻值 localparam CNT_HALF = (CNT_MAX>>1) ; // //狀態機狀態 localparam IDEL = 6'b000001, PRE = 6'b000010, START = 6'b000100, TX_DATA = 6'b001000, TX_CHECK = 6'b010000, STOP = 6'b100000; //assign busy = (nst != IDEL ) ; always @(posedge clk) begin if( !rst_n ) busy <= 1'b0; else begin if(start_p && (cst==IDEL)) busy <= 1'b1; else if(nst == IDEL && bsp_clk) busy <= 1'b0; else busy <= busy; end end reg [5:0] cst,nst; /***************************************************** * 產生數據接發送完畢的中斷信號 *****************************************************/ reg busy_f; assign interrupt = (~busy) & busy_f; always@(posedge clk) begin if( !rst_n ) begin busy_f <= 1'b0; end else begin busy_f <= busy; end end function integer clog2 (input integer din); for( clog2 = 0; din; clog2=clog2 +1) din = din >>1; endfunction /***************************************************** * 檢測觸發信號上升沿 *****************************************************/ reg start_f; wire start_p; assign start_p = start & (~start_f); always@(posedge clk) begin if ( !rst_n ) begin start_f <= 1'b0; //start_p <= 1'b0; end else begin start_f <= start; //start_p <= start & (~start_f); end end reg [ clog2(CNT_MAX) - 1 : 0 ] cnt ; //計數器 /***************************************************** * 計數產生bps *****************************************************/ wire bsp_clk; assign bsp_clk = (cnt == CNT_HALF)? 1'B1 : 1'B0; always@(posedge clk ) begin if(!rst_n)begin cnt <= 'd0; end else begin if( cnt >= CNT_MAX - 1'b1 || ((cst == IDEL) && (start_p))) cnt <= 1'b0; else if(busy) cnt <= cnt + 1'b1; else cnt <= 'd0; end end /***************************************************** * 狀態機到下一狀態 *****************************************************/ always@(posedge clk) begin if(rst_n == 1'b0 )begin cst <= IDEL; end else begin if(cst == IDEL ) cst <= nst; else cst <= (bsp_clk) ? nst : cst; end end /***************************************************** * 狀態機下一狀態選擇 *****************************************************/ reg [ 3 : 0 ] tx_cnt; always@(*) begin nst = IDEL; case(cst) IDEL : nst = (start_p)? PRE : IDEL; PRE : nst = START; START : nst = TX_DATA; TX_DATA : nst = (tx_cnt >= 4'd8)? TX_CHECK : TX_DATA; TX_CHECK :nst = STOP; STOP: nst = IDEL; default:nst = IDEL; endcase end /***************************************************** * 狀態機輸出 *****************************************************/ reg [7:0]tx_buf; always@(posedge clk) begin if(rst_n == 1'b0 )begin tx <= 1'b1; tx_cnt <= 4'd0; end else begin case(nst) IDEL: begin tx <= 1'b1; end PRE: begin //由于時鐘的原因,計算得到的分頻值可能是小數,因此每次發數據之前都回復初始狀態,不讓誤差累積,等一拍可實現 tx <= 1'b1; tx_buf <= sdata; end START: if(bsp_clk) begin tx <= 1'b0; //tx_buf <= sdata; tx_cnt <= 4'd0 ; end TX_DATA: if(bsp_clk) begin tx_cnt <= tx_cnt + 1'b1; tx <= tx_buf[0]; tx_buf <= tx_buf >> 1 ; end TX_CHECK : if(bsp_clk)begin //奇偶校驗 tx <= 1'b1; tx_cnt <= 4'b0; end STOP: if(bsp_clk) begin //停止位 tx <= 1'b1; end default: tx <= 1'b1; endcase end end endmodule ``` > # 使用示例 ```verilog module top ( input clk, //輸入系統12MHz時鐘 output tx ); wire tflag; wire rst_n; //產生復位信號 Rst_sys #( .N(9000000) // 計數器最大值 ,取值要大于2 ) rst_u1( .clk(clk), .rst_n(rst_n) ); divide #( .N(12000000) ) u2 ( .clk(clk), .rst_n(rst_n), .clkout(tflag) ); reg [7:0] tx_data; wire tx_inte; always@(posedge clk) begin if(rst_n == 0) begin tx_data <=0; start <= 1'b0; end else if(!tx_busy && (start==1'b0))begin tx_data <= tx_data + 1; start <= 1'b1; end else begin start <= 1'b0; end end wire tx_busy; reg start; uart_tx #( .CLK_FREQ(12000000), //時鐘頻率 .BSP(9600) // 波特率 ) u1 ( .clk(clk), .rst_n(rst_n), .start(start) , // 發送觸發標志,上升沿有效 .sdata(tx_data), //要發送的數據 .tx(tx), //串口tx .interrupt(tx_inte), .busy(tx_busy) //忙標志 ); endmodule ``` > # 仿真波形 ![](https://img.kancloud.cn/10/b4/10b40988ebda875f1d9831779e86ae6d_1915x593.png)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看