FPGA-串口通信的接收模块(发送接收模块)

简介: FPGA-串口通信的接收模块(发送接收模块)

接收模块和发送模块类似:

      在接收的过程中为了保证接收数据的准确性对单个时钟波特率进行分频,单个时钟信号下分频16次,进行数据采集保证了数据的准确性,这里的代码思想借鉴了小梅哥的代码的编写思想。

发送接收模块的验证:

这里发送接收的验证是通过PC端进行发送,由开发板先接收到数据,然后进行发送,这里如果要是验证些字符串或者是一些特殊的指令,用状态机或者类似状态机的思想进行设计。

这里只贴出任务要求的接收模块的验证基本任务和代码

任务要求:

由PC端口进行发送指令检测单个字符和字符串

     如果发送I Like FPGA led 全亮,如果错误led闪烁,当发送单个字符时,利用LED灯指示该字符的ASCII码。

串口接收模块:


module uart_rxd(clk,rst_n,bps_set,rxd,data_byte,rxd_finish,uart_state
    );
  input           clk       ;//输入时钟
  input           rst_n     ;//复位信号
  input     [1:0] bps_set   ;//波特率选择
  input           rxd       ;//接收模块
  output    [7:0] data_byte ;//接收数据
  output          rxd_finish;//发送完成标志
  output          uart_state;//串口通信状态
  reg       [7:0] data_byte ;
  reg             rxd_finish;
  reg             uart_state;
  parameter       BPS_4800    =16'd324,
                    BPS_9600    =16'd162,
          BPS_19200   =16'd80 ,
                    BPS_115200  =16'd13 ;
  //消除亚稳态
  reg rxd_s0,rxd_s1;  //同步寄存器
  always@(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
      rxd_s0<=1'b0;
      rxd_s1<=1'b0;
    end
    else begin
      rxd_s0<=rxd;
      rxd_s1<=rxd_s0;
    end
  end
  reg rxd_temp0,rxd_temp1;//数据寄存器
  always@(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
      rxd_temp0<=1'b0;
      rxd_temp1<=1'b0;
    end
    else begin
      rxd_temp0<=rxd_s1;
      rxd_temp1<=rxd_temp0;
    end
  end
  wire rxd_negedge =~rxd_temp0&rxd_temp1;
  reg [15:0] div_cnt;
  reg [15:0] time_div;
  //波特率选择模块
  always@(*)begin
    if(rst_n==1'b0)begin
      time_div=BPS_9600;
    end
    else begin
      case(bps_set)
        2'b00: time_div = BPS_4800;
        2'b01: time_div = BPS_9600;
        2'b10: time_div = BPS_19200;
        2'b11: time_div = BPS_115200;
        default:time_div = BPS_9600;
      endcase
    end
  end
  //波特率计数模块
  always@(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
      div_cnt<=1'b0;
    end
    else if(uart_state==1'b1)begin
      if(div_cnt==time_div)begin
        div_cnt<=1'b0;
      end
      else begin
        div_cnt<=div_cnt+1'b1;
      end
    end
    else begin
      div_cnt<=1'b0;
    end
  end
  //波特率时钟模块
  reg bps_clk;
  always@(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
      bps_clk<=1'b0;
    end
    else if(div_cnt==time_div)begin
      bps_clk<=1'b1;
    end
    else begin
      bps_clk<=1'b0;
    end
  end
  //bps计数模块
  reg [7:0] bps_cnt;
  always@(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
      bps_cnt<=8'd0;
    end
    else if(rxd_finish==1'b1||(bps_cnt==8'd12 && (Start>3'd3)))begin
      bps_cnt<=8'd0;
    end
    else if(bps_clk==1'b1)begin
      bps_cnt<=bps_cnt+1'b1;
    end
    else begin
      bps_cnt<=bps_cnt;
    end
  end
  always@(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
      rxd_finish=1'b0;
    end
    else if(bps_cnt==8'd159)begin
      rxd_finish=1'b1;
    end
    else begin
      rxd_finish=1'b0;
    end
  end
  //数据缓冲区模块
  reg [2:0] r_data_byte[7:0];
  reg [2:0]Start,Stop;
  always@(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
      Start<=3'd0;
      r_data_byte[0]<=3'd0;
      r_data_byte[1]<=3'd0;
      r_data_byte[2]<=3'd0;
      r_data_byte[3]<=3'd0;
      r_data_byte[4]<=3'd0;
      r_data_byte[5]<=3'd0;
      r_data_byte[6]<=3'd0;
      r_data_byte[7]<=3'd0;
      Stop<=3'd0;
    end
    else if(bps_clk==1'b1)begin
      if(bps_cnt==1'b0)begin
        Start<=3'd0;
        r_data_byte[0]<=3'd0;
        r_data_byte[1]<=3'd0;
        r_data_byte[2]<=3'd0;
        r_data_byte[3]<=3'd0;
        r_data_byte[4]<=3'd0;
        r_data_byte[5]<=3'd0;
        r_data_byte[6]<=3'd0;
        r_data_byte[7]<=3'd0;
        Stop<=3'd0;
      end
      if(16'd6<=bps_cnt&&bps_cnt<=16'd12)begin
        Start<=Start+rxd_s1;
      end
      else if(16'd22<=bps_cnt&&bps_cnt<=16'd28)begin
        r_data_byte[0]<=r_data_byte[0]+rxd_s1;
      end
      else if(16'd38<=bps_cnt&&bps_cnt<=16'd44)begin
        r_data_byte[1]<=r_data_byte[1]+rxd_s1;
      end
      else if(16'd54<=bps_cnt&&bps_cnt<=16'd60)begin
        r_data_byte[2]<=r_data_byte[2]+rxd_s1;
      end
      else if(16'd70<=bps_cnt&&bps_cnt<=16'd76)begin
        r_data_byte[3]<=r_data_byte[3]+rxd_s1;
      end
      else if(16'd86<=bps_cnt&&bps_cnt<=16'd92)begin
        r_data_byte[4]<=r_data_byte[4]+rxd_s1;
      end
      else if(16'd102<=bps_cnt&&bps_cnt<=16'd108)begin
        r_data_byte[5]<=r_data_byte[5]+rxd_s1;
      end
      else if(16'd118<=bps_cnt&&bps_cnt<=16'd124)begin
        r_data_byte[6]<=r_data_byte[6]+rxd_s1;
      end
      else if(16'd134<=bps_cnt&&bps_cnt<=16'd140)begin
        r_data_byte[7]<=r_data_byte[7]+rxd_s1;
      end
      else if(16'd150<=bps_cnt&&bps_cnt<=16'd156)begin
        Stop<=Stop+rxd_s1;
      end
    end
    else;
  end
    always@(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
      data_byte<=8'd0;
    end
    else if(bps_cnt==8'd159)begin
      data_byte[0]<=(r_data_byte[0]>3'd3)?1'b1:1'b0;
      data_byte[1]<=(r_data_byte[1]>3'd3)?1'b1:1'b0;
      data_byte[2]<=(r_data_byte[2]>3'd3)?1'b1:1'b0;
      data_byte[3]<=(r_data_byte[3]>3'd3)?1'b1:1'b0;
      data_byte[4]<=(r_data_byte[4]>3'd3)?1'b1:1'b0;
      data_byte[5]<=(r_data_byte[5]>3'd3)?1'b1:1'b0;
      data_byte[6]<=(r_data_byte[6]>3'd3)?1'b1:1'b0;
      data_byte[7]<=(r_data_byte[7]>3'd3)?1'b1:1'b0;
    end
    else begin
      data_byte<=data_byte;
    end
  end
  always@(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
      uart_state<=1'b0;
    end
    else if(rxd_negedge==1'b1)begin
      uart_state<=1'b1;
    end
    else if(rxd_finish==1'b1||(bps_cnt==8'd12 && (Start>3'd3)))begin
      uart_state<=1'b0;
    end
    else begin
      uart_state<=uart_state;
    end
  end
endmodule

字符缓冲模块:


module uart_dat_buf(clk,rst_n,rxd_sel,rxd_finish,rxd_state,data_byte,led
    );
  input           clk       ;//输入时钟
  input           rst_n     ;//复位信号
  input           rxd_sel   ;//指令选择
  input           rxd_finish;//一位数据发送完成标志
  input           rxd_state ;//发送状态标志
  input     [7:0] data_byte ;
  output reg[7:0] led       ;
  parameter       TIME = 25'd2500_0000,
          S0 =4'd0,
          S1 =4'd1,
          S2 =4'd2,
          S3 =4'd3,
          S4 =4'd4,
          S5 =4'd5,
          S6 =4'd6,
          S7 =4'd7,
          S8 =4'd8,
          S9 =4'd9,
          S10=4'd10,
          ERROR =4'd15;
  //数据接收模块
  reg       [7:0] data_byte_temp;
  always@(*)begin
    if(rst_n==1'b0)begin
      data_byte_temp=8'd0;
    end
    else if(rxd_state==1'b1)begin
      data_byte_temp=data_byte;
    end
    else begin
      data_byte_temp=data_byte_temp;
    end
  end
  //状态转换
  reg [3:0] state_c;
  reg [3:0] state_n;
  always@(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
      state_c<=S0;
    end
    else if(rxd_state==1'b1)begin
      state_c<=state_c;
    end
    else begin
      state_c<=state_n;
    end
  end
  //状态判断
  always@(*)begin
    if(rst_n==1'b0)begin
      state_n=S0;
    end
    else if(rxd_sel==1'b0&&rxd_state==1'b1)begin
      case(state_c)
        S0 :
          if(data_byte_temp=="I")begin
            state_n=S1;
          end
          else begin
            state_n=ERROR;
          end
        S1 :
          if(data_byte_temp==" ")begin
            state_n=S2;
          end
          else begin
            state_n=ERROR;
          end
        S2 :
          if(data_byte_temp=="L")begin
            state_n=S3;
          end
          else begin
            state_n=ERROR;
          end
        S3 :
          if(data_byte_temp=="i")begin
            state_n=S4;
          end
          else begin
            state_n=ERROR;
          end
        S4 :
          if(data_byte_temp=="k")begin
            state_n=S5;
          end
          else begin
            state_n=ERROR;
          end
        S5 :
          if(data_byte_temp=="e")begin
            state_n=S6;
          end
          else begin
            state_n=ERROR;
          end
        S6 :
          if(data_byte_temp==" ")begin
            state_n=S7;
          end
          else begin
            state_n=ERROR;
          end
        S7 :
          if(data_byte_temp=="F")begin
            state_n=S8;
          end
          else begin
            state_n=ERROR;
          end
        S8 :
          if(data_byte_temp=="P")begin
            state_n=S9;
          end
          else begin
            state_n=ERROR;
          end
        S9 :
          if(data_byte_temp=="G")begin
            state_n=S10;
          end
          else begin
            state_n=ERROR;
          end
        S10:
          if(data_byte_temp=="A")begin
            state_n=S0;
          end
          else begin
            state_n=ERROR;
          end
        ERROR:if(data_byte_temp=="I")begin
            state_n=S1;
          end
          else begin
            state_n=ERROR;
          end
        default:state_n=S0;
      endcase
    end
    else begin
      state_n=state_n;
    end
  end
  reg [1:0] flag_led;
  //输出模块
  always@(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
      flag_led<=2'd3;
    end
    else if(rxd_sel==1'b1)begin
      flag_led<=2'b10;
    end
    else if(rxd_sel==1'b0)begin
      if(state_c==ERROR)begin
        flag_led<=2'b01;
      end
      else if(state_c==S10)begin
        flag_led<=2'b00;
      end
      else begin
        flag_led<=flag_led;
      end
    end
    else begin
      flag_led<=2'b11;
    end
  end
  //闪烁led设计
  reg  [24:0] cnt;//存放计数器的值
  //数码管特殊状态闪烁计数器模块
  always@(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
      cnt <=25'd0;
    end
    else if(cnt ==TIME-1'b1)begin
      cnt <=1'b0;
    end
    else if(flag_led==2'b01)begin
      cnt <=cnt + 1'b1;
    end
    else begin
      cnt <=25'd0;
    end
  end
  //led灯指示
  always@(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
      led<=8'b1111_1111;
    end
    else if(flag_led==2'b10)begin
      led<=data_byte_temp;
    end
    else if(flag_led==2'b00)begin
      led<=8'b0000_0000;
    end
    else if(flag_led==2'b01)begin
      if(cnt<(TIME/2-1'b1))begin
        led<=8'b1111_1111;
      end
      else begin
        led<=8'b0000_0000;
      end
    end
    else if(flag_led==2'b11)begin
      led<=8'b1111_1111;
    end
    else begin
      led<=led;
    end
  end
endmodule

顶层文件:


module uart_rxd_top(ext_clk_25m,ext_rst_n,uart_rx,led,switch0
    );
  input ext_clk_25m ;//系统时钟
  input ext_rst_n   ;//复位信号
  input uart_rx   ;//串口通信接收
  input switch0   ;//指令切换
  output [7:0]led   ;//led显示
  wire [7:0]data_byte;
  wire uart_state;
  wire rxd_finish;
  uart_rxd u_r1(
  .clk(ext_clk_25m),
  .rst_n(ext_rst_n),
  .bps_set(1), 
  .rxd(uart_rx),
  .data_byte(data_byte),
  .rxd_finish(rxd_finish),
  .uart_state(uart_state)
    );
  uart_dat_buf u_dat1(
  .clk(ext_clk_25m),
  .rst_n(ext_rst_n),
  .rxd_sel(switch0),
  .rxd_finish(rxd_finish),
  .rxd_state(uart_state),
  .data_byte(data_byte),
  .led(led)
    );
endmodule
目录
相关文章
|
8天前
|
算法 数据安全/隐私保护 异构计算
基于FPGA的16QAM调制+软解调系统,包含testbench,高斯信道模块,误码率统计模块,可以设置不同SNR
本项目基于FPGA实现了16QAM基带通信系统,包括调制、信道仿真、解调及误码率统计模块。通过Vivado2019.2仿真,设置不同SNR(如8dB、12dB),验证了软解调相较于传统16QAM系统的优越性,误码率显著降低。系统采用Verilog语言编写,详细介绍了16QAM软解调的原理及实现步骤,适用于高性能数据传输场景。
107 69
|
12天前
|
移动开发 算法 数据安全/隐私保护
基于FPGA的QPSK调制+软解调系统,包含testbench,高斯信道模块,误码率统计模块,可以设置不同SNR
本文介绍了基于FPGA的QPSK调制解调系统,通过Vivado 2019.2进行仿真,展示了在不同信噪比(SNR=1dB, 5dB, 10dB)下的仿真效果。与普通QPSK系统相比,该系统的软解调技术显著降低了误码率。文章还详细阐述了QPSK调制的基本原理、信号采样、判决、解调及软解调的实现过程,并提供了Verilog核心程序代码。
49 26
|
18天前
|
算法 异构计算
基于FPGA的4ASK调制解调系统,包含testbench,高斯信道模块,误码率统计模块,可以设置不同SNR
本文介绍了基于FPGA的4-ASK调制解调系统的算法仿真效果、理论基础及Verilog核心程序。仿真在Vivado2019.2环境下进行,分别测试了SNR为20dB、15dB、10dB时的性能。理论部分概述了4-ASK的工作原理,包括调制、解调过程及其数学模型。Verilog代码实现了4-ASK调制器、加性高斯白噪声(AWGN)信道模拟、解调器及误码率计算模块。
41 8
|
25天前
|
算法 物联网 异构计算
基于FPGA的4FSK调制解调系统,包含testbench,高斯信道模块,误码率统计模块,可以设置不同SNR
本文介绍了基于FPGA的4FSK调制解调系统的Verilog实现,包括高斯信道模块和误码率统计模块,支持不同SNR设置。系统在Vivado 2019.2上开发,展示了在不同SNR条件下的仿真结果。4FSK调制通过将输入数据转换为四个不同频率的信号来提高频带利用率和抗干扰能力,适用于无线通信和数据传输领域。文中还提供了核心Verilog代码,详细描述了调制、加噪声、解调及误码率计算的过程。
47 11
|
1月前
|
算法 数据安全/隐私保护 异构计算
基于FPGA的1024QAM基带通信系统,包含testbench,高斯信道模块,误码率统计模块,可以设置不同SNR
本文介绍了基于FPGA的1024QAM调制解调系统的仿真与实现。通过Vivado 2019.2进行仿真,分别在SNR=40dB和35dB下验证了算法效果,并将数据导入Matlab生成星座图。1024QAM调制将10比特映射到复数平面上的1024个星座点之一,适用于高数据传输速率的应用。系统包含数据接口、串并转换、星座映射、调制器、解调器等模块。Verilog核心程序实现了调制、加噪声信道和解调过程,并统计误码率。
44 1
|
2月前
|
算法 数据安全/隐私保护 异构计算
基于FPGA的64QAM基带通信系统,包含testbench,高斯信道模块,误码率统计模块,可以设置不同SNR
本文介绍了基于FPGA的64QAM调制解调通信系统的设计与实现,包括信号生成、调制、解调和误码率测试。系统在Vivado 2019.2中进行了仿真,通过设置不同SNR值(15、20、25)验证了系统的性能,并展示了相应的星座图。核心程序使用Verilog语言编写,加入了信道噪声模块和误码率统计功能,提升了仿真效率。
52 4
|
2月前
|
存储 算法 数据处理
基于FPGA的8PSK调制解调系统,包含testbench,高斯信道模块,误码率统计模块,可以设置不同SNR
本系统在原有的8PSK调制解调基础上,新增了高斯信道与误码率统计模块,验证了不同SNR条件下的8PSK性能。VIVADO2019.2仿真结果显示,在SNR分别为30dB、15dB和10dB时,系统表现出不同的误码率和星座图分布。8PSK作为一种高效的相位调制技术,广泛应用于无线通信中。FPGA凭借其高度灵活性和并行处理能力,成为实现此类复杂算法的理想平台。系统RTL结构展示了各模块间的连接与协同工作。
58 16
|
2月前
|
算法 数据安全/隐私保护 异构计算
基于FPGA的16QAM基带通信系统,包含testbench,高斯信道模块,误码率统计模块,可以设置不同SNR
本项目基于FPGA实现16QAM调制解调通信系统,使用Verilog语言编写,包括信道模块、误码率统计模块。通过设置不同SNR值(如8dB、12dB、16dB),仿真测试系统的误码性能。项目提供了完整的RTL结构图及操作视频,便于理解和操作。核心程序实现了信号的生成、调制、信道传输、解调及误码统计等功能。
50 3
|
1月前
|
算法 数据安全/隐私保护 异构计算
基于FPGA的256QAM基带通信系统,包含testbench,高斯信道模块,误码率统计模块,可以设置不同SNR
本文介绍了256QAM调制解调算法的仿真效果及理论基础。使用Vivado 2019.2进行仿真,分别在SNR为40dB、32dB和24dB下生成星座图,并导入Matlab进行分析。256QAM通过将8比特数据映射到复平面上的256个点,实现高效的数据传输。Verilog核心程序包括调制、信道噪声添加和解调模块,最终统计误码率。
35 0
|
2月前
|
算法 数据安全/隐私保护 异构计算
基于FPGA的16PSK调制解调系统,包含testbench,高斯信道模块,误码率统计模块,可以设置不同SNR
### 简介 本项目采用VIVADO 2019.2进行了十六进制相位移键控(16PSK)算法仿真,结果显示,在SNR=30dB时效果为Tttttttttttttt12,在SNR=20dB时效果为Tttttttttttttt34。系统RTL结构如Tttttttttttttt555555所示。16PSK是一种高效的相位调制技术,能在每个符号时间内传输4比特信息,适用于高速数据传输。其工作原理包括将比特流映射到16个相位状态之一(Tttttttttttttt777777),并通过匹配滤波和决策进行解调。具体Verilog核心程序见完整代码。
39 1

热门文章

最新文章