【FPGA协议篇】UART通信及其verilog实现(代码采用传参实现模块通用性,适用于快速开发)

这篇具有很好参考价值的文章主要介绍了【FPGA协议篇】UART通信及其verilog实现(代码采用传参实现模块通用性,适用于快速开发)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

UART通信简介

​ 即通用异步收发器(Universal Asynchronous Receiver/Transmitter),是一种串行、异步、全双工的通信协议。特点是通信线路简单,适用于远距离通信,但传输速度慢。

数据传输速率:波特率(单位:baud,波特)

常见波特率有:1200、2400、4800、19200、38400、57600等,最常用的是9600和115200。

数据通信格式如下:包含一个起始位、n个数据位(通常为8位,即一个字节)、1个校验位、1个结束位

【FPGA协议篇】UART通信及其verilog实现(代码采用传参实现模块通用性,适用于快速开发)

其中各位的意义如下:

空闲位:

UART协议规定,当总线处于空闲状态时信号线的状态为‘1’即高电平,表示当前线路上没有数据传输。

起始位:

每开始一次通信时发送方先发出一个逻辑”0”的信号(低电平),表示传输字符的开始。因为总线空闲时为高电平所以开始一次通信时先发送一个明显区别于空闲状态的信号即低电平。

数据位:

起始位之后就是我们所要传输的数据,数据位可以是5、6、7、8,9位等,构成一个字符(一般都是8位)。如ASCII码(7位),扩展BCD码(8位)。先发送最低位,最后发送最高位,使用低电平表示‘0’高电平表示‘1’完成数据位的传输。

奇偶校验位:

数据位加上这一位后,使得“1”的位数应为偶数(偶校验)或奇数(奇校验),以此来校验数据传送的正确性。校验位其实是调整个数,串口校验分几种方式:

  • 1、无校验(no parity)。
  • 2、奇校验(odd parity):如果数据位中“1”的数目是偶数,则校验位为“1”,如果“1”的数目是奇数,校验位为“0”。
  • 3、偶校验(even parity):如果数据为中“1”的数目是偶数,则校验位为“0”,如果为奇数,校验位为“1”。
  • 4、mark parity:校验位始终为1(不常用)。
  • 5、parity:校验位始终为0(不常用)。

停止位:

它是一个字符数据的结束标志。可以是1位、1.5位、2位的高电平。 由于数据是在传输线上定时的,并且每一个设备有其自己的时钟,很可能在通信中两台设备之间出现了小小的不同步。因此停止位不仅仅是表示传输的结束,并且提供计算机校正时钟的机会。停止位个数越多,数据传输越稳定,但是数据传输速度也越慢。

verilog实现

本次UART工程实现采用环路测试,为了达到通用模块的标准,采用参数传递的形式来实现工程,可修改的参数有:

1.时钟频率。对应不同的开发平台,其芯片的工作频率不同,可直接通过修改参数CLK_FRE来实现频率匹配,参数缺省为50MHz。
2. UART传输数据长度。UART的数据长度可修改,通常采用byte的形式,即8位数据长度,缺省也为8位。
3. 奇偶校验位。通过PARITY_ON的参数传递实现是否需要奇偶校验的功能,缺省为不需要奇偶校验。
4. 奇偶校验类型。可选择为奇校验或偶校验,缺省为奇校验。
5. 波特率。波特率类型可自行调整,一般常用为9600,115200。

亲测可用。既可用于学习,也可用于快速开发。废话完了,开始正文……

顶层模块

顶层模块直接调用uart_rx和uart_tx两个模块,前者实现接收数据,后者实现发送数据,从而形成环路。代码(附注释)如下:

