用狀態機實現串口多位元組數據發送

来源:https://www.cnblogs.com/Lclone/archive/2022/12/13/16980903.html
-Advertisement-
Play Games

這次設計一個多位元組(8-256位)且波特率可更改(通過修改例化模塊的參數)的串口發送模塊。 1、狀態機的設定 狀態機的設定有空閑、發送、和數據移位三個狀態,其中空閑狀態為等待多位元組發送的信號; 發送狀態為給8位串口發送模塊傳輸待發送8位的數據同時判斷是否發送完數據回到空閑狀態; 數據移位狀態為等到前 ...


這次設計一個多位元組(8-256位)且波特率可更改(通過修改例化模塊的參數)的串口發送模塊。

1、狀態機的設定

image

  • 狀態機的設定有空閑、發送、和數據移位三個狀態,其中空閑狀態為等待多位元組發送的信號;
  • 發送狀態為給8位串口發送模塊傳輸待發送8位的數據同時判斷是否發送完數據回到空閑狀態;
  • 數據移位狀態為等到前面8位位元組數據發送完後,將接下來待發送的8位數據移動到數據寄存器的低8位中。若數據在發送中則會進行等待;

2、需要的模塊

(1)8位串口發送模塊

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Engineer: Lclone
// 
// Create Date: 2022/12/10 00:21:40
// Design Name: uart_byte_tx
// Module Name: uart_byte_tx
// Project Name: uart_byte_tx
// Description: 8位串口發送模塊,波特率可通過參數設置。
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module uart_byte_tx
    #(
        parameter   TX_BAUD  = 9600,
        parameter   CLK_FQC  = 50_000_000,
        parameter   BAUD_CNT = CLK_FQC/TX_BAUD)
    (
        input       [7:0]   Data,
        input               Send_en,
        input               Clk,
        input               Rst_n,
        output  reg        Uart_Tx,
        output  reg        Tx_done
    );
    


    
    reg   [15:0]   baud_cnt;            
    reg   [ 3:0]   bit_cnt;
    reg            Send_en_r;
    reg            Send_en_rr;
    reg            Tx_flag;
    
    always @(posedge Clk) begin   
        Send_en_r <= Send_en;
        Send_en_rr <= Send_en_r;
    end
       
    always @(posedge Clk or negedge Rst_n) begin
        if(Rst_n == 0)
            Tx_flag <= 0;
        else if(~Send_en_rr & Send_en_r)
            Tx_flag <= 1'b1;
        else if(bit_cnt == 10 - 1 & baud_cnt == BAUD_CNT - 1)
            Tx_flag <= 1'b0;            
    end   
        
    always @(posedge Clk or negedge Rst_n) begin
        if(Rst_n == 0)
            baud_cnt <= 0;
        else if(baud_cnt == BAUD_CNT - 1)
            baud_cnt <= 0;
        else if(Tx_flag)
            baud_cnt <= baud_cnt + 1'b1;
    end
    
    always @(posedge Clk or negedge Rst_n) begin
        if(Rst_n == 0)    
            bit_cnt <= 0;
        else if(bit_cnt == 10 - 1 & baud_cnt == BAUD_CNT - 1)
            bit_cnt <= 0;
        else if(baud_cnt == BAUD_CNT - 1)
            bit_cnt <= bit_cnt + 1'b1;
     end   
    
    always @(posedge Clk or negedge Rst_n) begin
        if(Rst_n == 0)
            Uart_Tx <= 1'b1;
        else if(Tx_flag == 0)
            Uart_Tx <= 1'b1;
        else case(bit_cnt)
            0: Uart_Tx <= 1'b0;
            1: Uart_Tx <= Data[0];
            2: Uart_Tx <= Data[1];
            3: Uart_Tx <= Data[2];
            4: Uart_Tx <= Data[3];
            5: Uart_Tx <= Data[4];
            6: Uart_Tx <= Data[5];
            7: Uart_Tx <= Data[6];
            8: Uart_Tx <= Data[7];
            9: Uart_Tx <= 1'b1;
            default: Uart_Tx <= 1'b1;
         endcase
     end
    
     always @(posedge Clk or negedge Rst_n) begin
        if(Rst_n == 0)
            Tx_done <= 1'b0;
        else if(bit_cnt == 9 & baud_cnt == BAUD_CNT - 1)
            Tx_done <= 1'b1;
        else
            Tx_done <= 1'b0;            
     end
