FPGA: RS译码仿真过程

这篇具有很好参考价值的文章主要介绍了FPGA: RS译码仿真过程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

FPGA: RS译码仿真过程

在上一篇中记录了在FPGA中利用RS编码IP核完成信道编码的仿真过程,这篇记录利用译码IP核进行RS解码的仿真过程,带有程序和结果。

1. 开始准备

在进行解码的过程时,同时利用上一篇中的MATLAB仿真程序和编码过程,IP核的下载是同样的地址。解码过程中的参数设置正好对应编码的过程。对0-15的自然数通过RS编码得到的数据进行解码,其中m=4,n=15,k=3,ploy=19

2. RS译码IP核

RS译码IP核全名Reed-Solomon Decoder,具体细节可以参照PDF技术文档,首先看IP核参数设置。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R32PpUta-1692190030739)(1.png “rs解码IP核设置1”)]

已经通过RS编码IP核完成了编码的仿真过程,并且通过MATLAB对比对结果进行了验证,所以这个第一个页码的参数直接参照如图设置就可以,与编码是一一对应的,没有什么需要特别的说明。
在下面的Variable Check Symbol Options不需要勾选。

FPGA: RS译码仿真过程,通信系统,FPGA,fpga开发,信道编码,RS编译码

在第二个参数设置界面,都不需要勾选,勾选的话译码输出的结果会带有校验的数据。

FPGA: RS译码仿真过程,通信系统,FPGA,fpga开发,信道编码,RS编译码

在第三个参数设置界面中,把Reset选项勾选上。

FPGA: RS译码仿真过程,通信系统,FPGA,fpga开发,信道编码,RS编译码

完成这个IP核的设置。

补充

为了方便利用仿真过程中的译码过程,在之前完成编码过程后添加了一个fifo方便进行数据处理和信号控制,其中的fifoIP核的参数设置为如下。

FPGA: RS译码仿真过程,通信系统,FPGA,fpga开发,信道编码,RS编译码

FPGA: RS译码仿真过程,通信系统,FPGA,fpga开发,信道编码,RS编译码

FPGA: RS译码仿真过程,通信系统,FPGA,fpga开发,信道编码,RS编译码

这个fifo根据需要设置即可,主要是为了编码之后的数据和译码过程使用控制方便。

3. 代码编写

译码过程是在编码基础上添加的,编码过程的参数没有变化,对0-15的数据进行编码,然后再进行译码,在编码和译码过程中间有一个fifo,其中fifo的读控制信号利用empty信号和译码IP的s_ready信号,fifo的写信号编码信号的输出valid信号。详细的逻辑看代码。

代码如下rs_test.v

