串口接收模块设计与项目实例学习

文章描述了一个在FPGA中实现的UART串口数据接收模块,该模块能抵抗电磁干扰,通过多次采样判断数据位,并结合波特率设置进行数据解析。接收的数据随后被用于控制LED灯的状态,实现了用户通过串口发送指令来动态改变LED的亮灭模式。
摘要由CSDN通过智能技术生成

一、模块设计

 在实际工业应用中,现场往往有非常强的电磁干扰,只采样一次就作为该数据的电平状态是不可靠的,很有可能恰好采集到被干扰的信号而导致结果出错。

1、基本原理:采样

2、技巧:一位数据采多次,统计其电平高低情况,出现次数多的就是该位数据的值。

              采样八次,若出现高电平的次数为0、1、2、3则该为数据为低电平,

              若出现高电平的次数为    4、5、6、7,则该为数据为高电平。

3、起始位检测:通过边沿检测电路

因此,将每位数据分为16份,采每位数据的5—11段,并根据高低电平出现的次数判断该位数据的值。

设计输入

//在实际工业应用中,现场往往有非常强的电磁干扰,只采样一次就作为该数据的电平状态是不可靠的,很有可能恰好采集到被干扰的信号而导致结果出错;
//因此,将每位数据分为16份,采每位数据的5—11段,并根据高低电平出现的次数判断该位数据的值。


