当前位置: 首页 > news >正文

多字节串口收发IP设计(五)串口模块增加数据位停止位动态配置功能(含源码)

在实际应用时,有数据位和停止位位宽配置的需求,并且需要在PS端进行配置,特此在原设计文件上增加位宽的动态配置功能。

串口接收模块

为适应后级缓存FIFO的位宽,将串口接收模块输出的数据固定为8bit,若配置的数据位位宽小于8bit,则在高位补0,使其组成一个8bit数据,便于后级模块设计。

源代码

`timescale 1ns / 1ps

module UART_rx (

    input   wire                            i_clk               ,

    input   wire                            i_rst               ,

    input   wire                            i_uart_rx           ,

    input   wire    [15:0]                  i_uart_baud_cnt     ,

    input   wire    [ 1:0]                  i_uart_check        , //0-no,1-odd,2-even

    input   wire    [ 1:0]                  i_uart_bit_width    , //0-8bit,1-7bit,2-6bit,3-5bit

    input   wire    [ 1:0]                  i_uart_stop_width   , //0-1bit,1-1.5bit,2-2bit

    output  reg     [ 7:0]                  o_user_rx_data      ,

    output  reg                             o_user_rx_valid     ,

    output  reg                             o_user_rx_error

);

////////////////////////////////////////////////////////////////////

//reg define

reg     [ 5:0]                  r_uart_rx                       ;               

reg     [15:0]                  r_cnt_baud                      ;

reg     [ 3:0]                  r_cnt_bit                       ;

reg                             r_rx_check                      ;

reg                             r_run                           ;

reg     [ 3:0]                  r_data_width                    ;

reg     [ 3:0]                  r_stop_width                    ;

//wire define

wire                            w_rx_en                         ;

wire                            w_bit_en                        ;

wire                            w_start_flag                    ;

wire    [ 3:0]                  w_bit_len                       ;

////////////////////////////////////////////////////////////////////

assign w_rx_en = (r_cnt_baud == (i_uart_baud_cnt >> 1) - 1 );

assign w_bit_en = (r_cnt_baud == i_uart_baud_cnt - 1 );

assign w_start_flag = ~(r_uart_rx[4] | r_uart_rx[3] | r_uart_rx[2] | r_uart_rx[1] | r_uart_rx[0]) ;

assign w_bit_len = 2 + r_data_width + r_stop_width ; //start+data+check+stop

////////////////////////////////////////////////////////////////////

always @(posedge i_clk )begin

    if(i_rst)

        r_uart_rx <= 6'b111111;

    else

        r_uart_rx <= {r_uart_rx[4:0],i_uart_rx}; 

end

always @(*) begin

    case(i_uart_bit_width)

        0 : r_data_width = 8 ;

        1 : r_data_width = 7 ;

        2 : r_data_width = 6 ;

        3 : r_data_width = 5 ;

        default : r_data_width = 8 ;

    endcase

end

always @(*) begin

    case(i_uart_stop_width)

        0 : r_stop_width = 1 ;

        1 : r_stop_width = 2 ;

        2 : r_stop_width = 2 ;

        default : r_stop_width = 1 ;

    endcase

end

always @(posedge i_clk) begin

    if (i_rst)

        r_run <= 0 ;

    else if (o_user_rx_valid)

        r_run <= 0 ;

    else if (w_start_flag && !r_run)

        r_run <= 1 ;

end 

always @(posedge i_clk) begin

    if (i_rst)

        r_cnt_baud <= 0 ;

    else if (r_run && r_cnt_baud < i_uart_baud_cnt - 1)

        r_cnt_baud <= r_cnt_baud + 1 ;

    else 

        r_cnt_baud <= 0 ;

end

always @(posedge i_clk )begin

    if(i_rst)

        r_cnt_bit <= 'd0;

    else if(r_run && r_cnt_bit == r_data_width && i_uart_check == 0 && w_bit_en)

        r_cnt_bit <= 'd0;

    else if(r_run && r_cnt_bit == r_data_width +1 && i_uart_check > 0 && w_bit_en)

        r_cnt_bit <= 'd0;

    else if(r_run && w_bit_en)

        r_cnt_bit <= r_cnt_bit + 1;

end

always @(posedge i_clk )begin

    if(i_rst)

        o_user_rx_data <= 'd0;

    else if(r_run && r_cnt_bit >= 1 && r_cnt_bit <= r_data_width && w_rx_en && (r_data_width==8))

        o_user_rx_data <= {r_uart_rx[5],o_user_rx_data[7:1]};//LSB first

    else if(r_run && r_cnt_bit >= 1 && r_cnt_bit <= r_data_width && w_rx_en && (r_data_width==7))

        o_user_rx_data <= {1'b0,r_uart_rx[5],o_user_rx_data[6:1]};//LSB first

    else if(r_run && r_cnt_bit >= 1 && r_cnt_bit <= r_data_width && w_rx_en && (r_data_width==6))

        o_user_rx_data <= {2'b0,r_uart_rx[5],o_user_rx_data[5:1]};//LSB first

    else if(r_run && r_cnt_bit >= 1 && r_cnt_bit <= r_data_width && w_rx_en && (r_data_width==5))

        o_user_rx_data <= {3'b0,r_uart_rx[5],o_user_rx_data[4:1]};//LSB first

end

always @(posedge i_clk )begin

    if(i_rst)

        o_user_rx_valid <= 'd0;

    else if(r_run && r_cnt_bit == r_data_width && i_uart_check == 0 && w_bit_en)

        o_user_rx_valid <= 1'd1;

    else if(r_run && r_cnt_bit == r_data_width + 1 && w_bit_en)

        o_user_rx_valid <= 1'd1; 

    else if(r_run && r_cnt_bit == r_data_width + 1 && w_bit_en)

        o_user_rx_valid <= 1'd1;

    else

        o_user_rx_valid <= 'd0;

end

always @(posedge i_clk )begin

    if(i_rst)

        o_user_rx_error <= 'd0;

    else if(r_run && r_cnt_bit == r_data_width && i_uart_check == 0 && w_bit_en)

        o_user_rx_error <= 1'd0;

    else if(r_run && r_cnt_bit == r_data_width + 1 && i_uart_check == 1 && r_uart_rx[5] == r_rx_check && w_bit_en)

        o_user_rx_error <= 1'd1; 

    else if(r_run && r_cnt_bit == r_data_width + 1 && i_uart_check == 2 && r_uart_rx[5] == ~r_rx_check && w_bit_en)

        o_user_rx_error <= 1'd1;

    else

        o_user_rx_error <= 'd0;

end

always @(posedge i_clk )begin

    if(i_rst)

        r_rx_check <= 'd0;

    else if(r_run && r_cnt_bit >= 1 && r_cnt_bit <= r_data_width && w_rx_en)

        r_rx_check <= r_rx_check ^ r_uart_rx[5];//异或结果为1说明1个数为奇数

    else if (!r_run)

        r_rx_check <= 'd0;

end

endmodule

串口发送模块

为适应前级缓存FIFO的位宽,将串口发送模块输入的数据固定为8bit,若配置的数据位位宽小于8bit,则去掉高位,使其组成一个小于8bit数据。

源代码

`timescale 1ns / 1ps