`timescale 1ns / 1ps

module rs_test(
    input clk,          //时钟
    input rst_n         // 复位  高电平复位
//    input [7:0] data_in,  // 输入的待编码数据
//    output [7:0] dataout      // 输出的解码数据
    );

wire rs_encode_input_tready;  // 编码输入准备信号
reg rs_encode_input_tvalid_reg;  // 编码输入有效信号
reg rs_encode_input_tready_reg;
wire rs_encode_input_tlast;
reg rs_encode_input_tlast_reg;
wire[7:0] rs_encode_data;
wire rs_encode_output_tvalid;
wire rs_encode_output_tlast;
wire rs_enocde_output_tready;
reg rs_enocde_output_tready_reg;

parameter K = 3;   //  对应MATLAB仿真中的k和n的值,这个在IP核设置中已经有体现
parameter N = 4;   //
parameter L = 15;  // 编码之后的数据长度

reg [3:0] datain_num; // 每一组编码的原始数据个数
reg [5:0] dataout_num;  //输出编码数据的个数

wire fifo_full; // fifo 满信号

// 设计输入数据
reg [3:0] datain;
always@(posedge clk)begin
    if(~rst_n)begin
        datain <= 4'b0;
        rs_encode_input_tready_reg <= 1'b0;
        rs_encode_input_tvalid_reg <= 1'b0;
        rs_encode_input_tlast_reg <= 1'b0;
        rs_enocde_output_tready_reg <= 1'b0;
        datain_num <= 4'b0;
    end
    else begin
        rs_encode_input_tready_reg <= rs_encode_input_tready;
        if(fifo_full==1'b1)begin
            rs_encode_input_tvalid_reg <= 1'b0;
        end
        else begin
            rs_encode_input_tvalid_reg <= 1'b1;
        end
        
        if(rs_encode_input_tready == 1'b1 && rs_encode_input_tvalid_reg == 1'b1)begin // 在ready 和valid信号都有效的时候才开始编码数据,可以在这里计数编码的个数。
            datain <= datain + 4'b1;
            datain_num <= 4'b1 + datain_num;
            rs_enocde_output_tready_reg <= 1'b1;
        end
        else begin
        end
    end
end

// 根据每一组编码的组数来确定数据顺序 控制最后一个tlast信号。
always@(posedge clk)begin
    if(~rst_n)begin
        rs_encode_input_tlast_reg <= 1'b0; // 这个信号是需要在一组中的最后一个数据时候信号处于高电平 和k的大小对应
    end
    else begin
        if(datain_num >= K)begin
            rs_encode_input_tlast_reg <= 1'b1;
        end
        else begin
            rs_encode_input_tlast_reg <= 1'b0;  //然后重新置零
        end
    end
end

wire [3:0] data_in;
assign data_in = datain;

rs_encoder_0 rs_encoder_0_ins (   //latency 5clk
  .aclk(clk),                                                      // input wire aclk
  .aresetn(rst_n),                                                // input wire aresetn
  .s_axis_input_tdata(data_in),                          // input wire [7 : 0] s_axis_input_tdata
  .s_axis_input_tvalid(rs_encode_input_tvalid_reg),                        // input wire s_axis_input_tvalid
  .s_axis_input_tready(rs_encode_input_tready),                        // output wire s_axis_input_tready
  .s_axis_input_tlast(rs_encode_input_tlast_reg),                          // input wire s_axis_input_tlast
  .m_axis_output_tdata(rs_encode_data),                        // output wire [7 : 0] m_axis_output_tdata
  .m_axis_output_tvalid(rs_encode_output_tvalid),                      // output wire m_axis_output_tvalid
  .m_axis_output_tready(rs_enocde_output_tready_reg),                      // input wire m_axis_output_tready
  .m_axis_output_tlast(rs_encode_output_tlast)                       // output wire m_axis_output_tlast
);

// 通过编码模块输出的valid信号和ready信号来记录输出数据的个数
always@(posedge clk)begin
    if(~rst_n)begin
        dataout_num <= 6'b0;
    end
    else begin
        if(rs_encode_output_tvalid==1'b1 && rs_enocde_output_tready_reg==1'b1)begin
            dataout_num <= dataout_num + 6'b1;
            if(dataout_num >= 6'd15)begin
                dataout_num <= 6'b0;
            end
        end
        else begin
            
        end
    end
end

// rs 译码过程
// 在编码之后的数据添加一个fifo  方便管理valid信号和ready信号,减少耦合同时可以比配位宽
wire fifo_empty;
wire fifo_rd_en;

wire[3:0] fifo_data;
reg fifo_flag;  // 这个是用来标致第一次从fifo中读取数据的过程

wire [7:0] rs_decode_data_temp;
wire [3:0] rs_decode_data;
//in
wire rs_decode_data_s_ready;
wire rs_decode_data_s_valid;
reg rs_decode_data_s_valid_reg;  // 去掉fifo 输出的一个时钟延迟
reg rs_decode_data_s_tlast_reg;
assign fifo_rd_en = rs_decode_data_s_ready && (!fifo_empty);
// out
wire rs_decode_data_m_valid;
wire rs_decode_data_m_tlast;
wire rs_decode_data_m_ready;
// stat
wire [7:0] rs_decode_stat_data;
//wire rs_decode_stat_ready;
wire rs_decode_stat_valid;

always@(posedge clk)begin
    if(~rst_n)begin
        fifo_flag <= 1'b0;
    end
    else begin
        if(fifo_rd_en==1'b1)begin
            fifo_flag <= 1'b1;
        end
    end
end

always@(posedge clk)begin
    if(~rst_n)begin
        rs_decode_data_s_valid_reg <= 1'b0;
    end
    else begin
        rs_decode_data_s_valid_reg <= fifo_rd_en;
    end
end

fifo_generator_0 fifo_ins( // 这个输出有1clk延迟
  .clk(clk),      // input wire clk
  .srst(~rst_n),    // input wire srst
  .din(rs_encode_data[3:0]),      // input wire [3 : 0] din
  .wr_en(rs_encode_output_tvalid),  // input wire wr_en
  .rd_en(fifo_rd_en),  // input wire rd_en
  .dout(fifo_data),    // output wire [3 : 0] dout  
  .full(fifo_full),    // output wire full
  .empty(fifo_empty)  // output wire empty
);
// 输入编码中的有效信号
assign rs_decode_data_s_valid = (fifo_flag==1'b1)?fifo_rd_en:rs_decode_data_s_valid_reg; // 在第一次读取的时候 信号跟随reg信号,之后跟随en信号
reg[5:0] decode_num;
always@(posedge clk)begin
    if(~rst_n)begin
        decode_num = 6'b1;
    end
    else begin
        if(rs_decode_data_s_valid==1'b1)begin
            decode_num <= decode_num + 6'b1;
            if(decode_num >= 6'd14)begin
                decode_num <= 6'b0;
            end
        end
    end
end
// 控制tlast信号
always@(posedge clk)begin
    if(~rst_n)begin
        rs_decode_data_s_tlast_reg <= 1'b0;
    end
    else begin //当解码输入进入的数据为一组时,拉高tlast信号;
        if(decode_num >= 6'd14)begin
            rs_decode_data_s_tlast_reg <= 1'b1;
        end
        else begin
            rs_decode_data_s_tlast_reg <= 1'b0;
        end
    end
end

rs_decoder_0 rs_decoder_0_ins (
  .aclk(clk),                                                      // input wire aclk
  .aresetn(rst_n),                                                // input wire aresetn
  .s_axis_input_tdata(fifo_data),                          // input wire [7 : 0] s_axis_input_tdata
  .s_axis_input_tvalid(rs_decode_data_s_valid),                        // input wire s_axis_input_tvalid
  .s_axis_input_tlast(rs_decode_data_s_tlast_reg),                          // input wire s_axis_input_tlast
  .s_axis_input_tready(rs_decode_data_s_ready),                        // output wire s_axis_input_tready
  .m_axis_output_tdata(rs_decode_data_temp),                        // output wire [7 : 0] m_axis_output_tdata
  .m_axis_output_tvalid(rs_decode_data_m_valid),                      // output wire m_axis_output_tvalid
  .m_axis_output_tready(1'b1),                      // input wire m_axis_output_tready
  .m_axis_output_tlast(rs_decode_data_m_tlast),                        // output wire m_axis_output_tlast
  .m_axis_stat_tdata(rs_decode_stat_data),                            // output wire [7 : 0] m_axis_stat_tdata
  .m_axis_stat_tvalid(rs_decode_stat_valid),                          // output wire m_axis_stat_tvalid
  .m_axis_stat_tready(1'b1)                          // input wire m_axis_stat_tready
);

assign rs_decode_data = rs_decode_data_temp[3:0];

endmodule

4. 仿真测试

测试程序的testbench文件和之前保持一致,只需要把实例化的模块名字更改即可。

`timescale 1ns / 1ps
module rs_tb();