module uart_byte_rx(
    Clk       ,
    Reset_n   ,
    Baud_Set  ,//波特率选择信号,需要和数据发送波特率一致
    uart_rx   ,//输入串行数据
    Data      ,//将接收到的数据传送出去,并行输出
    Rx_Done    //接收完成信号
    );
    input Clk           ;
    input Reset_n       ;
    input [2:0]Baud_Set ;
    input uart_rx       ;
    output reg [7:0]Data    ;
    output reg Rx_Done      ;
    
    //定义两个寄存器,实现边缘检测电路
    reg [1:0]uart_rx_r;   //先将数据进行存储,两个D触发器
    always@(posedge Clk)begin
        uart_rx_r[0] <= uart_rx;         
        uart_rx_r[1] <= uart_rx_r[0];
    end

    //检测边沿
    wire pedge_uart_rx;     //上升沿
   // assign pedge_uart_rx = ((uart_rx_r[1] = 0)&&(uart_rx_r[0] == 1));
    assign pedge_uart_rx = (uart_rx_r == 2'b01);
    wire nedge_uart_rx;    //下降沿
   // assign pedge_uart_rx = ((uart_rx_r[1] = 1)&&(uart_rx_r[0] == 0));
    assign nedge_uart_rx = (uart_rx_r == 2'b10);
    
    //波特率设置,在采样时要把每位数据发送的时间分为16段进行采样
    reg [8:0] Bps_DR;
    always@(*)
        case(Baud_Set)
            0:Bps_DR = 1000000000/9600/16/20 - 1;
            1:Bps_DR = 1000000000/19200/16/20 - 1;
            2:Bps_DR = 1000000000/38400/16/20 - 1;
            3:Bps_DR = 1000000000/57600/16/20 - 1;
            4:Bps_DR = 1000000000/115200/16/20 - 1;
            default:Bps_DR = 1000000000/9600/16/20 - 1;
        endcase
        
        //产生bps_clk,每一小段,取最中间的值 
        wire bps_clk_16x;
        reg [8:0]div_cnt;
        assign bps_clk_16x = (div_cnt == Bps_DR / 2);
        
        //需要一个分频计数器  
        
        reg RX_EN;    //数据接收的时候,RX_EN处于高电平
        reg [2:0]sta_bit;
        always@(posedge Clk or negedge Reset_n)
        if(!Reset_n)
            RX_EN <= 0;
        else if(nedge_uart_rx)       //当检测到下降沿,即下一位为发送起始位,开始接收数据
            RX_EN <= 1;
        else if(Rx_Done || (sta_bit >= 4))  // 当Rx_Done拉高,或者检测到发送起始位并不是真正的起始位
            RX_EN <= 0;
            
        //reg [8:0]div_cnt;  分频计数器,计数一个波特率
        always@(posedge Clk or negedge Reset_n)
        if(!Reset_n)
            div_cnt <= 0;
        else if(RX_EN)begin
            if(div_cnt == Bps_DR)
                div_cnt <= 0;
             else
                div_cnt <= div_cnt + 1'b1;
        end
        else    
            div_cnt <= 0;

        //计数器,传送一八位数据需要十个时间段,每个时间段分16小段,计数16*10 = 160 次,
        //每当bps_clk_16x到来一次,计数器加一
        reg [7:0]bps_cnt;
        always@(posedge Clk or negedge Reset_n)
        if(!Reset_n)
            bps_cnt <= 0;
         else if(RX_EN)begin
             if(bps_clk_16x)begin
                if(bps_cnt == 160)
                    bps_cnt <= 0;
                else
                     bps_cnt <= bps_cnt + 1'b1;
              end
              else
                bps_cnt <= bps_cnt;
        end
        else
            bps_cnt <= 0;
            
            
        //接收数据,每位数据采样八次,将八次采样值进行累加,判断累加后的值r_data;
        //若值为0-3 则该位数据为0,若值为4-7 则该位数据为1。
        
        //reg 位宽width name number
        reg[2:0]r_data[7:0];  //表示定义了8个3位的寄存器r_data;定义八个是为了和要接收的八位数据对应,后边再分别定义起始位和结束位
       // r_data[0][1]     表示第0个r_data中的第一位数据      
        //reg [2:0]sta_bit;
        reg [2:0]sto_bit;
        
        //接收数据
        always@(posedge Clk or negedge Reset_n)
        if(!Reset_n)begin
            sta_bit <= 0;
            sto_bit <= 0;
            r_data[0] <= 0;
            r_data[1] <= 0;
            r_data[2] <= 0;
            r_data[3] <= 0;
            r_data[4] <= 0;
            r_data[5] <= 0;
            r_data[6] <= 0;
            r_data[7] <= 0;
        end
        else if(bps_clk_16x)begin
            case(bps_cnt)
                0:begin
                    sta_bit <= 0;
                    sto_bit <= 0;
                    r_data[0] <= 0;
                    r_data[1] <= 0;
                    r_data[2] <= 0;
                    r_data[3] <= 0;
                    r_data[4] <= 0;
                    r_data[5] <= 0;
                    r_data[6] <= 0;
                    r_data[7] <= 0;
                end
                5,6,7,8,9,10,11:sta_bit <= sta_bit + uart_rx;
                21,22,23,24,25,26,27:r_data[0] <= r_data[0] + uart_rx;
                37,38,39,40,41,42,43:r_data[1] <= r_data[1] + uart_rx;
                53,54,55,56,57,58,59:r_data[2] <= r_data[2] + uart_rx;
                69,70,71,72,73,74,75:r_data[3] <= r_data[3] + uart_rx;
                85,86,87,88,89,90,91:r_data[4] <= r_data[4] + uart_rx;
                101,102,103,104,105,106,107:r_data[5] <= r_data[5] + uart_rx;
                117,118,119,120,121,122,123:r_data[6] <= r_data[6] + uart_rx;
                133,134,135,136,137,138,139:r_data[7] <= r_data[7] + uart_rx;
                149,150,151,152,153,154,155:sto_bit <= sto_bit + uart_rx;
                default:;
            endcase
         end
        
        //输出结果,给到Data
        always@(posedge Clk or negedge Reset_n)
        if(!Reset_n)
            Data <= 0;
         else if((bps_cnt == 159 ))begin
            Data[0] <= (r_data[0] >= 4)? 1'b1:1'b0;
            Data[1] <= (r_data[1] >= 4)? 1'b1:1'b0;
            Data[2] <= (r_data[2] >= 4)? 1'b1:1'b0;
            Data[3] <= (r_data[3] >= 4)? 1'b1:1'b0;
            Data[4] <= (r_data[4] >= 4)? 1'b1:1'b0;
            Data[5] <= (r_data[5] >= 4)? 1'b1:1'b0;
            Data[6] <= (r_data[6] >= 4)? 1'b1:1'b0;
            Data[7] <= (r_data[7] >= 4)? 1'b1:1'b0;
         end
        
//        0:3'b000;
//        1:3'b001;
//        2:3'b010;
//        3:3'b011;
        
//        4:3'b100;
//        5:3'b101;
//        6:3'b110;
//        7:3'b110;
//0-3 的第二位都为0,4-7的第二位都为1
    
//        always@(posedge Clk or negedge Reset_n)
//        if(!Reset_n)
//            Data <= 0;
//         else if((bps_cnt == 159 ))begin
//            Data[0] <= r_data[0][2] ;  //等价于 Data[0] <= (r_data[0] >= 4)? 1'b1:1'b0;
//            Data[1] <= r_data[1][2] ;  //将r_data[1] 第二位的值赋给Data[1]
//            Data[2] <= r_data[2][2] ;
//            Data[3] <= r_data[3][2] ;
//            Data[4] <= r_data[4][2] ;
//            Data[5] <= r_data[5][2] ;
//            Data[6] <= r_data[6][2] ;
//            Data[7] <= r_data[7][2] ;
//        end
        
        //给Rx_Done值
        always@(posedge Clk or negedge Reset_n)
        if(!Reset_n)
            Rx_Done <= 0;
         else if((div_cnt == Bps_DR) && (bps_cnt == 160 )) //脉冲到来,并且计数到最后一位数159时
            Rx_Done <= 1;
         else
            Rx_Done <= 0;
   
endmodule

功能仿真代码

`timescale 1ns / 1ps
module uart_byte_rx_tb();
    
    reg Clk           ;
    reg Reset_n       ;
    wire [2:0]Baud_Set ;
    reg uart_rx       ;
    wire [7:0]Data         ;
    wire Rx_Done      ;
    
    assign Baud_Set = 4;
    
    uart_byte_rx uart_byte_rx (
    Clk       ,
    Reset_n   ,
    Baud_Set  ,
    uart_rx   ,
    Data      ,
    Rx_Done    
    );
    
    initial Clk = 1;
    always #10 Clk = ~Clk;
    
    initial begin
        Reset_n  = 0   ;
        uart_rx  = 1   ;
        #201;
        Reset_n = 1;
        #200;
        uart_tx_byte (8'h5a)   ;
        #90000;
        uart_tx_byte (8'ha5)   ;
        #90000;
        uart_tx_byte (8'h86)   ;
        #90000;
        $stop;
    end
  
    task uart_tx_byte;
        input [7:0]tx_data;
        begin
            uart_rx = 1;
            #20;
            uart_rx = 0; //起始位
            #8680;   //115200的波特率发送数据,每位保持时间为8680ns
            uart_rx = tx_data[0];
            #8680;
            uart_rx = tx_data[1];
            #8680;
            uart_rx = tx_data[2];
            #8680;
            uart_rx = tx_data[3];
            #8680;
            uart_rx = tx_data[4];
            #8680;
            uart_rx = tx_data[5];
            #8680;
            uart_rx = tx_data[6];
            #8680;
            uart_rx = tx_data[7];
            #8680;
            uart_rx = 1; //结束位
            #8680;
        end
    endtask

endmodule

功能仿真结果

 二、项目实例 使用串口控制LED的工作状态

使用串口发送指令到FPGA开发板,控制led灯:

让LED灯按照指定的亮灭模式亮灭,亮灭模式未知,由用户随机指定。8个变化状态为一个循环,每个变化状态的时间值可以根据不同的应用场景选择。

 

 使用五个比特数据,分别对应Time值和Ctrl值。制定一个发送协议,使用移位寄存器实现该功能。

设计输入 

顶层模块

`timescale 1ns / 1ps

module uart_rx_ctrl_led(
    Clk     ,
    Reset_n ,
    uart_rx ,
    LED
    );
    
    input Clk      ;
    input Reset_n  ;
    input uart_rx  ;
    output LED     ; 

    wire [7:0]ctrl;
    wire [31:0]time_set;
    wire [7:0]rx_data;
    wire rx_done;
    wire Led;

    counter_led_4 counter_led_4(
        .Clk     (Clk)   ,
        .Reset_n (Reset_n)   ,
        .Ctrl    (ctrl)   ,
        .Time    (time_set)   ,
        .Led     (Led)
);

    uart_byte_rx uart_byte_rx(
        .Clk      (Clk) ,
        .Reset_n  (Reset_n) ,
        .Baud_Set (4) ,
        .uart_rx  (uart_rx) ,
        .Data     (rx_data) ,
        .Rx_Done  (rx_done)  
        );
    uart_cmd uart_cmd (
        .Clk       (Clk) ,
        .Reset_n   (Reset_n) ,
        .rx_data   (rx_data) ,
        .rx_done   (rx_done) ,
        .ctrl      (ctrl) ,
        .time_set  (time_set)
        );

endmodule

子模块——控制LED

//让LED灯按照指定的亮灭模式亮灭,亮灭模式未知,由用户随机指定。
//8个变化状态为一个循环,每个变化状态的时间值可以根据不同的应用场景选择。
//化零为整,设置八个相同时间段,第一个计数器计数每个时间段,位数和每个时间段时间相匹配,Time的值为计数次数,即代表每个时间段是时间长短,计数器位数和Time位数一致;
//第二个计数器计数八个时间段,共8次,需要三位的计数器;
//根据计数器2的值,共八个值,通过八位的Ctrl分别控制八个信号的亮灭状态。

module counter_led_4(
    Clk,
    Reset_n,
    Ctrl,
    Time,
    Led
);

    input Clk;
    input Reset_n;
    input [7:0]Ctrl;
    input [31:0]Time;
    output reg [7:0]Led;

    reg [31:0]counter;
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        counter <= #1 0;
    else if (counter >= Time - 1)
        counter <= #1 0;
    else
        counter <= #1 counter + 1'b1;
        //刚上电的时候,Timne为0,Time - 1 = 32'hFFFFFFFFFFFFFFFF,counter不满足这个值,所以它就一直自加直到加满才会清零,溢出后,进入下一个自加循环,、
        //判断counter == Time - 1,
        //当实际板级运行的时候,当Time值(25000000)更新时,counter的值已大于该值,只有等其加满溢出后,才能进入下一个循环正常计数
        //所以设置counter >= Time - 1,counter值过大时,清零
        
    reg[2:0]counter2;
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        counter2 <= #1 0;
    else if (counter >= Time - 1)
        counter2 <= #1 counter2 + 1'b1;
        
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        Led <= #1 0;
     else case(counter2)
        0:Led <= #1 Ctrl[0];
        1:Led <= #1 Ctrl[1];
        2:Led <= #1 Ctrl[2];
        3:Led <= #1 Ctrl[3];
        4:Led <= #1 Ctrl[4];
        5:Led <= #1 Ctrl[5];
        6:Led <= #1 Ctrl[6];
        7:Led <= #1 Ctrl[7];
        default:Led <= #1 Led;
     endcase
endmodule

子模块——发送数据

`timescale 1ns / 1ps

module uart_byte_rx(
    Clk       ,
    Reset_n   ,
    Baud_Set  ,//波特率选择信号,需要和数据发送波特率一致
    uart_rx   ,//输入串行数据
    Data      ,//将接收到的数据传送出去,并行输出
    Rx_Done    //接收完成信号
    );
    input Clk           ;
    input Reset_n       ;
    input [2:0]Baud_Set ;
    input uart_rx       ;
    output reg [7:0]Data    ;
    output reg Rx_Done      ;
    
    //定义两个寄存器,实现边缘检测电路
    reg [1:0]uart_rx_r;   //先将数据进行存储,两个D触发器
    always@(posedge Clk)begin
        uart_rx_r[0] <= #1 uart_rx;         
        uart_rx_r[1] <= #1 uart_rx_r[0];
    end

    //检测边沿
    wire pedge_uart_rx;     //上升沿
   // assign pedge_uart_rx = ((uart_rx_r[1] = 0)&&(uart_rx_r[0] == 1));
    assign pedge_uart_rx = (uart_rx_r == 2'b01);
    wire nedge_uart_rx;    //下降沿
   // assign pedge_uart_rx = ((uart_rx_r[1] = 1)&&(uart_rx_r[0] == 0));
    assign nedge_uart_rx = (uart_rx_r == 2'b10);
    
    //波特率设置,在采样时要把每位数据发送的时间分为16段进行采样
    reg [8:0] Bps_DR;
    always@(*)
        case(Baud_Set)
            0:Bps_DR = 1000000000/9600/16/20 - 1;
            1:Bps_DR = 1000000000/19200/16/20 - 1;
            2:Bps_DR = 1000000000/38400/16/20 - 1;
            3:Bps_DR = 1000000000/57600/16/20 - 1;
            4:Bps_DR = 1000000000/115200/16/20 - 1;
            default:Bps_DR = 1000000000/9600/16/20 - 1;
        endcase
        
        //产生bps_clk,每一小段,取最中间的值 
        wire bps_clk_16x;
        reg [8:0]div_cnt;
        assign bps_clk_16x = (div_cnt == Bps_DR / 2);
        
        //需要一个分频计数器  
        
        reg RX_EN;    //数据接收的时候,RX_EN处于高电平
        reg [2:0]sta_bit;
        always@(posedge Clk or negedge Reset_n)
        if(!Reset_n)
            RX_EN <= #1 0;
        else if(nedge_uart_rx)       //当检测到下降沿,即下一位为发送起始位,开始接收数据
            RX_EN <= #1 1;
        else if(Rx_Done || (sta_bit >= 4))  // 当Rx_Done拉高,或者检测到发送起始位并不是真正的起始位
            RX_EN <= #1 0;
            
        //reg [8:0]div_cnt;  分频计数器,计数一个波特率
        always@(posedge Clk or negedge Reset_n)
        if(!Reset_n)
            div_cnt <= #1 0;
        else if(RX_EN)begin
            if(div_cnt == Bps_DR)
                div_cnt <= #1 0;
             else
                div_cnt <= #1 div_cnt + 1'b1;
        end
        else    
            div_cnt <= #1 0;

        //计数器,传送一八位数据需要十个时间段,每个时间段分16小段,计数16*10 = 160 次,
        //每当bps_clk_16x到来一次,计数器加一
        reg [7:0]bps_cnt;
        always@(posedge Clk or negedge Reset_n)
        if(!Reset_n)
            bps_cnt <= #1 0;
         else if(RX_EN)begin
             if(bps_clk_16x)begin
                if(bps_cnt == 160)
                    bps_cnt <= #1 0;
                else
                     bps_cnt <= #1 bps_cnt + 1'b1;
              end
              else
                bps_cnt <= #1 bps_cnt;
        end
        else
            bps_cnt <= #1 0;
            
            
        //接收数据,每位数据采样八次,将八次采样值进行累加,判断累加后的值r_data;
        //若值为0-3 则该位数据为0,若值为4-7 则该位数据为1。
        
        //reg 位宽width name number
        reg[2:0]r_data[7:0];  //表示定义了8个3位的寄存器r_data;定义八个是为了和要接收的八位数据对应,后边再分别定义起始位和结束位
       // r_data[0][1]     表示第0个r_data中的第一位数据      
        //reg [2:0]sta_bit;
        reg [2:0]sto_bit;
        
        //接收数据
        always@(posedge Clk or negedge Reset_n)
        if(!Reset_n)begin
            sta_bit <= #1 0;
            sto_bit <= #1 0;
            r_data[0] <= #1 0;
            r_data[1] <= #1 0;
            r_data[2] <= #1 0;
            r_data[3] <= #1 0;
            r_data[4] <= #1 0;
            r_data[5] <= #1 0;
            r_data[6] <= #1 0;
            r_data[7] <= #1 0;
        end
        else if(bps_clk_16x)begin
            case(bps_cnt)
                0:begin
                    sta_bit <= #1 0;
                    sto_bit <= #1 0;
                    r_data[0] <= #1 0;
                    r_data[1] <= #1 0;
                    r_data[2] <= #1 0;
                    r_data[3] <= #1 0;
                    r_data[4] <= #1 0;
                    r_data[5] <= #1 0;
                    r_data[6] <= #1 0;
                    r_data[7] <= #1 0;
                end
                5,6,7,8,9,10,11:sta_bit <= #1 sta_bit + uart_rx;
                21,22,23,24,25,26,27:r_data[0] <= #1 r_data[0] + uart_rx;
                37,38,39,40,41,42,43:r_data[1] <= #1 r_data[1] + uart_rx;
                53,54,55,56,57,58,59:r_data[2] <= #1 r_data[2] + uart_rx;
                69,70,71,72,73,74,75:r_data[3] <= #1 r_data[3] + uart_rx;
                85,86,87,88,89,90,91:r_data[4] <= #1 r_data[4] + uart_rx;
                101,102,103,104,105,106,107:r_data[5] <= #1 r_data[5] + uart_rx;
                117,118,119,120,121,122,123:r_data[6] <= #1 r_data[6] + uart_rx;
                133,134,135,136,137,138,139:r_data[7] <= #1 r_data[7] + uart_rx;
                149,150,151,152,153,154,155:sto_bit <= #1 sto_bit + uart_rx;
                default:;
            endcase
         end
        
        //输出结果,给到Data
        always@(posedge Clk or negedge Reset_n)
        if(!Reset_n)
            Data <= #1 0;
         else if((bps_cnt == 159 ))begin
            Data[0] <= #1 (r_data[0] >= 4)? 1'b1:1'b0;
            Data[1] <= #1 (r_data[1] >= 4)? 1'b1:1'b0;
            Data[2] <= #1 (r_data[2] >= 4)? 1'b1:1'b0;
            Data[3] <= #1 (r_data[3] >= 4)? 1'b1:1'b0;
            Data[4] <= #1 (r_data[4] >= 4)? 1'b1:1'b0;
            Data[5] <= #1 (r_data[5] >= 4)? 1'b1:1'b0;
            Data[6] <= #1 (r_data[6] >= 4)? 1'b1:1'b0;
            Data[7] <= #1 (r_data[7] >= 4)? 1'b1:1'b0;
         end
        
//        0:3'b000;
//        1:3'b001;
//        2:3'b010;
//        3:3'b011;
        
//        4:3'b100;
//        5:3'b101;
//        6:3'b110;
//        7:3'b110;
//0-3 的第二位都为0,4-7的第二位都为1
    
//        always@(posedge Clk or negedge Reset_n)
//        if(!Reset_n)
//            Data <= 0;
//         else if((bps_cnt == 159 ))begin
//            Data[0] <= r_data[0][2] ;  //等价于 Data[0] <= (r_data[0] >= 4)? 1'b1:1'b0;
//            Data[1] <= r_data[1][2] ;  //将r_data[1] 第二位的值赋给Data[1]
//            Data[2] <= r_data[2][2] ;
//            Data[3] <= r_data[3][2] ;
//            Data[4] <= r_data[4][2] ;
//            Data[5] <= r_data[5][2] ;
//            Data[6] <= r_data[6][2] ;
//            Data[7] <= r_data[7][2] ;
//        end
        
        //给Rx_Done值
        always@(posedge Clk or negedge Reset_n)
        if(!Reset_n)
            Rx_Done <= #1 0;
         else if((div_cnt == Bps_DR) && (bps_cnt == 160 )) //脉冲到来,并且计数到最后一位数159时
            Rx_Done <= #1 1;
         else
            Rx_Done <= #1 0;
   
endmodule

子模块——将发送的数据与led控制端口进行匹配

`timescale 1ns / 1ps

module uart_cmd(
    Clk        ,
    Reset_n    ,
    rx_data    ,
    rx_done    ,
    ctrl       ,
    time_set 
    );
    
    input Clk             ;
    input Reset_n         ;
    input [7:0]rx_data    ;
    input rx_done         ;
    output reg [7:0]ctrl      ;
    output reg [31:0]time_set ;
    
    //八个数据,移位寄存器
    reg [7:0] data_str [7:0];  ///八个八位的数据
    always@(posedge Clk )
     if(rx_done)begin              //如果接收完一个数据
        data_str [7] <= #1 rx_data;      //将接收到的数据给7
        data_str [6] <= #1 data_str [7];
        data_str [5] <= #1 data_str [6];
        data_str [4] <= #1 data_str [5];
        data_str [3] <= #1 data_str [4];
        data_str [2] <= #1 data_str [3];
        data_str [1] <= #1 data_str [2];
        data_str [0] <= #1 data_str [1];
     end
        
        //定义一个rx_done的寄存器r_rx_done,这样r_rx_done一直比rx_done延迟一拍
        reg r_rx_done;
        always@(posedge Clk )
        r_rx_done <= rx_done;
 
        //判断接收到的数据是否符合预期设定的协议
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)begin
        ctrl <= #1 0;     
        time_set <= #1 0;
    end
    else if(r_rx_done) begin
        if((data_str [0] == 8'h55)&&(data_str [1] == 8'hA5)&&(data_str [7] == 8'hF0))begin
            time_set[7:0] <= #1 data_str [2];
            time_set[15:8] <= #1 data_str [3];
            time_set[23:16] <= #1 data_str [4];
            time_set[31:24] <= #1 data_str [5];
            ctrl <= #1 data_str [6];
        end
    end
 
endmodule

功能仿真代码

`timescale 1ns / 1ps

module uart_rx_ctrl_led_tb();

    reg  Clk      ;
    reg  Reset_n  ;
    reg  uart_rx  ;
    wire LED      ;

    uart_rx_ctrl_led uart_rx_ctrl_led(
        .Clk     (Clk),
        .Reset_n (Reset_n),
        .uart_rx (uart_rx),
        .LED     (LED)
        );

    initial Clk = 1;
    always #10 Clk = ~Clk;
    
    initial begin
        Reset_n  = 0   ;
        uart_rx  = 1   ;
        #201;
        Reset_n = 1;
        #200;
        
        uart_tx_byte (8'h55)   ;//协议第0位
        #90000;
        uart_tx_byte (8'ha5)   ;//协议第1位
        #90000;
        
        uart_tx_byte (8'h55)   ;//协议第0位
        #90000;
        uart_tx_byte (8'ha5)   ;//协议第1位
        #90000;
        uart_tx_byte (8'h12)   ;//数据第2位
        #90000;
        uart_tx_byte (8'h34)   ;//数据第3位
        #90000;
        uart_tx_byte (8'h56)   ;//数据第4位
        #90000;
        uart_tx_byte (8'h78)   ;//数据第5位
        #90000;
        uart_tx_byte (8'h9a)   ;//数据第6位,给ctrl
        #90000;
        uart_tx_byte (8'hf0)   ;//协议第7位
        #90000;
        
        uart_tx_byte (8'h55)   ;//协议第0位
        #90000;
        uart_tx_byte (8'ha5)   ;//协议第1位
        #90000;
        uart_tx_byte (8'h9a)   ;//数据第2位
        #90000;
        uart_tx_byte (8'h78)   ;//数据第3位
        #90000;
        uart_tx_byte (8'h56)   ;//数据第4位
        #90000;
        uart_tx_byte (8'h34)   ;//数据第5位
        #90000;
        uart_tx_byte (8'h12)   ;//数据第6位,给ctrl
        #90000;
        uart_tx_byte (8'hf1)   ;//协议第7位
        #90000;
        
        
        $stop;
    end
  
    task uart_tx_byte;
        input [7:0]tx_data;
        begin
            uart_rx = 1;
            #20;
            uart_rx = 0; //起始位
            #8680;   //115200的波特率发送数据,每位保持时间为8680ns
            uart_rx = tx_data[0];
            #8680;
            uart_rx = tx_data[1];
            #8680;
            uart_rx = tx_data[2];
            #8680;
            uart_rx = tx_data[3];
            #8680;
            uart_rx = tx_data[4];
            #8680;
            uart_rx = tx_data[5];
            #8680;
            uart_rx = tx_data[6];
            #8680;
            uart_rx = tx_data[7];
            #8680;
            uart_rx = 1; //结束位
            #8680;
        end
    endtask

endmodule

功能仿真结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值