endmodule

3、設計的模塊代碼

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2022/12/12 19:14:03
// Design Name: uart_bytes_tx
// Module Name: uart_bytes_tx_3
// Project Name: uart_bytes_tx
// Target Devices: xc7z020clg400-1
// Tool Versions: 2018.3
// Description: 多位元組(8-256位)且波特率可更改(通過修改例化模塊的參數)的串口發送模塊。
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module uart_bytes_tx_3
    #(   parameter              DATA_WIDTH = 40,            //待發送的數據位寬
         parameter              ROUNDS = DATA_WIDTH/8)      //數據發送的次數(例化時不需要設置)
    (
         input                   Clk,                         //時鐘信號
         input                   Rst_n,                       //複位信號
         input [DATA_WIDTH-1:0]  Bytes_data,                  //多位元組數據埠
         input                   Send_bytes_en,               //多位元組發送使能
         output  reg            Tx_bytes_done,               //多位元組發送結束
         output  wire           Uart_Tx                      //串口發送埠
    );
    

    
    reg             [ 2:0]  state;                             //狀態寄存器
    reg   [DATA_WIDTH-1:0]  bytes_data_reg;                    //多位元組數據寄存器
    reg             [ 7:0]  data_reg;                          //待發送的8位數據寄存器
    reg                     send_en;                           //8位數據的發送使能
    wire                    tx_done;                           //8位數據的發送結束
    reg             [ 4:0]  rounds;                            //需要發送的次數
    
    uart_byte_tx                                                //串口8位發送模塊
  # (   .TX_BAUD            (9600),                              //波特率
        .CLK_FQC            (50_000_000))                        //模塊的時鐘頻率
    uart_byte_tx_inst
    (                          
        .Data               (data_reg),
        .Send_en            (send_en),
        .Clk                (Clk),
        .Rst_n              (Rst_n),
        .Uart_Tx            (Uart_Tx),
        .Tx_done            (tx_done)
        );
        
    always @(posedge Clk or negedge Rst_n) begin //數據寄存
        if(Rst_n == 0)
            bytes_data_reg <= 0;
        else if(Send_bytes_en)
            bytes_data_reg <= Bytes_data;
        else
            bytes_data_reg <= bytes_data_reg;
    end
    
    always @(posedge Clk or negedge Rst_n) begin   //狀態機
        if(Rst_n == 0) begin
            state <= 0;
            data_reg <= 0;
            send_en <= 0;
            Tx_bytes_done <= 0;
        end
        
        else case(state)
            0: begin
                if(Send_bytes_en)
                
                    state <= 3'b1;
                
                else begin
                    state <= 0;
                    data_reg <= 0;
                    send_en <= 0;
                    Tx_bytes_done <= 0;
                end
            end
            
            
            1: begin
                if(rounds == ROUNDS) begin
                    Tx_bytes_done <= 1'b1;
                    state <= 0;                    
                end
                
                else begin
                    data_reg <= bytes_data_reg[7:0];
                    send_en <= 1'b1;
                    state <= 3'd2;
                end
                
            end
            
            2: begin
                
                send_en <= 0;
                
                if(tx_done) begin
                    bytes_data_reg <= bytes_data_reg >> 8;
                    state <= 3'd1;
                end
                else
                    state <= 3'd2;
            end
            
        endcase
    end
    
    always @(posedge Clk or negedge Rst_n) begin //發送次數計數
        if(Rst_n == 0)
            rounds <= 0;
        else if(rounds == ROUNDS & state == 1)
            rounds <= 0;
        else if(tx_done)
            rounds <= rounds + 1'b1;    
    end
endmodule

4、模擬驗證

(1)模擬激勵