reg l_clk;
reg rst_n;

rs_test rs_test_ins(
    .clk(l_clk),          //时钟
    .rst_n(rst_n)         // 复位  高电平复位
    );
initial l_clk = 1;
always #5 l_clk= !l_clk;  //15.625   

initial begin
    rst_n <= 0;
    #40;
    rst_n <= 1;
    #320;
    //#50000000;
    #320;
//    $stop;
end
endmodule

然后进入仿真过程,对照时序查看结果。

FPGA: RS译码仿真过程,通信系统,FPGA,fpga开发,信道编码,RS编译码

首先看试验大图,其中的蓝色线是解码之后的数据,从数据结果中可以看出每个数据间隔3,正好是编码之前的结果,拉开蓝色线就可以看到具体的数值。因为译码也是存在延时的,所以看起来数据会滞后,蓝色数据线的m_valid信号对应输出数据有效信号。

这里面有需要注意的地方,首先看仿真结果的前面部分。

FPGA: RS译码仿真过程,通信系统,FPGA,fpga开发,信道编码,RS编译码

这是fifo_rd_en有效的第一段,由于有1个clk的时钟延迟,所以把有效信号rs_decode_data_s_valid信号需要延迟一个clk,然后看接下来的fifo_rd_en第二个周期,需要把rs_decode_data_s_valid信号和fifo_rd_en信号对齐,否则会丢一个数据,后面的和第二个周期相同,只有第一个需要延迟一个周期,这个在程序中通过fifo_flag判断是不是第一个周期。

FPGA: RS译码仿真过程,通信系统,FPGA,fpga开发,信道编码,RS编译码

至此完成了译码的过程。文章来源地址https://www.toymoban.com/news/detail-720062.html