module uart_loop(
    input i_clk_sys,
    input i_rst_n,
    input i_uart_rx,
    output o_uart_tx,
    output o_ld_parity
    );
    
    localparam DATA_WIDTH = 8;
    localparam BAUD_RATE = 9600;
    localparam PARITY_ON = 1;
    localparam PARITY_TYPE = 1;
    
    wire w_rx_done;
    wire[DATA_WIDTH-1 : 0] w_data;
    
    
    uart_rx 
    #(
            .CLK_FRE(50),         //时钟频率,默认时钟频率为50MHz
            .DATA_WIDTH(DATA_WIDTH),       //有效数据位,缺省为8位
            .PARITY_ON(PARITY_ON),        //校验位,1为有校验位,0为无校验位,缺省为0
            .PARITY_TYPE(PARITY_TYPE),      //校验类型,1为奇校验,0为偶校验,缺省为偶校验
            .BAUD_RATE(BAUD_RATE)      //波特率,缺省为9600
    ) u_uart_rx
    (
        .i_clk_sys(i_clk_sys),      //系统时钟
        .i_rst_n(i_rst_n),        //全局异步复位,低电平有效
        .i_uart_rx(i_uart_rx),      //UART输入
        .o_uart_data(w_data),    //UART接收数据
        .o_ld_parity(o_ld_parity),    //校验位检验LED,高电平位为校验正确
        .o_rx_done(w_rx_done)       //UART数据接收完成标志
    );
    
    uart_tx
    #(
        .CLK_FRE(50),         //时钟频率,默认时钟频率为50MHz
        .DATA_WIDTH(DATA_WIDTH),       //有效数据位,缺省为8位
        .PARITY_ON(PARITY_ON),        //校验位,1为有校验位,0为无校验位,缺省为0
        .PARITY_TYPE(PARITY_TYPE),      //校验类型,1为奇校验,0为偶校验,缺省为偶校验
        .BAUD_RATE(BAUD_RATE)      //波特率,缺省为9600
    ) u_uart_tx
    (   .i_clk_sys(i_clk_sys),      //系统时钟
        .i_rst_n(i_rst_n),        //全局异步复位
        .i_data_tx(w_data),      //传输数据输入
        .i_data_valid(w_rx_done),   //传输数据有效
        .o_uart_tx(o_uart_tx)       //UART输出
        );
    
endmodule

接收模块

接收模块采用三段式状态机的形式编写,附带基本注释说明。