module UART_tx  (

    input   wire                            i_clk               ,

    input   wire                            i_rst               ,

    input   wire    [15:0]                  i_uart_baud_cnt     ,

    input   wire    [ 1:0]                  i_uart_check        , //0-no,1-odd,2-even

    input   wire    [ 1:0]                  i_uart_bit_width    , //0-8bit,1-7bit,2-6bit,3-5bit

    input   wire    [ 1:0]                  i_uart_stop_width   , //0-1bit,1-1.5bit,2-2bit

    input   wire    [ 7:0]                  i_user_tx_data      ,

    input   wire                            i_user_tx_valid     ,

    output  reg                             o_user_tx_ready     ,

    output  reg                             o_uart_tx           

    );

////////////////////////////////////////////////////////////////////

//reg define

reg     [ 7:0]                  ri_user_tx_data                 ;

reg     [ 3:0]                  r_cnt_bit                       ; 

reg     [15:0]                  r_cnt_baud                      ;

reg     [ 7:0]                  r_tx_data                       ;

reg                             r_tx_check                      ;

reg     [ 3:0]                  r_data_width                    ;

reg     [ 3:0]                  r_stop_width                    ;

//wire define

wire                            w_active                        ;

wire                            w_tx_en                         ;

wire    [ 3:0]                  w_bit_len                       ;

////////////////////////////////////////////////////////////////////