到了这里,关于FPGA: RS译码仿真过程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • m基于FPGA的RS+卷积级联编译码实现,RS用IP核实现,卷积用verilog实现,包含testbench测试文件

    目录 1.算法仿真效果 2.算法涉及理论知识概要 2.1 卷积码编码 2.2 RS码编码 2.3 级联编码 2.4 解码过程 3.Verilog核心程序 4.完整算法代码文件获得 Vivado2019.2仿真结果如下:         级联码是一种通过将两种或多种纠错码结合使用来提高纠错能力的编码方案。在RS+卷积级联编码中,

    2024年02月22日
    浏览(38)
  • FPGA学习小例子:38译码器设计与仿真

    译码器74x138是数字电路课程重点内容之一。译码器的设计比 较简单,使用Verilog语言实现译码器就更为简单。本教程设计了一个3-8译码器并做了仿真。 打开vivado,点击File 填写项目名,以及选择项目路径 并勾选“Do not specify sources at this time”,意思是先创建工程,后期再添加

    2024年02月09日
    浏览(38)
  • 通信信号处理技术(8)-卷积码译码FPGA优化分析1

    在FPGA实现卷积编解码的过程中,如何有效的利用FPGA资源并加快信号处理的过程,关系到无线通信系统能够处理信息的带宽,即一定程度上决定了系统的业务能力。以下分析能够优化系统性能的方法。 提高FPGA系统的处理速度,即时钟速度。提高时钟速度能一定程度的加快信号

    2024年02月07日
    浏览(38)
  • FPGA实现串口通信(RS232)含代码

    带有CH340的FPAG开发板 该模块的功能是接收通过 PC 机上的串口调试助手发送的固定波特率的数据,串口接收模块按照串口的协议准确接收串行数据,解析提取有用数据后需将其转化为并行数据;简单的说,接收模块的功能就是 解析+串转并 ; 具体实现步骤如下: 1、算出波特

    2024年02月02日
    浏览(41)
  • FPGA与RS485通信:从入门到精通

    FPGA与RS485通信:从入门到精通 FPGA(Field-Programmable Gate Array)作为一种可编程逻辑芯片,因其高度灵活、低功耗、高性能等特点,被广泛应用于工业自动化、通信、医疗等领域。而RS485作为一种串行通信协议,具有距离远、速率快、可靠性高等特点,也是工业自动化中常用的通

    2024年01月18日
    浏览(60)
  • FPGA串口(RS422)调试笔记:理解串口通信与调试记录

    探索FPGA串口(RS422)通信的调试过程与记录,包括串口通信概念解析、调试步骤、代码示例以及数据拼接方法。记录调试中遇到的问题与解决方案,展示对串口通信功能的实现与乐趣体验。

    2023年04月08日
    浏览(33)
  • OFDM通信系统的LS信道估计均衡算法matlab仿真

    目录 一、理论基础 二、核心程序 三、仿真结论       OFDM主要思想是:将信道分成若干正交子信道,将高速数据信号转换成并行的低速子数据流,调制到在每个子信道上进行传输。正交信号可以通过在接收端采用相关技术来分开,这样可以减少子信道之间的相互干扰(ISI) 。

    2024年02月06日
    浏览(27)
  • 香山处理器跑仿真和跑FPGA两套环境配置过程小结

    ============================================ 裸机ubuntu18.04上运行香山处理器(南湖)make verilog ============================================ system program problem detected - sudo vi /etc/default/apport sudo apt install tree git cmake curl sudo apt install bison flex  sudo apt install verilator sudo apt install default-jre sudo sh -c \\\"curl -L

    2024年02月14日
    浏览(31)
  • FPGA学习笔记(三)——串口通信之发送数据(调试过程)

    本学习笔记主要参考小梅哥B站教学视频,网址如下: https://www.bilibili.com/video/BV1va411c7Dz?p=1 使用的编译器为Vivado,HDL语言为verilog 一、串口通信之发送数据 原理 设计代码 测试代码 仿真结果 发现Send_en拉高之前,uart_tx就置为0了,不符合常理。 转到第二个发送信号处,发现Send

    2023年04月09日
    浏览(36)
  • DSP与FPGA通过XINTF并行通信的实验过程

    DSP与FPGA通过XINTF并行通信的实验过程(FPGA是小梅哥家XILINX的A7系列,DSP是普中家的C28335系列) DSP和FPGA都是用的开发板,用的普通的杜邦线连接(16bit),然后在VIVADO当中用ila观察信号,在DSP当中用仿真器观察变量数值,对于XINTF的读写,其实是先要定义一段zone当中的地址,然

    2024年02月04日
    浏览(60)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包