1概述 上面的课程,我们完成了对TMDS三通道数据的拆分,成功提取出数据岛部分的4bit数据,本讲我们需要将4bit的island data数据恢复成BCH块的形式,方便我们对原始数据的恢复。 2原理部分
关于BCH块编解码原理的介绍,我们前面的课程已经讲解过了,本章节我们要做的就是逆向恢复出BCH block数据。首先我们通过串并转换恢复出32bit的Channel 0[0:3] ~ Channel 2[0:3]数据。然后对Channel 0~Channel 2的数据进行拆分重组。 3代码部分
3.1data_island_bch_assembler.v模块该模块为HDMI数据岛周期BCH编码组装器,负责将HDMI控制周期的并行数据流重组为符合BCH纠错编码规范的结构化数据块。其通过三路输入通道接收TMDS编码后的4位数据岛信息(含同步信号、音频及辅助数据),利用多级移位寄存器对数据进行位序列重组,最终输出符合HDMI 1.4b规范(CTA-861标准)的5个BCH编码块(4×64位+1×32位)。同时模块集成同步信号提取功能,可分离垂直/水平同步信号,为后续BCH校验及TMDS传输提供标准化的数据封装接口。
- `timescale 1ns / 1ps
- //////////////////////////////////////////////////////////////////////////////////
- // 模块名称:HDMI数据岛BCH编码组装器
- // 功能描述:将HDMI数据岛周期的并行数据重组为BCH纠错码块结构
- // 关键特性:
- // - 支持HDMI 1.4b规范的数据岛协议
- // - 生成5个BCH块(4个64bit + 1个32bit)
- // - 集成数据有效性校验机制
- //////////////////////////////////////////////////////////////////////////////////
-
- module data_island_bch_assembler(
- input wire I_pixel_clk, // 像素时钟(与TMDS字符速率同步)
- input wire I_reste_n, // 异步复位(低有效,注意命名应为reset_n)
- input wire [3:0] I_island_data_ch0, // 数据岛通道0输入(含VSYNC/HSYNC)
- input wire [3:0] I_island_data_ch1, // 数据岛通道1输入(音频/辅助数据)
- input wire [3:0] I_island_data_ch2, // 数据岛通道2输入(音频/辅助数据)
- input wire I_island_data_vaild, // 数据有效标志(高电平有效)
-
- // BCH块输出(符合HDMI规范第6.4节结构)
- output reg [63:0] O_BCH_block_0 , // BCH块0(交叉组合通道1&2数据)
- output reg [63:0] O_BCH_block_1 , // BCH块1(交叉组合通道1&2数据)
- output reg [63:0] O_BCH_block_2 , // BCH块2(交叉组合通道1&2数据)
- output reg [63:0] O_BCH_block_3 , // BCH块3(交叉组合通道1&2数据)
- output reg [31:0] O_BCH_block_4 , // BCH块4(直接来自通道0数据)
- output reg O_block_data_vaild, // BCH块有效标志
- output reg O_vsync, // 垂直同步输出
- output reg O_hsync // 水平同步输出
- );
-
- // 控制信号寄存器组
- reg [4:0] r_block_data_cunt; // BCH块数据计数器(注意命名应为count)
- reg r_block_data_vaild; // 块数据有效中间信号
- reg r_island_data_ch0_d0; // 通道0数据延迟寄存器(第0级)
- reg r_island_data_ch0_d1; // 通道0数据延迟寄存器(第1级)
- reg r_island_data_vaild; // 有效信号延迟寄存器
-
- reg [31:0] r_island_data_ch0_d2; // 通道0数据位2的移位寄存器
-
- // 通道1数据移位寄存器组(4bit输入展开为32bit)
- reg [31:0] r_island_data_ch1_d0; // 通道1数据位0的移位寄存器
- reg [31:0] r_island_data_ch1_d1; // 通道1数据位1的移位寄存器
- reg [31:0] r_island_data_ch1_d2; // 通道1数据位2的移位寄存器
- reg [31:0] r_island_data_ch1_d3; // 通道1数据位3的移位寄存器
-
- // 通道2数据移位寄存器组(同通道1结构)
- reg [31:0] r_island_data_ch2_d0; // 通道2数据位0移位寄存器
- reg [31:0] r_island_data_ch2_d1; // 通道2数据位1移位寄存器
- reg [31:0] r_island_data_ch2_d2; // 通道2数据位2移位寄存器
- reg [31:0] r_island_data_ch2_d3; // 通道2数据位3移位寄存器
-
- // BCH块数据计数器(每个块32个有效数据)
- always @(posedge I_pixel_clk or negedge I_reste_n) begin
- if (!I_reste_n) begin
- r_block_data_cunt <= 'b0; // 复位清零
- end
- else begin
- if (I_island_data_vaild && r_block_data_cunt <= 5'h1E)
- r_block_data_cunt <= r_block_data_cunt + 1; // 有效数据计数
- else
- r_block_data_cunt <= 'b0; // 计数器归零
- end
- end
-
- // BCH块有效信号生成(计数满30周期触发)
- always @(posedge I_pixel_clk or negedge I_reste_n) begin
- if (!I_reste_n)
- r_block_data_vaild <= 'b0;
- else if (r_block_data_cunt == 5'h1E) // 达到30计数时
- r_block_data_vaild <= 1; // 置位有效信号
- else
- r_block_data_vaild <= 'b0;
- end
-
- // 有效信号延迟一拍
- always @(posedge I_pixel_clk or negedge I_reste_n) begin
- if (!I_reste_n)
- r_island_data_vaild <= 'b0;
- else
- r_island_data_vaild <= r_block_data_vaild; // 同步时序
- end
-
- // 输出有效信号生成
- always @(posedge I_pixel_clk) begin
- if (!I_reste_n)
- O_block_data_vaild <= 'b0;
- else
- O_block_data_vaild <= r_island_data_vaild; // 最终有效信号
- end
-
- // 数据移位寄存器处理(通道1&2数据重组)
- always @(posedge I_pixel_clk or negedge I_reste_n) begin
- if (!I_reste_n) begin // 复位初始化
- r_island_data_ch0_d2 <= 'b0;
-
- r_island_data_ch1_d0 <= 'b0;
- r_island_data_ch1_d1 <= 'b0;
- r_island_data_ch1_d2 <= 'b0;
- r_island_data_ch1_d3 <= 'b0;
-
- r_island_data_ch2_d0 <= 'b0;
- r_island_data_ch2_d1 <= 'b0;
- r_island_data_ch2_d2 <= 'b0;
- r_island_data_ch2_d3 <= 'b0;
- end
- else if (I_island_data_vaild) begin // 有效数据周期
- // 通道0数据移位(bit2)
- r_island_data_ch0_d2 <= {I_island_data_ch0[2],r_island_data_ch0_d2[31:1]};
-
- // 通道1四bit数据分别移位
- r_island_data_ch1_d0 <= {I_island_data_ch1[0],r_island_data_ch1_d0[31:1]};
- r_island_data_ch1_d1 <= {I_island_data_ch1[1],r_island_data_ch1_d1[31:1]};
- r_island_data_ch1_d2 <= {I_island_data_ch1[2],r_island_data_ch1_d2[31:1]};
- r_island_data_ch1_d3 <= {I_island_data_ch1[3],r_island_data_ch1_d3[31:1]};
-
- // 通道2四bit数据分别移位(同通道1)
- r_island_data_ch2_d0 <= {I_island_data_ch2[0],r_island_data_ch2_d0[31:1]};
- r_island_data_ch2_d1 <= {I_island_data_ch2[1],r_island_data_ch2_d1[31:1]};
- r_island_data_ch2_d2 <= {I_island_data_ch2[2],r_island_data_ch2_d2[31:1]};
- r_island_data_ch2_d3 <= {I_island_data_ch2[3],r_island_data_ch2_d3[31:1]};
- end
- else begin // 非有效周期清零
- r_island_data_ch0_d2 <= 'b0;
-
- r_island_data_ch1_d0 <= 'b0;
- r_island_data_ch1_d1 <= 'b0;
- r_island_data_ch1_d2 <= 'b0;
- r_island_data_ch1_d3 <= 'b0;
-
- r_island_data_ch2_d0 <= 'b0;
- r_island_data_ch2_d1 <= 'b0;
- r_island_data_ch2_d2 <= 'b0;
- r_island_data_ch2_d3 <= 'b0;
- end
- end
-
- // 通道0 bit0数据延迟链(生成HSYNC)
- always @(posedge I_pixel_clk or negedge I_reste_n) begin
- if (!I_reste_n) begin
- r_island_data_ch0_d0 <= 'b0;
- end
- else
- r_island_data_ch0_d0 <= I_island_data_ch0[0]; // 同步输入数据
- end
-
- // HSYNC信号输出
- always @(posedge I_pixel_clk or negedge I_reste_n) begin
- if (!I_reste_n) begin
- O_hsync <= 'b0;
- end
- else
- O_hsync <= r_island_data_ch0_d0; // 直接输出延迟后的信号
- end
-
- // 通道0 bit1数据延迟链(生成VSYNC)
- always @(posedge I_pixel_clk or negedge I_reste_n) begin
- if (!I_reste_n) begin
- r_island_data_ch0_d1 <= 'b0;
- end
- else
- r_island_data_ch0_d1 <= I_island_data_ch0[1]; // 同步输入数据
- end
-
- // VSYNC信号输出
- always @(posedge I_pixel_clk or negedge I_reste_n) begin
- if (!I_reste_n) begin
- O_vsync <= 'b0;
- end
- else
- O_vsync <= r_island_data_ch0_d1; // 直接输出延迟后的信号
- end
-
- // BCH块0组装逻辑(通道1&2数据交叉排列)
- always @(posedge I_pixel_clk or negedge I_reste_n) begin
- if (!I_reste_n) begin
- O_BCH_block_0 <= 'b0;
- end
- else begin
- if (r_island_data_vaild)
- O_BCH_block_0 <= {r_island_data_ch2_d0[31],r_island_data_ch1_d0[31],r_island_data_ch2_d0[30],r_island_data_ch1_d0[30],
- r_island_data_ch2_d0[29],r_island_data_ch1_d0[29],r_island_data_ch2_d0[28],r_island_data_ch1_d0[28],
- r_island_data_ch2_d0[27],r_island_data_ch1_d0[27],r_island_data_ch2_d0[26],r_island_data_ch1_d0[26],
- r_island_data_ch2_d0[25],r_island_data_ch1_d0[25],r_island_data_ch2_d0[24],r_island_data_ch1_d0[24],
- r_island_data_ch2_d0[23],r_island_data_ch1_d0[23],r_island_data_ch2_d0[22],r_island_data_ch1_d0[22],
- r_island_data_ch2_d0[21],r_island_data_ch1_d0[21],r_island_data_ch2_d0[20],r_island_data_ch1_d0[20],
- r_island_data_ch2_d0[19],r_island_data_ch1_d0[19],r_island_data_ch2_d0[18],r_island_data_ch1_d0[18],
- r_island_data_ch2_d0[17],r_island_data_ch1_d0[17],r_island_data_ch2_d0[16],r_island_data_ch1_d0[16],
- r_island_data_ch2_d0[15],r_island_data_ch1_d0[15],r_island_data_ch2_d0[14],r_island_data_ch1_d0[14],
- r_island_data_ch2_d0[13],r_island_data_ch1_d0[13],r_island_data_ch2_d0[12],r_island_data_ch1_d0[12],
- r_island_data_ch2_d0[11],r_island_data_ch1_d0[11],r_island_data_ch2_d0[10],r_island_data_ch1_d0[10],
- r_island_data_ch2_d0[9 ],r_island_data_ch1_d0[9 ],r_island_data_ch2_d0[8 ],r_island_data_ch1_d0[8 ],
- r_island_data_ch2_d0[7 ],r_island_data_ch1_d0[7 ],r_island_data_ch2_d0[6 ],r_island_data_ch1_d0[6 ],
- r_island_data_ch2_d0[5 ],r_island_data_ch1_d0[5 ],r_island_data_ch2_d0[4 ],r_island_data_ch1_d0[4 ],
- r_island_data_ch2_d0[3 ],r_island_data_ch1_d0[3 ],r_island_data_ch2_d0[2 ],r_island_data_ch1_d0[2 ],
- r_island_data_ch2_d0[1 ],r_island_data_ch1_d0[1 ],r_island_data_ch2_d0[0 ],r_island_data_ch1_d0[0 ]};
- else O_BCH_block_0 <= 'b0;
- end
-
- end
-
- // BCH块1组装逻辑(通道1&2数据交叉排列)
- always @(posedge I_pixel_clk or negedge I_reste_n) begin
- if (!I_reste_n) begin
- O_BCH_block_1 <= 'b0;
- end
- else begin
- if (r_island_data_vaild)
- O_BCH_block_1 <= {r_island_data_ch2_d1[31],r_island_data_ch1_d1[31],r_island_data_ch2_d1[30],r_island_data_ch1_d1[30],
- r_island_data_ch2_d1[29],r_island_data_ch1_d1[29],r_island_data_ch2_d1[28],r_island_data_ch1_d1[28],
- r_island_data_ch2_d1[27],r_island_data_ch1_d1[27],r_island_data_ch2_d1[26],r_island_data_ch1_d1[26],
- r_island_data_ch2_d1[25],r_island_data_ch1_d1[25],r_island_data_ch2_d1[24],r_island_data_ch1_d1[24],
- r_island_data_ch2_d1[23],r_island_data_ch1_d1[23],r_island_data_ch2_d1[22],r_island_data_ch1_d1[22],
- r_island_data_ch2_d1[21],r_island_data_ch1_d1[21],r_island_data_ch2_d1[20],r_island_data_ch1_d1[20],
- r_island_data_ch2_d1[19],r_island_data_ch1_d1[19],r_island_data_ch2_d1[18],r_island_data_ch1_d1[18],
- r_island_data_ch2_d1[17],r_island_data_ch1_d1[17],r_island_data_ch2_d1[16],r_island_data_ch1_d1[16],
- r_island_data_ch2_d1[15],r_island_data_ch1_d1[15],r_island_data_ch2_d1[14],r_island_data_ch1_d1[14],
- r_island_data_ch2_d1[13],r_island_data_ch1_d1[13],r_island_data_ch2_d1[12],r_island_data_ch1_d1[12],
- r_island_data_ch2_d1[11],r_island_data_ch1_d1[11],r_island_data_ch2_d1[10],r_island_data_ch1_d1[10],
- r_island_data_ch2_d1[9 ],r_island_data_ch1_d1[9 ],r_island_data_ch2_d1[8 ],r_island_data_ch1_d1[8 ],
- r_island_data_ch2_d1[7 ],r_island_data_ch1_d1[7 ],r_island_data_ch2_d1[6 ],r_island_data_ch1_d1[6 ],
- r_island_data_ch2_d1[5 ],r_island_data_ch1_d1[5 ],r_island_data_ch2_d1[4 ],r_island_data_ch1_d1[4 ],
- r_island_data_ch2_d1[3 ],r_island_data_ch1_d1[3 ],r_island_data_ch2_d1[2 ],r_island_data_ch1_d1[2 ],
- r_island_data_ch2_d1[1 ],r_island_data_ch1_d1[1 ],r_island_data_ch2_d1[0 ],r_island_data_ch1_d1[0 ]};
- else
- O_BCH_block_1 <= 'b0;
- end
-
- end
-
- // BCH块2组装逻辑(通道1&2数据交叉排列)
- always @(posedge I_pixel_clk or negedge I_reste_n) begin
- if (!I_reste_n) begin
- O_BCH_block_2 <= 'b0;
- end
- else begin
- if (r_island_data_vaild)
- O_BCH_block_2 <= {r_island_data_ch2_d2[31],r_island_data_ch1_d2[31],r_island_data_ch2_d2[30],r_island_data_ch1_d2[30],
- r_island_data_ch2_d2[29],r_island_data_ch1_d2[29],r_island_data_ch2_d2[28],r_island_data_ch1_d2[28],
- r_island_data_ch2_d2[27],r_island_data_ch1_d2[27],r_island_data_ch2_d2[26],r_island_data_ch1_d2[26],
- r_island_data_ch2_d2[25],r_island_data_ch1_d2[25],r_island_data_ch2_d2[24],r_island_data_ch1_d2[24],
- r_island_data_ch2_d2[23],r_island_data_ch1_d2[23],r_island_data_ch2_d2[22],r_island_data_ch1_d2[22],
- r_island_data_ch2_d2[21],r_island_data_ch1_d2[21],r_island_data_ch2_d2[20],r_island_data_ch1_d2[20],
- r_island_data_ch2_d2[19],r_island_data_ch1_d2[19],r_island_data_ch2_d2[18],r_island_data_ch1_d2[18],
- r_island_data_ch2_d2[17],r_island_data_ch1_d2[17],r_island_data_ch2_d2[16],r_island_data_ch1_d2[16],
- r_island_data_ch2_d2[15],r_island_data_ch1_d2[15],r_island_data_ch2_d2[14],r_island_data_ch1_d2[14],
- r_island_data_ch2_d2[13],r_island_data_ch1_d2[13],r_island_data_ch2_d2[12],r_island_data_ch1_d2[12],
- r_island_data_ch2_d2[11],r_island_data_ch1_d2[11],r_island_data_ch2_d2[10],r_island_data_ch1_d2[10],
- r_island_data_ch2_d2[9 ],r_island_data_ch1_d2[9 ],r_island_data_ch2_d2[8 ],r_island_data_ch1_d2[8 ],
- r_island_data_ch2_d2[7 ],r_island_data_ch1_d2[7 ],r_island_data_ch2_d2[6 ],r_island_data_ch1_d2[6 ],
- r_island_data_ch2_d2[5 ],r_island_data_ch1_d2[5 ],r_island_data_ch2_d2[4 ],r_island_data_ch1_d2[4 ],
- r_island_data_ch2_d2[3 ],r_island_data_ch1_d2[3 ],r_island_data_ch2_d2[2 ],r_island_data_ch1_d2[2 ],
- r_island_data_ch2_d2[1 ],r_island_data_ch1_d2[1 ],r_island_data_ch2_d2[0 ],r_island_data_ch1_d2[0 ]};
- else
- O_BCH_block_2 <= 'b0;
- end
- end
-
- // BCH块3组装逻辑(通道1&2数据交叉排列)
- always @(posedge I_pixel_clk or negedge I_reste_n) begin
- if (!I_reste_n) begin
- O_BCH_block_3 <= 'b0;
- end
- else begin
- if (r_island_data_vaild)
- O_BCH_block_3 <= {r_island_data_ch2_d3[31],r_island_data_ch1_d3[31],r_island_data_ch2_d3[30],r_island_data_ch1_d3[30],
- r_island_data_ch2_d3[29],r_island_data_ch1_d3[29],r_island_data_ch2_d3[28],r_island_data_ch1_d3[28],
- r_island_data_ch2_d3[27],r_island_data_ch1_d3[27],r_island_data_ch2_d3[26],r_island_data_ch1_d3[26],
- r_island_data_ch2_d3[25],r_island_data_ch1_d3[25],r_island_data_ch2_d3[24],r_island_data_ch1_d3[24],
- r_island_data_ch2_d3[23],r_island_data_ch1_d3[23],r_island_data_ch2_d3[22],r_island_data_ch1_d3[22],
- r_island_data_ch2_d3[21],r_island_data_ch1_d3[21],r_island_data_ch2_d3[20],r_island_data_ch1_d3[20],
- r_island_data_ch2_d3[19],r_island_data_ch1_d3[19],r_island_data_ch2_d3[18],r_island_data_ch1_d3[18],
- r_island_data_ch2_d3[17],r_island_data_ch1_d3[17],r_island_data_ch2_d3[16],r_island_data_ch1_d3[16],
- r_island_data_ch2_d3[15],r_island_data_ch1_d3[15],r_island_data_ch2_d3[14],r_island_data_ch1_d3[14],
- r_island_data_ch2_d3[13],r_island_data_ch1_d3[13],r_island_data_ch2_d3[12],r_island_data_ch1_d3[12],
- r_island_data_ch2_d3[11],r_island_data_ch1_d3[11],r_island_data_ch2_d3[10],r_island_data_ch1_d3[10],
- r_island_data_ch2_d3[9 ],r_island_data_ch1_d3[9 ],r_island_data_ch2_d3[8 ],r_island_data_ch1_d3[8 ],
- r_island_data_ch2_d3[7 ],r_island_data_ch1_d3[7 ],r_island_data_ch2_d3[6 ],r_island_data_ch1_d3[6 ],
- r_island_data_ch2_d3[5 ],r_island_data_ch1_d3[5 ],r_island_data_ch2_d3[4 ],r_island_data_ch1_d3[4 ],
- r_island_data_ch2_d3[3 ],r_island_data_ch1_d3[3 ],r_island_data_ch2_d3[2 ],r_island_data_ch1_d3[2 ],
- r_island_data_ch2_d3[1 ],r_island_data_ch1_d3[1 ],r_island_data_ch2_d3[0 ],r_island_data_ch1_d3[0 ]};
-
- else
- O_BCH_block_3 <= 'b0;
- end
- end
-
- // BCH块4组装逻辑(直接赋值)
- always @(posedge I_pixel_clk or negedge I_reste_n) begin
- if (!I_reste_n) begin
- O_BCH_block_4 <= 'b0;
- end
- else begin
- if (r_island_data_vaild)
- O_BCH_block_4 <= r_island_data_ch0_d2;
- else
- O_BCH_block_4 <= 'b0;
- end
- end
-
- endmodule
复制代码
3.2hdmi_audio_packet_decoder.v模块该模块为HDMI音频包解码器,主要负责从BCH编码数据块中提取并校验音频信息。通过BCH_32_24和BCH_64_56双校验单元对包头和音频数据进行纠错验证,采用两级寄存器锁存保证时序同步,通过同步FIFO实现音频数据缓冲。当检测到有效音频包(包头标识0x02且双校验通过)时,将24位PCM立体声数据分离为左右声道输出,并配合外部请求信号实现流量控制,满足HDMI 1.4b规范对音频数据包的处理要求,确保音频流传输的完整性和实时性。
- `timescale 1ns / 1ps
- //////////////////////////////////////////////////////////////////////////////////
- // 模块功能:HDMI音频数据提取与校验
- // 设计规范:
- // 1. 同步复位(低电平有效)
- // 2. 严格遵循IEEE 1364-2001 Verilog标准
- // 3. 所有输出寄存器复位初始化
- // 4. 模块端口符合输入/输出方向命名规范
- //////////////////////////////////////////////////////////////////////////////////
-
- module hdmi_audio_packet_decoder(
- // 系统基础信号
- input wire I_pixel_clk, // 像素时钟
- input wire I_reset_n, // 低有效异步复位
-
- // BCH数据块输入接口
- input wire [63:0] I_BCH_block_0, // BCH编码数据块0
- input wire [63:0] I_BCH_block_1, // BCH编码数据块1
- input wire [63:0] I_BCH_block_2, // BCH编码数据块2
- input wire [63:0] I_BCH_block_3, // BCH编码数据块3
- input wire [31:0] I_BCH_block_4, // BCH编码包头数据
-
- input wire I_block_data_vaild,// 块数据有效标志
- input wire I_audio_packet_req,
- // 音频输出接口
- output reg O_audio_valid, // 音频数据有效信号
- output reg [23:0] O_audio_left_data, // 左声道PCM数据
- output reg [23:0] O_audio_right_data // 右声道PCM数据
- );
-
- //------------------------------------------------------------------------------
- // 内部信号声明(严格位宽声明)
- //------------------------------------------------------------------------------
- wire w_fifo_full ;
- wire w_fifo_empty ;
- wire [7:0] w_header_ecc, w_body_ecc; // ECC校验结果
- wire [7:0] w_header_ecc_base, w_body_ecc_base; // ECC传输结果
- wire [23:0] w_header;
- wire [55:0] w_body;
- wire [63:0] w_fifo_dout;
- wire [63:0] w_audio_data;
- wire w_rd_en;
-
- reg r_audio_valid;
- reg [63:0] r_BCH_block_0; // 数据块0寄存器
- reg [63:0] r_BCH_block_1; // 数据块1寄存器
- reg [63:0] r_BCH_block_2; // 数据块2寄存器
- reg [63:0] r_BCH_block_3; // 数据块3寄存器
- reg [31:0] r_BCH_block_4; // 包头数据寄存器
-
- reg [63:0] r_BCH_block_0d; // 数据块0寄存器
- reg [63:0] r_BCH_block_1d; // 数据块1寄存器
- reg [63:0] r_BCH_block_2d; // 数据块2寄存器
- reg [63:0] r_BCH_block_3d; // 数据块3寄存器
- reg [31:0] r_BCH_block_4d; // 包头数据寄存器
- //------------------------------------------------------------------------------
- // BCH校验逻辑(严格时序控制)
- //------------------------------------------------------------------------------
- assign w_header_ecc_base = r_BCH_block_4[31:24]; // 包头校验码提取
- assign w_body_ecc_base = r_BCH_block_0[63:56]; // 包体验证码提取
- assign w_header = I_BCH_block_4[23:0];
- assign w_body = I_BCH_block_0[55:0];
- assign w_rd_en = w_fifo_empty ? 1'b0 : I_audio_packet_req; //非空时才接入需求信号
- assign w_audio_data = w_fifo_empty ? 64'h000000 : w_fifo_dout; //数据速度不够发送静音数据
-
- BCH_32_24_encode u_BCH_32_24_encode(
- .I_clk (I_pixel_clk ),
- .I_data_in (w_header ),
- .O_bch_ecc_out (w_header_ecc)
- );
-
- BCH_64_56_encode u_BCH_64_56_encode(
- .I_clk (I_pixel_clk),
- .I_data_in (w_body ),
- .O_bch_ecc_out (w_body_ecc )
- );
- //------------------------------------------------------------------------------
- // 数据锁存逻辑(严格时序控制)
- //------------------------------------------------------------------------------
- always @(posedge I_pixel_clk or negedge I_reset_n) begin
- if (!I_reset_n) begin
- // 异步复位初始化
- r_BCH_block_0 <= 64'h0;
- r_BCH_block_1 <= 64'h0;
- r_BCH_block_2 <= 64'h0;
- r_BCH_block_3 <= 64'h0;
- r_BCH_block_4 <= 32'h0;
- end
- else if (I_block_data_vaild) begin
- // 数据有效时锁存整个数据包
- r_BCH_block_0 <= I_BCH_block_0;
- r_BCH_block_1 <= I_BCH_block_1;
- r_BCH_block_2 <= I_BCH_block_2;
- r_BCH_block_3 <= I_BCH_block_3;
- r_BCH_block_4 <= I_BCH_block_4;
- end
- else begin
- r_BCH_block_0 <= 64'h0;
- r_BCH_block_1 <= 64'h0;
- r_BCH_block_2 <= 64'h0;
- r_BCH_block_3 <= 64'h0;
- r_BCH_block_4 <= 32'h0;
- end
- end
-
- always @(posedge I_pixel_clk or negedge I_reset_n) begin
- if (!I_reset_n) begin
- // 异步复位初始化
- r_BCH_block_0d <= 64'h0;
- r_BCH_block_1d <= 64'h0;
- r_BCH_block_2d <= 64'h0;
- r_BCH_block_3d <= 64'h0;
- r_BCH_block_4d <= 32'h0;
- end
- else begin
- r_BCH_block_0d <= r_BCH_block_0;
- r_BCH_block_1d <= r_BCH_block_1;
- r_BCH_block_2d <= r_BCH_block_2;
- r_BCH_block_3d <= r_BCH_block_3;
- r_BCH_block_4d <= r_BCH_block_4;
- end
- end
-
- //------------------------------------------------------------------------------
- // 音频数据提取逻辑(满足建立/保持时间)
- //------------------------------------------------------------------------------
- always @(posedge I_pixel_clk or negedge I_reset_n) begin
- if (!I_reset_n) begin
- // 复位时清空音频输出
- r_audio_valid <= 1'b0;
- end
- else begin
- // 复合校验条件:包头类型+双校验通过
- if ((r_BCH_block_4[7:0] == 8'h02) && (w_header_ecc == w_header_ecc_base) && (w_body_ecc == w_body_ecc_base))begin
- if ((r_BCH_block_0[55:0] != 56'h00))
- r_audio_valid <= 1'b1;
- else
- r_audio_valid <= 1'b0;
- end
- else
- r_audio_valid <= 1'b0; // 保持数据有效信号严格单周期
- end
- end
-
- //=======================================================================
- // 包有效状态机
- //=======================================================================
-
- always @(posedge I_pixel_clk or negedge I_reset_n) begin
- if (!I_reset_n) begin
- O_audio_valid <= 1'b0;
- end else begin
- if (I_audio_packet_req && !w_fifo_empty) begin
- O_audio_valid <= 1'b1;
- end else begin
- O_audio_valid <= 1'b0;
- end
- end
- end
-
- always @(posedge I_pixel_clk or negedge I_reset_n) begin
- if (!I_reset_n) begin
- O_audio_right_data <= 'b0;
- end else begin
- O_audio_right_data <= w_audio_data[47:24];
- end
- end
-
- always @(posedge I_pixel_clk or negedge I_reset_n) begin
- if (!I_reset_n) begin
- O_audio_left_data <= 'b0;
- end else begin
- O_audio_left_data <= w_audio_data[23:0];
- end
- end
-
- xpm_fifo_sync #(
- .DOUT_RESET_VALUE ("0" ), // 复位输出值
- .ECC_MODE ("no_ecc"), // 关闭ECC校验
- .FIFO_MEMORY_TYPE ("auto" ), // 自动选择存储类型
- .FIFO_READ_LATENCY (1 ), // 标准模式读延迟
- .FIFO_WRITE_DEPTH (1024 ), // 物理深度=2^log2(FIFO_DEPTH)
- .FULL_RESET_VALUE (0 ), // 复位时FULL信号状态
- .READ_DATA_WIDTH (64 ), // 必须与WRITE_DATA_WIDTH成整数倍关系
- .READ_MODE ("fwft" ), // 推荐使用FWFT模式降低延迟
- .SIM_ASSERT_CHK (0 ), // 关闭仿真断言
- .WRITE_DATA_WIDTH (64 ) // 必须与READ_DATA_WIDTH匹配或成比例
- ) u_audio_fifo (
- .rst (!I_reset_n ), // 异步复位连接
- .wr_clk (I_pixel_clk ),
- .wr_en (r_audio_valid ),
- .din ({16'h0000, r_BCH_block_0d[47:0]}),
- .full (w_fifo_full ),
- .rd_en (w_rd_en ),
- .dout (w_fifo_dout ),
- .empty (w_fifo_empty )
- );
-
- endmodule
复制代码
4代码仿真
4.1 data_island_bch_assembler.v模块仿真检查解析出的BCH block数据,BCH block4数据就是Header包数据,BCH block0数据是Body包数据,符合模拟发送的数据。
恢复出的island data中的HSYNC和VSYNC数据。
4.2 hdmi_audio_packet_decoder.v模块仿真从仿真结果看,左右声道数据解析为24bit的24’h7FFFF0,符合我们仿真发送的原始数据,模块校验通过。
|