数字通信模块数据处理--FPGA实现标准帧的选取

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2024/10/31 17:00:24
// Design Name: 
// Module Name: Standard code module
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//
module Standard_code(
    input clk,
    input rst,
    output reg [31:0] correct_frame_count // 正确帧计数
);

    // 状态定义
    parameter IDLE = 3'b000;
    parameter STATE1 = 3'b001;
    parameter STATE2 = 3'b010;
    parameter STATE3 = 3'b011;
    parameter STATE4 = 3'b111;

    reg [2:0] current_state, next_state;
    reg [9:0] compare_counter; // 用于计数对比的字节数

    // 实例化ROM和RAM IP核
    reg ena;
    reg [9:0] addr;
    wire [7:0]douta;
    reg [7:0] douta_reg;
    reg [7:0] douta_reg_1;//compare
    
    blk_mem_gen_0 rom_0 (
      .clka(clk),    // input wire clka
      .ena(ena),      // input wire ena
      .addra(addr),  // input wire [9 : 0] addra
      .douta(douta)  // output wire [7 : 0] douta
);      
    reg wea  ;
    reg  enb  ;
    wire [7:0] doutb;
    
    reg [9:0] addr_ram;  
    blk_mem_gen_1 ram_0 (
      .clka(clk),    // input wire clka
      .wea(wea),      // input wire [0 : 0] wea
      .addra(addr_ram),  // input wire [9 : 0] addra
      .dina(douta),    // input wire [7 : 0] dina
      .clkb(clk),    // input wire clkb
      .enb(enb),      // input wire enb
      .addrb(addr_ram),  // input wire [9 : 0] addrb
      .doutb(doutb)  // output wire [7 : 0] doutb
    );
    // 地址累加逻辑
    always @(posedge clk or posedge rst) begin
        if (rst) begin
            addr <= 0;
            compare_counter <= 0; // 重置对比计数器
        end else if (ena || enb|| wea) begin
            if (addr < 10'd1023) begin
                addr <= addr + 1;
            end else begin
                addr <= 0;
            end
            
        end
        addr_ram<=addr;
        douta_reg<=douta;
        douta_reg_1<=douta_reg;
    end

    // 状态转移逻辑
    always @(posedge clk or posedge rst) begin
        if (rst) begin
            current_state <= IDLE;
            compare_counter <= 0; // 初始化对比计数器
        end else begin
            current_state <= next_state;
            compare_counter <= compare_counter; // 初始化对比计数器
        end
    end

    // 状态机逻辑
    always @(*) begin
        // 默认状态
        case (current_state)
            IDLE: begin
                   if(ena)begin                  
                    next_state = STATE1; // 进入第一个状态
                    end else begin
                    next_state = IDLE;
                    end
                   end

            STATE1: begin
                if (correct_frame_count==0 && addr < 10'd1023) begin
                    next_state = STATE1; // 循环在此状态
                end else if (addr == 10'd1023) begin
                    next_state = STATE2; // 跳转到第二状态 状态1:ROM中的数据写如RAM中。
                end
            end
            STATE2: begin                                                  //RAM开始输出,他0的时候在这循环,并不能回到重新写RAM的
                if (correct_frame_count==0 && compare_counter < 10'd1023) begin      //状态,所以分开;
                    next_state = STATE2; // 循环在此状态                    //思路分析:如过程中出现错误帧,需要重新归0,就得回到状态1,                                                                                                                                             
                end else begin                                            //重新写入RAM,回到状态1,如果程序刚开始运行的过程时正确帧为0,
                    next_state = STATE3; // 跳转到第三状态                  //就在状态2. 
                end                                                       //突然想到,我可以按照流水线的方式编写,如果他能跳转的下一步
            end                                                           //就说明状态良好,状态不好就都回到初始化状态。
            STATE3: begin                                                 //RAM开始输出,
                if (0<correct_frame_count&&correct_frame_count<=5) 
                    next_state = STATE3; // 循环在此状态
                else if(correct_frame_count==0) 
                    next_state = STATE1; // 跳转到第三状态              
                else 
                    next_state = STATE4;  
            end

            STATE4: begin
                next_state = STATE4; // 循环在此状态
            end
            default: next_state = IDLE; // 默认状态
        endcase
    end
 always @(posedge clk or posedge rst) begin
        if (rst) begin
            ena   <= 0;
            wea   <= 0;
            enb   <= 0;
        end else begin
            case (current_state)
                IDLE: begin
                    ena   <= 1;
                    wea   <= 1;
                    enb   <= 0;  // 初始状态,所有模块禁用

                end
                STATE1: begin
                    ena <= 1;  // 使能ROM_1
                    wea <= 1;
                    enb <= 0;
 
                end
                STATE2: begin
                    ena <= 1;
                    wea <= 0;  // 使能LFSR
                    enb <= 1;
                end
                 STATE3: begin
                    ena <= 1;  // 使能ROM_1
                    wea <= 0;
                    enb <= 1;
 
                end
                STATE4: begin
                    ena <= 0;
                    wea <= 0;  // 使能LFSR
                    enb <= 1;
                end

                default: begin
                    wea <= 0;
                    ena <= 0;
                    enb <= 0;  // 默认情况下所有模块禁用
                end
            endcase 
        end
    end
//控制条件重复的情况,开始正确帧为0的情况和出现错误帧时正确帧数重新置为0情况

    // 对比模块
    always @(posedge clk or posedge rst) begin
        if (rst) begin
            correct_frame_count <= 0; // 复位计数器
            compare_counter <= 0; // 重置对比计数器
        end else if (ena&&enb) begin
            // 从RAM读取数据
            // 对比数据
            if ((douta_reg ^ doutb) == 16'h0000) begin
                compare_counter <= compare_counter + 1; // 数据完全正确,计数加1
                // 如果对比完一帧数据
                if (compare_counter == 10'd1023) begin
                    correct_frame_count <= correct_frame_count + 1; // 增加正确帧计数                  
                end else begin
                    correct_frame_count <=correct_frame_count;
                end          
            end else begin
                correct_frame_count <=0;//判断出错误帧,置为0,状态跳转到1.
                compare_counter <= 0; // 数据不相同,重置计数
            end
        end
    end

endmodule

数据源对比标准帧:

第一步:ROM当做数据源:使能开启,使用地址addr控制其输出。(使用状态机写入RAM时的控制选用addr)

RAM作为标准帧的缓存,使用addr_ram作为RAM的写入地址。

此时ROM的地址比RAM的地址延迟了一个节拍;(addr_ram<=addr;)

第二步:RAM缓存写满之后开启对比。

RAM输出使能开启。

由于当遇到两帧不相同时需要重新将值写入RAM中,所以状态机的设计:一、写入RAM;二、对比第一帧;三、对比第二之第五帧,(关键点:如果正确帧为1~5则在本状态循环,如果正确帧为0,则跳回状态1,重新写入RAM,如果正确帧大于5,则跳入下一状态)。

判断模块:ena&&enb作为判断条件,两个寄存器的值异或,结果为0,继续判断1024个完全相同则正确帧数加1;如果任意一个不相同则正帧数置为0,状态跳转,重新写入RAM。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值