`timescale 1ns / 1ps

module uart_bytes_tx_tb();

    reg Clk;
    reg Rst_n;
    reg Send_bytes_en;
    reg [63:0]Bytes_data;
    wire Tx_bytes_done;
    wire Uart_Tx;
    
    uart_bytes_tx_3   
  # (   .DATA_WIDTH             (64))
    uart_bytes_tx_inst
    (
        .Clk                    (Clk),
        .Rst_n                  (Rst_n),
        .Bytes_data             (Bytes_data),
        .Send_bytes_en          (Send_bytes_en),
        .Tx_bytes_done          (Tx_bytes_done),
        .Uart_Tx                (Uart_Tx)
    );
    defparam uart_bytes_tx_inst.uart_byte_tx_inst.BAUD_CNT = 10;
    
    initial Clk <= 1'b1;
    always #10 Clk <= ~Clk;
    
    initial begin
        Rst_n <= 0;
        Bytes_data <= 0;
        Send_bytes_en <= 0;
        #200
        Rst_n <= 1'b1;
        #20
        Bytes_data <= 64'h0123456789abcdef;
        Send_bytes_en <= 1'b1;
        #20
        Send_bytes_en <= 0;
        #20000
        Bytes_data <= 64'hfedcba9876543210;
        Send_bytes_en <= 1'b1;
        #20
        Send_bytes_en <= 0;
        @(posedge Tx_bytes_done)
        #100
        $stop;
    end

endmodule

(2)模擬波形

第一輪發送:
image
兩輪發送:
image


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在實際開發中,大多數性能問題都可以追溯到糟糕的模型設計。官方也提供分享過文檔模型設計的進階技巧,這裡簡單翻譯記錄一下。 ...
  • SPL基於的理論基礎不再是關係代數,而是我們發明的離散數據集。在這個體系下有更多的數據類型和運算,就能寫出更多高性能演算法了。SPL是離散數據集的一種實現,封裝了許多現成的演算法。用Java和C++當然也能從頭來實現這個代數體系,因而都能寫出來高性能代碼 ...
  • 作者:崔雄華 1 Elasticsearch Head是什麼 ElasticSearch head就是一款能連接ElasticSearch搜索引擎,並提供可視化的操作頁面對ElasticSearch搜索引擎進行各種設置和數據檢索功能的管理插件,如在head插件頁面編寫RESTful介面風格的請求,就 ...
  • 當下,汽車行業已慢慢由曾經的增量市場逐步轉變為存量市場。更年輕的消費群體偏好、更精準智能的營銷投放策略和強勢入局的新能源汽車等因素都在推動著汽車行業的不斷發展。對於汽車廠商和垂域媒體來說,進行豐富的人群洞察與用戶分層,能挖掘更多用戶生命周期內的價值。 聯合建模,精準拉新 隨著電商與短視頻的快速發展, ...
  • 最近在摸魚時看到了一些博客園API文章,就想著摸魚時寫個APP練練手。 現階段實現了以下功能模塊: 博客瀏覽、評論 新聞瀏覽 快閃記憶體瀏覽、發佈、評論 博問瀏覽 用戶登錄 博問暫時只支持瀏覽,不支持回答提問等操作。 支持iOS、Android平臺。 截圖 淺色模式: 深色模式: API 開發前需要先到h ...
  • 案例介紹 歡迎來到我的小院,我是霍大俠,恭喜你今天又要進步一點點了!我們來用JavaScript編程實戰案例,做一個實時字元計數器。用戶在指定位置打字,程式實時顯示字元數量。 案例演示 在編輯框內輸入字元,下方實時記錄數字,且輸入有數量限制,輸入超出限制的字元後就無法再繼續輸入。 源碼學習 進入核心 ...
  • 微服務作為雲原生時代下一種開發軟體的架構和組織方法,通過將明確定義的功能分成更小的服務,並讓每個服務獨立迭代,增加了應用程式的靈活性,允許開發者根據需要更輕鬆地更改部分應用程式。同時每個微服務可以由單獨的團隊進行管理,使用適當的語言編寫,並根據需要進行獨立擴縮容。但微服務同樣也並非“銀彈”,在帶來如... ...
  • keepalived + nginx 實現高可用 本篇主要介紹一下 keepalived + nginx 來實現 對於nginx的高可用, 還是簡單的主備模式 1.概述 前面有瞭解keepalived 的主備的基本使用, 但是那種是針對宕機等情況 停止了keepalived 的進程實現的 vip的漂 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...