assign w_active = i_user_tx_valid & o_user_tx_ready ;

assign w_tx_en = (r_cnt_baud == i_uart_baud_cnt - 1 );

assign w_bit_len = 2 + r_data_width + r_stop_width ; //start+data+check+stop

////////////////////////////////////////////////////////////////////

always @(*) begin

    case(i_uart_bit_width)

        0 : r_data_width = 8 ;

        1 : r_data_width = 7 ;

        2 : r_data_width = 6 ;

        3 : r_data_width = 5 ;

        default : r_data_width = 8 ;

    endcase

end

always @(*) begin

    case(i_uart_stop_width)

        0 : r_stop_width = 1 ;

        1 : r_stop_width = 2 ;

        2 : r_stop_width = 2 ;

        default : r_stop_width = 1 ;

    endcase

end

always @(posedge i_clk) begin

    ri_user_tx_data <= i_user_tx_data ;

end

always @(posedge i_clk) begin

    if (i_rst)

        r_cnt_baud <= 0 ;

    else if (!o_user_tx_ready && r_cnt_baud < i_uart_baud_cnt - 1)

        r_cnt_baud <= r_cnt_baud + 1 ;

    else 

        r_cnt_baud <= 0 ;

end

always @(posedge i_clk ) begin

    if (i_rst)

        o_user_tx_ready <= 1 ;

    else if (w_active)

        o_user_tx_ready <= 0 ;

    else if ((i_uart_stop_width==1) && (r_cnt_bit == w_bit_len - 2) && (i_uart_check == 0) && (r_cnt_baud == (i_uart_baud_cnt>>1) - 1 ))

        o_user_tx_ready <= 1 ;

    else if ((i_uart_stop_width==1) && (r_cnt_bit == w_bit_len - 1) && (i_uart_check > 0) && (r_cnt_baud == (i_uart_baud_cnt>>1) - 2 ))

        o_user_tx_ready <= 1 ;

    else if ((r_cnt_bit == w_bit_len - 2) && (i_uart_check == 0) && (r_cnt_baud == i_uart_baud_cnt - 2 ))

        o_user_tx_ready <= 1 ;

    else if ((r_cnt_bit == w_bit_len - 1) && (i_uart_check > 0) && (r_cnt_baud == i_uart_baud_cnt - 2 ))

        o_user_tx_ready <= 1 ;

end

always @(posedge i_clk ) begin

    if (i_rst)

        r_cnt_bit <= 0 ;

    else if (o_user_tx_ready)

        r_cnt_bit <= 0 ;

    else if (!o_user_tx_ready && w_tx_en)

        r_cnt_bit <= r_cnt_bit + 1 ;

end

always @(posedge i_clk ) begin

    if (i_rst)

        r_tx_data <= 0 ;

    else if (w_active)

        r_tx_data <= ri_user_tx_data ;

    else if (!o_user_tx_ready && w_tx_en)

        r_tx_data <= r_tx_data >> 1 ;

end

always @(posedge i_clk ) begin

    if (i_rst) 

        o_uart_tx <= 1 ; // idle

    else if (w_active)

        o_uart_tx <= 0 ; //send start

    else if ((r_cnt_bit == r_data_width) && (i_uart_check > 0) && w_tx_en) 

        o_uart_tx <= i_uart_check == 1 ? ~r_tx_check : r_tx_check ; //send check

    else if ((r_cnt_bit == r_data_width) && (i_uart_check == 0) && w_tx_en) 

        o_uart_tx <= 1 ; //send stop

    else if ((r_cnt_bit == r_data_width+1) && (i_uart_check > 0) && w_tx_en) 

        o_uart_tx <= 1 ; //send stop

    else if (!o_user_tx_ready && w_tx_en && (r_cnt_bit < r_data_width))

        o_uart_tx <= r_tx_data[0] ; //send data

    else if (o_user_tx_ready) 

        o_uart_tx <= 1 ; // idle

end

always @(posedge i_clk) begin

    if (i_rst)

        r_tx_check <= 0 ;

    else if (w_active) 

        r_tx_check <= 0 ;

    else if (!o_user_tx_ready && w_tx_en && (r_cnt_bit < r_data_width))

        r_tx_check <= r_tx_check ^ r_tx_data[0] ;

end

endmodule

联合仿真

仿真代码