module uart_rx
#(
    parameter CLK_FRE = 50,         //时钟频率,默认时钟频率为50MHz
    parameter DATA_WIDTH = 8,       //有效数据位,缺省为8位
    parameter PARITY_ON = 0,        //校验位,1为有校验位,0为无校验位,缺省为0
    parameter PARITY_TYPE = 0,      //校验类型,1为奇校验,0为偶校验,缺省为偶校验
    parameter BAUD_RATE = 9600      //波特率,缺省为9600
)
(
    input                           i_clk_sys,      //系统时钟
    input                           i_rst_n,        //全局异步复位,低电平有效
    input                           i_uart_rx,      //UART输入
    output reg[DATA_WIDTH-1 :0]     o_uart_data,    //UART接收数据
    output reg                      o_ld_parity,    //校验位检验LED,高电平位为校验正确
    output reg                      o_rx_done       //UART数据接收完成标志
    );
    
    /*
    UART输入是异步输入,最好是同步到FPGA内部的时钟域
    可以省略,但在异步电路中,保持时钟域同步是一个良好习惯
    */
    reg sync_uart_rx;
    always@(posedge i_clk_sys or negedge i_rst_n)
        begin
            if(!i_rst_n)
                sync_uart_rx <= 1'b1;
            else
                sync_uart_rx <= i_uart_rx;
        end
    
    /*
    连续采样五个接收路电平来判断rx是否有信号传来
    用五个采样信号来作为判断标准可以有效排除毛刺噪声带来的误判
    */
    reg [4:0] r_flag_rcv_start;
    wire w_rcv_start;
    always@(posedge i_clk_sys or negedge i_rst_n)
        begin
            if(!i_rst_n)
                r_flag_rcv_start <= 5'b11111;
            else
                r_flag_rcv_start <= {r_flag_rcv_start[3:0], sync_uart_rx};
        end
    
    
    //状态机定义
    reg [2:0] r_current_state;  //当前状态
    reg [2:0] r_next_state;     //次态
        
    localparam STATE_IDLE = 3'b000;         //空闲状态
    localparam STATE_START = 3'b001;        //开始状态
    localparam STATE_DATA = 3'b011;         //数据接收状态
    localparam STATE_PARITY = 3'b100;       //数据校验状态
    localparam STATE_END = 3'b101;          //结束状态
    
    
    localparam CYCLE = CLK_FRE * 1000000 / BAUD_RATE;   //波特计数周期
    
    reg baud_valid;                         //波特计数有效位
    reg [15:0] baud_cnt;                    //波特率计数器 
    reg baud_pulse;                         //波特率采样脉冲
    
    reg [3:0]   r_rcv_cnt;      //接收数据位计数
    
    //波特率计数器
    always@(posedge i_clk_sys or negedge i_rst_n)
        begin
            if(!i_rst_n)
                baud_cnt <= 16'h0000;
            else if(!baud_valid)
                baud_cnt <= 16'h0000;
            else if(baud_cnt == CYCLE - 1)
                baud_cnt <= 16'h0000;
            else
                baud_cnt <= baud_cnt + 1'b1;
        end
        
    //波特采样脉冲
    always@(posedge i_clk_sys or negedge i_rst_n)
        begin
            if(!i_rst_n)
                baud_pulse <= 1'b0;
            else if(baud_cnt == CYCLE/2-1)
                baud_pulse <= 1'b1;
            else
                baud_pulse <= 1'b0;
        end
    
    //状态机状态变化定义
    always@(posedge i_clk_sys or negedge i_rst_n)
        begin
            if(!i_rst_n)
                r_current_state <= STATE_IDLE;
            else if(!baud_valid)
                r_current_state <= STATE_IDLE;
            else if(baud_valid && baud_cnt == 16'h0000)
                r_current_state <= r_next_state;
        end
    
    //状态机次态定义
    always@(*)
        begin
            case(r_current_state)
                STATE_IDLE:     r_next_state <= STATE_START;
                STATE_START:    r_next_state <= STATE_DATA;
                STATE_DATA:
                    if(r_rcv_cnt == DATA_WIDTH)
                        begin
                            if(PARITY_ON == 0)
                                r_next_state <= STATE_END;
                            else
                                r_next_state <= STATE_PARITY;       //校验位开启时进入校验状态
                        end
                    else
                        begin
                                r_next_state <= STATE_DATA;
                        end
                STATE_PARITY:   r_next_state <= STATE_END;
                STATE_END:      r_next_state <= STATE_IDLE;
                default:;
            endcase
        end
    
    
    reg[DATA_WIDTH - 1 :0] r_data_rcv;
    reg r_parity_check;
    
    //状态机输出逻辑
    always@(posedge i_clk_sys or negedge i_rst_n)
        begin
            if(!i_rst_n)
                begin
                    baud_valid <= 1'b0;
                    r_data_rcv <= 'd0;
                    r_rcv_cnt <= 4'd0;
                    r_parity_check <= 1'b0;
                    o_uart_data <= 'd0;
                    o_ld_parity <= 1'b0;
                    o_rx_done <= 1'b0;
                end
            else
                case(r_current_state)
                    STATE_IDLE:begin
                            //闲置状态下对寄存器进行复位
                            r_rcv_cnt <= 4'd0;
                            r_data_rcv <= 'd0;
                            r_parity_check <= 1'b0;
                            o_rx_done <= 1'b0;
                            //连续检测到低电平时认为UART传来数据,拉高baud_valid
                            if(r_flag_rcv_start == 5'b00000)
                                baud_valid <= 1'b1;
                        end
                    STATE_START:begin
                            if(baud_pulse && sync_uart_rx)     //波特率采样脉冲到来时再次检测是否为低电平,如果不为低电平,认为前期误检测,重新进入IDLE状态
                                baud_valid <= 1'b0;
                        end
                    STATE_DATA:begin
                            if(baud_pulse)
                                begin
                                    r_data_rcv <= {sync_uart_rx, r_data_rcv[DATA_WIDTH-1 : 1]}; //数据移位存储
                                    r_rcv_cnt <= r_rcv_cnt + 1'b1;                          //数据位计数
                                    r_parity_check <= r_parity_check + sync_uart_rx;        //校验位做加法验证高电平的奇偶
                                end
                        end
                    STATE_PARITY:begin
                            if(baud_pulse)
                                begin
                                //校验检测,正确则o_ld_parity拉高,可输出给led检测,如果闪烁则表示有错误数据发生
                                    if(r_parity_check + sync_uart_rx == PARITY_TYPE)
                                        o_ld_parity <= 1'b1;
                                    else
                                        o_ld_parity <= 1'b0;
                                end
                            else
                                        o_ld_parity <= o_ld_parity;
                        end
                    STATE_END:begin
                            if(baud_pulse)
                                begin
                                //没有校验位或者校验位正确时才输出数据,否则直接丢弃数据
                                    if(PARITY_ON == 0 || o_ld_parity)
                                        begin
                                            o_uart_data <= r_data_rcv;
                                            o_rx_done <= 1'b1;
                                        end
                                end
                            else
                                begin
                                    o_rx_done <= 1'b0;
                                end
                            
                            if(baud_cnt == 16'h0000)
                                    baud_valid <= 1'b0;
                        end
                    default:;
                endcase
        end
    
    
endmodule

发送模块

发送模块和接收模块基本写法一致,只有细微的参数改动实现逆过程。重点区别在于三段状态机的状态机输出逻辑不同。

module uart_tx
#(
   parameter CLK_FRE = 50,         //时钟频率,默认时钟频率为50MHz
   parameter DATA_WIDTH = 8,       //有效数据位,缺省为8位
   parameter PARITY_ON = 0,        //校验位,1为有校验位,0为无校验位,缺省为0
   parameter PARITY_TYPE = 0,      //校验类型,1为奇校验,0为偶校验,缺省为偶校验
   parameter BAUD_RATE = 9600      //波特率,缺省为9600
)
(   input                       i_clk_sys,      //系统时钟
   input                       i_rst_n,        //全局异步复位
   input [DATA_WIDTH-1 : 0]    i_data_tx,      //传输数据输入
   input                       i_data_valid,   //传输数据有效
   output reg                  o_uart_tx       //UART输出
   );
   
       
   //状态机定义
           reg [2:0] r_current_state;  //当前状态
           reg [2:0] r_next_state;     //次态
               
           localparam STATE_IDLE = 3'b000;         //空闲状态
           localparam STATE_START = 3'b001;        //开始状态
           localparam STATE_DATA = 3'b011;         //数据发送状态
           localparam STATE_PARITY = 3'b100;       //数据校验计算和发送
           localparam STATE_END = 3'b101;          //结束状态
           
           
           localparam CYCLE = CLK_FRE * 1000000 / BAUD_RATE;   //波特计数周期
           
           reg baud_valid;                         //波特计数有效位
           reg [15:0] baud_cnt;                    //波特率计数器 
           reg baud_pulse;                         //波特率采样脉冲
           
           reg [3:0]   r_tx_cnt;      //接收数据位计数
           
           //波特率计数器
           always@(posedge i_clk_sys or negedge i_rst_n)
               begin
                   if(!i_rst_n)
                       baud_cnt <= 16'h0000;
                   else if(!baud_valid)
                       baud_cnt <= 16'h0000;
                   else if(baud_cnt == CYCLE - 1)
                       baud_cnt <= 16'h0000;
                   else
                       baud_cnt <= baud_cnt + 1'b1;
               end
               
           //波特采样脉冲
           always@(posedge i_clk_sys or negedge i_rst_n)
               begin
                   if(!i_rst_n)
                       baud_pulse <= 1'b0;
                   else if(baud_cnt == CYCLE/2-1)
                       baud_pulse <= 1'b1;
                   else
                       baud_pulse <= 1'b0;
               end
           
           //状态机状态变化定义
           always@(posedge i_clk_sys or negedge i_rst_n)
               begin
                   if(!i_rst_n)
                       r_current_state <= STATE_IDLE;
                   else if(!baud_valid)
                       r_current_state <= STATE_IDLE;
                   else if(baud_valid && baud_cnt == 16'h0000)
                       r_current_state <= r_next_state;
               end
           
           //状态机次态定义
           always@(*)
               begin
                   case(r_current_state)
                       STATE_IDLE:     r_next_state <= STATE_START;
                       STATE_START:    r_next_state <= STATE_DATA;
                       STATE_DATA:
                           if(r_tx_cnt == DATA_WIDTH)
                               begin
                                   if(PARITY_ON == 0)
                                       r_next_state <= STATE_END;
                                   else
                                       r_next_state <= STATE_PARITY;       //校验位开启时进入校验状态
                               end
                           else
                               begin
                                       r_next_state <= STATE_DATA;
                               end
                       STATE_PARITY:   r_next_state <= STATE_END;
                       STATE_END:      r_next_state <= STATE_IDLE;
                       default:;
                   endcase
               end
   
   
   reg [DATA_WIDTH-1 : 0]      r_data_tx;
   reg                         r_parity_check;
   //状态机输出逻辑
   always@(posedge i_clk_sys or negedge i_rst_n)
       begin
           if(!i_rst_n)
               begin
                   baud_valid  <= 1'b0;
                   r_data_tx   <= 'd0;
                   o_uart_tx   <= 1'b1;
                   r_tx_cnt    <= 4'd0;
                   r_parity_check <= 1'b0;
               end
           else
               case(r_current_state)
                   STATE_IDLE:begin
                           o_uart_tx   <= 1'b1;
                           r_tx_cnt    <= 4'd0;
                           r_parity_check <= 4'd0;
                           if(i_data_valid)
                               begin
                                   baud_valid <= 1'b1;
                                   r_data_tx <= i_data_tx;
                               end
                       end
                   STATE_START:begin
                           if(baud_pulse)
                               o_uart_tx   <= 1'b0;
                       end
                   STATE_DATA:begin
                           if(baud_pulse)
                               begin
                                   r_tx_cnt <= r_tx_cnt + 1'b1;
                                   o_uart_tx <= r_data_tx[0];
                                   r_parity_check <= r_parity_check + r_data_tx[0];
                                   r_data_tx <= {1'b0 ,r_data_tx[DATA_WIDTH-1:1]};
                               end
                       end
                   STATE_PARITY:begin
                           if(baud_pulse)
                               begin
                                   if(PARITY_TYPE == 1)
                                       o_uart_tx <= r_parity_check;
                                   else
                                       o_uart_tx <= r_parity_check + 1'b1;
                               end
                       end
                   STATE_END:begin
                           if(baud_pulse)
                               begin
                                   o_uart_tx <= 1'b1;
                                   baud_valid <= 1'b0;
                               end
                       end
                   default:;
               endcase
       end

endmodule

以上便是整个工程的完整代码,至于FPGA的xdc约束,不同开发平台不同,这里就不贴出来了。

仿真波形

testbench的编写如下:

module uart_loop_tb(
    );
    
    reg clk_sys;
    reg rst_n;
    reg uart_in;
    wire uart_out;
    wire parity;
    
    uart_loop u_uart_loop(
        .i_clk_sys(clk_sys),
        .i_rst_n(rst_n),
        .i_uart_rx(uart_in),
        .o_uart_tx(uart_out),
        .o_ld_parity(parity)
        );
        
        
    initial begin
        clk_sys = 1'b0;
        rst_n = 1'b0;
        uart_in = 1'b1;
    end
    
    always #10 clk_sys = ~clk_sys;
    
    localparam ELEMENT_TIME = 104160;
    reg [7:0] DATA = 8'hAC;
    
    initial begin
        #100 rst_n = 1'b1;
        #20000;
        
        uart_in = 1'b0;
        #ELEMENT_TIME
        uart_in = DATA[0];
        #ELEMENT_TIME
        uart_in = DATA[1];
        #ELEMENT_TIME
        uart_in = DATA[2];
        #ELEMENT_TIME
        uart_in = DATA[3];
        #ELEMENT_TIME
        uart_in = DATA[4];
        #ELEMENT_TIME
        uart_in = DATA[5];
        #ELEMENT_TIME
        uart_in = DATA[6];
        #ELEMENT_TIME
        uart_in = DATA[7];
        #ELEMENT_TIME
        uart_in = 1'b1;
        #ELEMENT_TIME
        uart_in = 1'b1;
        
    end

endmodule

此处我们只进行一次数据传输过程的测试,读者可自行编写测试程序。
传输的字节内容为8’hAC即8’b10101100。
仿真波形如下:
【FPGA协议篇】UART通信及其verilog实现(代码采用传参实现模块通用性,适用于快速开发)仿真波形中蓝色部分为rx端的主要波形,橙色部分为tx端的主要波形。
有兴趣了解细致波形的可以直接建立一个工程,这样子想看哪个波形就能看哪个波形啦~

实测结果

实测直接通过串口CH340实现TTL电平转换,与PC端的串口调试助手进行测试。调试助手采用友善串口调试助手(老实说这个调试助手界面做的不怎么样哈哈),设置条件可查看左边串口设置:

测试结果如下:
【FPGA协议篇】UART通信及其verilog实现(代码采用传参实现模块通用性,适用于快速开发)可以看到,红色为发送数据,蓝色为接收数据,串口回环实现了将接收数据再次转发给PC端。

以上就是本次分享的内容啦~有机会再更新其他的协议。文章来源地址https://www.toymoban.com/news/detail-453124.html

到了这里,关于【FPGA协议篇】UART通信及其verilog实现(代码采用传参实现模块通用性,适用于快速开发)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • UART协议——FPGA代码篇

            UART 串口通信有几个重要的参数,分别是波特率、起始位、数据位、停止位和奇偶检验位,对于两个使用UART 串口通信的端口,这些参数必须匹配,否则通 起始位:表示数据传输的开始,电平逻辑为“0” 。 数据位:可能值有5、6、7、8、9,表示传输这几个bit 位数

    2024年01月18日
    浏览(42)
  • FPGA 串口通信(uart)初探篇(含源代码)

    一、UART 串口通信,说实话是日常生活中很常见的一种9针型的主机和显示屏之间的通信模式。本次博客,只为自己复盘相关知识,初学者,错误较多,请多指教。所以本文参考(一)FPGA之串口通信(UART)_fpga uart-CSDN博客 而编著的。 FPGA是一种可编程的逻辑器件,用于各种数字电

    2024年04月14日
    浏览(34)
  • 【FPGA】FPGA实现UART串口通信回环

    关于UART协议的基础理论部分已经在上一篇文章中讲述,不再重复介绍。 UART通信协议 本文主要介绍如何使用Verlilog编程,通过FPGA实现UART串口通信回环工程。在本工程中所使用的系统时钟为50MHz,如果选择115200的波特率进行数据传输,那么传输1bit所用的时钟周期数就是50_000_

    2024年02月05日
    浏览(65)
  • 基于FPGA的UART多字节环回实验verilog代码(含帧头帧尾和解码部分)

    采用VIVADO开发环境,频率50MHz,波特率 256000,8位数据位,1位停止位。 串口接收程序源自正点原子的例程。 带仿真工程,数据帧格式如下图: 发送数据为:aa ff 03 00 0E 03 B1 86 10 00 40 01 11 00 00 00 00 00 00 00 11 00 00 00 00 00 11 11 55 CC 效果如图:  仿真效果图: 参考以下文章和视频:

    2024年02月08日
    浏览(53)
  • FPGA实现UART通信(1)---发送数据

    1、基本概念 通用异步收发传输器,是一种异步收发传输器,在发送数据通过将并行数据转换成串行数据进行传输,在接收数据时将串行数据转换成并行数据。 串行通信分为同步串行通信和异步串行通信。同步串行通信即需要时钟的参与,通信双方需要在同一时钟的控制下,

    2024年02月04日
    浏览(45)
  • 【FPGA】UART串口通信——奇偶校验实现

    奇偶校验位是基于uart的数据上进行一个判断 奇校验:数据1个数为奇时,校验为0,反之为1 偶校验:数据0个数为偶时,校验为0,反之为1 Uart回环在之前已经实现,现在需要基于uart增加一个奇偶校验位的需求 uart及代码:https://blog.csdn.net/weixin_59150966/article/details/128005066?spm=10

    2024年02月11日
    浏览(42)
  • 【FPGA学习】状态机实现UART通信

      在之前的文章中【FPGA学习】实例一、Cyclone IV串口通信(RS232)我们已经能够采用波形图的方法,实现9600bps的Uart通信。近期笔者在整理了状态机和计数器组合的设计方法以后,对状态机的设计又有了新的感悟和体会,所以又把经典的RS232协议拉出来当状态机的例子练手了哈哈

    2023年04月11日
    浏览(41)
  • FPGA-结合协议时序实现UART收发器(一):UART协议、架构规划、框图

    记录FPGA的UART学习笔记,以及一些细节处理,主要参考奇哥fpga学习资料。 本次UART主要采用计数器方法实现,实现uart的稳定性发送和接收功能,最后实现串口数据回环进行功能测试。 UART协议如图。 包含:空闲位、起始位、数据位、校验位、停止位、空闲位(一般没有) 对于

    2024年02月08日
    浏览(67)
  • FPGA实现 RDMA NIC 10G UDP协议栈网卡,纯verilog代码编写,提供工程源码和技术支持

    FPGA实现 NIC 10G 网卡,纯verilog代码编写,提供3套工程源码和技术支持 网络接口控制器(NIC)是计算机与网络进行交互的网关。NIC构成了软件协议栈和网络之间的桥梁,该桥梁的功能定义了网络接口。网络接口的功能以及这些功能的实现都在迅速发展。这些变化是由提高线速和

    2024年02月10日
    浏览(80)
  • Verilog(1)UART串口通信

    第一部分为uart串口通信的接收部分,用pc端虚拟串口来对其发送数据。 第三部分为uart串口通信的发送部分,用此部分对pc端虚拟串口发送数据。 第二部分loop,处理数据,形成回环,使发送部分有数据来源,以此来保证实验的完成。 串口接收 :  输入: sys_clk、sys_rst_n、u

    2024年02月03日
    浏览(81)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包