`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。