`timescale 1ns / 1ps

module tb_UART( );

reg                            i_clk               ;

reg                            i_rst               ;

reg    [31:0]                  i_uart_baud_cnt     ;

reg    [ 1:0]                  i_uart_check        ; //0-no,1-odd,2-even

reg    [ 1:0]                  i_uart_bit_width    ; //0-8bit,1-7bit,2-6bit,3-5bit

reg    [ 1:0]                  i_uart_stop_width   ; //0-1bit,1-1.5bit,2-2bit

reg    [ 7:0]                  i_user_tx_data      ;

reg                            i_user_tx_valid     ;

wire                           o_user_tx_ready     ;

wire                           o_uart_tx           ;

wire   [ 7:0]                  w_usr_rx_data       ;

wire                           w_usr_rx_valid      ;

wire                           o_user_rx_error     ;

reg  flag ;

wire w_active = i_user_tx_valid & o_user_tx_ready ;

initial begin

    i_clk = 0 ;

    i_rst = 1 ;

    i_uart_check = 0 ;

    i_uart_bit_width = 0 ;

    i_uart_stop_width= 0 ;

    i_uart_baud_cnt = 8 ;

    flag = 0 ;

    #100;

    @(posedge i_clk) i_rst = 0 ;

    #200;

    @(posedge i_clk);

    send_data(0,0,0);

    wait(flag);

    @(posedge i_clk);

    send_data(1,0,0);

    wait(flag);

    @(posedge i_clk);

    send_data(2,0,0);

    wait(flag);

    @(posedge i_clk);

    send_data(0,2,0);

    wait(flag);

    @(posedge i_clk);

    send_data(1,2,0);

    wait(flag);

    @(posedge i_clk);

    send_data(2,2,0);

    wait(flag);

    @(posedge i_clk);

    send_data(0,3,1);

    wait(flag);

    @(posedge i_clk);

    send_data(1,3,1);

    wait(flag);

    @(posedge i_clk);

    send_data(2,3,1);

end

always #5 i_clk = ~i_clk ;

task send_data(input [3:0] check, input [3:0] bitwidth, input [3:0] stopwidth);

begin: send_data_task

    flag = 0 ;

    i_uart_check = check ;

    i_uart_bit_width = bitwidth ;

    i_uart_stop_width= stopwidth ;

    @(posedge i_clk);

    wait(o_user_tx_ready);

    @(posedge i_clk);

    case (bitwidth)

        0 : begin i_user_tx_data = 8'hFF ; i_user_tx_valid = 1 ; end 

        1 : begin i_user_tx_data = 8'h7F ; i_user_tx_valid = 1 ; end 

        2 : begin i_user_tx_data = 8'h3F ; i_user_tx_valid = 1 ; end 

        3 : begin i_user_tx_data = 8'h1F ; i_user_tx_valid = 1 ; end 

    endcase

    @(posedge i_clk);

    case (bitwidth)

        0 : begin i_user_tx_data = 8'hFF ; i_user_tx_valid = 0 ; end 

        1 : begin i_user_tx_data = 8'h7F ; i_user_tx_valid = 0 ; end 

        2 : begin i_user_tx_data = 8'h3F ; i_user_tx_valid = 0 ; end 

        3 : begin i_user_tx_data = 8'h1F ; i_user_tx_valid = 0 ; end 

    endcase

    @(posedge i_clk);

    wait(o_user_tx_ready);

    @(posedge i_clk);

    case (bitwidth)

        0 : begin i_user_tx_data = 8'hAA ; i_user_tx_valid = 1 ; end 

        1 : begin i_user_tx_data = 8'h2A ; i_user_tx_valid = 1 ; end 

        2 : begin i_user_tx_data = 8'h2A ; i_user_tx_valid = 1 ; end 

        3 : begin i_user_tx_data = 8'h0A ; i_user_tx_valid = 1 ; end 

    endcase

    @(posedge i_clk);

    case (bitwidth)

        0 : begin i_user_tx_data = 8'hAA ; i_user_tx_valid = 0 ; end 

        1 : begin i_user_tx_data = 8'h2A ; i_user_tx_valid = 0 ; end 

        2 : begin i_user_tx_data = 8'h2A ; i_user_tx_valid = 0 ; end 

        3 : begin i_user_tx_data = 8'h0A ; i_user_tx_valid = 0 ; end 

    endcase

    @(posedge i_clk);

    wait(o_user_tx_ready);

    @(posedge i_clk);

    case (bitwidth)

        0 : begin i_user_tx_data = 8'hA8 ; i_user_tx_valid = 1 ; end 

        1 : begin i_user_tx_data = 8'h28 ; i_user_tx_valid = 1 ; end 

        2 : begin i_user_tx_data = 8'h28 ; i_user_tx_valid = 1 ; end 

        3 : begin i_user_tx_data = 8'h08 ; i_user_tx_valid = 1 ; end 

    endcase

    @(posedge i_clk);

    case (bitwidth)

        0 : begin i_user_tx_data = 8'hA8 ; i_user_tx_valid = 0 ; end 

        1 : begin i_user_tx_data = 8'h28 ; i_user_tx_valid = 0 ; end 

        2 : begin i_user_tx_data = 8'h28 ; i_user_tx_valid = 0 ; end 

        3 : begin i_user_tx_data = 8'h08 ; i_user_tx_valid = 0 ; end 

    endcase

    @(posedge i_clk);

    wait(o_user_tx_ready);

    flag = 1 ;

end

endtask

UART_tx u_UART_tx(

    .i_clk           (i_clk           ),

    .i_rst           (i_rst           ),

    .i_uart_baud_cnt (i_uart_baud_cnt ),

    .i_uart_check    (i_uart_check    ),

    .i_uart_bit_width  (i_uart_bit_width  ),

    .i_uart_stop_width (i_uart_stop_width ),

    .i_user_tx_data  (i_user_tx_data  ),

    .i_user_tx_valid (i_user_tx_valid ),

    .o_user_tx_ready (o_user_tx_ready ),

    .o_uart_tx       (o_uart_tx       )

);

UART_rx UART_rx_u

(

    .i_clk              (i_clk          ),

    .i_rst              (i_rst          ),

    .i_uart_rx          (o_uart_tx      ),

    .i_uart_baud_cnt    (i_uart_baud_cnt),

    .i_uart_check    (i_uart_check    ),

    .i_uart_bit_width  (i_uart_bit_width  ),

    .i_uart_stop_width (i_uart_stop_width ),

    .o_user_rx_data     (w_usr_rx_data  ),

    .o_user_rx_valid    (w_usr_rx_valid ),

    .o_user_rx_error    (o_user_rx_error)

    );

endmodule

仿真结果

输入与输出结果一致。

http://www.dtcms.com/a/486950.html

相关文章:

  • 上海网站建设专业公司排名百度搜索app
  • Java 设计模式—— 责任链模式:从原理到 SpringBoot 最优实现
  • Linux中快速部署Minio(基础TLS配置)
  • 大型小说网站开发语言望野博物馆
  • 做早餐烧菜有什么网站零基础搭建网站
  • SAP PCE生产订单组件不能更改物料编码和工厂
  • Aosp14系统壁纸的启动和加载流程
  • 电压源和电流源学习理解
  • 刘洋洋《魔法派对Magic Party》童话重启,温柔守护每颗童心
  • 东莞长安网站设计搞网站开发的程序员属于哪一类
  • 运维领域核心概念的专有名词解释-详解
  • 【AIGC】语音识别ASR:火山引擎大模型技术实践
  • 如何在AutoCAD中加载大型影像文件?
  • 爬虫调试技巧:如何用浏览器开发者工具找接口?
  • Linux 页缓存(Page Cache)与回写(Writeback)机制详解
  • 【NI测试方案】基于ARM+FPGA的整车仿真与电池标定
  • JavaScript将url转为blob和file,三种方法
  • 电商营销型网站建设中国菲律宾关系现状
  • 英文网站建设 飞沐wordpress公众号文章分类
  • 怎么做qq靓号网站岳阳网站设计公司
  • Unity 通过Texture生成的Sprite存在边缘黑线问题 Image黑边问题
  • 计算机方向如何才能更好的找到工作?(成长心得)
  • 大连市城市建设投资集团网站网站怎么做文件上传
  • 织梦网站转跳手机站盐城网盐城网站建设站建设
  • Spring AOP 中@annotation的两种写法详解
  • Linux设备模型
  • Linux fg命令使用教程
  • 微博爬虫流程解析——session的使用
  • 企业网站建设的核心是专业手机建站公司
  • Vllm Semantic-router MoM 架构