问答 店铺
热搜: ZYNQ FPGA discuz

QQ登录

只需一步,快速开始

微信登录

微信扫码,快速开始

微信扫一扫 分享朋友圈

已有 43 人浏览分享

开启左侧

HDMI-IP项目-主讲音频信号提取(BCH块解码+音频块识别提取)-连载十三

[复制链接]
43 0
1概述

上面的课程,我们完成了对TMDS三通道数据的拆分,成功提取出数据岛部分的4bit数据,本讲我们需要将4bitisland data数据恢复成BCH块的形式,方便我们对原始数据的恢复。

2原理部分 640?wx_fmt=png&from=appmsg

关于BCH块编解码原理的介绍,我们前面的课程已经讲解过了,本章节我们要做的就是逆向恢复出BCH block数据。首先我们通过串并转换恢复出32bitChannel 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标准)的5BCH编码块(4×64+1×32位)。同时模块集成同步信号提取功能,可分离垂直/水平同步信号,为后续BCH校验及TMDS传输提供标准化的数据封装接口。

  1. `timescale 1ns / 1ps  
  2. //////////////////////////////////////////////////////////////////////////////////  
  3. // 模块名称:HDMI数据岛BCH编码组装器  
  4. // 功能描述:将HDMI数据岛周期的并行数据重组为BCH纠错码块结构  
  5. // 关键特性:  
  6. //   - 支持HDMI 1.4b规范的数据岛协议  
  7. //   - 生成5个BCH块(4个64bit + 1个32bit)  
  8. //   - 集成数据有效性校验机制  
  9. //////////////////////////////////////////////////////////////////////////////////  
  10. module data_island_bch_assembler(  
  11. input  wire         I_pixel_clk,    // 像素时钟(与TMDS字符速率同步)  
  12. input  wire         I_reste_n,      // 异步复位(低有效,注意命名应为reset_n)  
  13. input  wire [3:0]   I_island_data_ch0,  // 数据岛通道0输入(含VSYNC/HSYNC)  
  14. input  wire [3:0]   I_island_data_ch1,  // 数据岛通道1输入(音频/辅助数据)  
  15. input  wire [3:0]   I_island_data_ch2,  // 数据岛通道2输入(音频/辅助数据)  
  16. input  wire         I_island_data_vaild, // 数据有效标志(高电平有效)  
  17. // BCH块输出(符合HDMI规范第6.4节结构)  
  18. output reg [63:0]   O_BCH_block_0 ,  // BCH块0(交叉组合通道1&2数据)  
  19. output reg [63:0]   O_BCH_block_1 ,  // BCH块1(交叉组合通道1&2数据)  
  20. output reg [63:0]   O_BCH_block_2 ,  // BCH块2(交叉组合通道1&2数据)  
  21. output reg [63:0]   O_BCH_block_3 ,  // BCH块3(交叉组合通道1&2数据)  
  22. output reg [31:0]   O_BCH_block_4 ,  // BCH块4(直接来自通道0数据)  
  23. output reg          O_block_data_vaild, // BCH块有效标志  
  24. output reg          O_vsync,        // 垂直同步输出  
  25. output reg          O_hsync         // 水平同步输出  
  26. );
  27. // 控制信号寄存器组  
  28. reg [4:0]  r_block_data_cunt;       // BCH块数据计数器(注意命名应为count)  
  29. reg        r_block_data_vaild;      // 块数据有效中间信号  
  30. reg        r_island_data_ch0_d0;    // 通道0数据延迟寄存器(第0级)  
  31. reg        r_island_data_ch0_d1;    // 通道0数据延迟寄存器(第1级)  
  32. reg        r_island_data_vaild;     // 有效信号延迟寄存器  
  33. reg [31:0] r_island_data_ch0_d2;  // 通道0数据位2的移位寄存器
  34. // 通道1数据移位寄存器组(4bit输入展开为32bit)  
  35. reg [31:0] r_island_data_ch1_d0;  // 通道1数据位0的移位寄存器  
  36. reg [31:0] r_island_data_ch1_d1;  // 通道1数据位1的移位寄存器   
  37. reg [31:0] r_island_data_ch1_d2;  // 通道1数据位2的移位寄存器  
  38. reg [31:0] r_island_data_ch1_d3;  // 通道1数据位3的移位寄存器  
  39. // 通道2数据移位寄存器组(同通道1结构)  
  40. reg [31:0] r_island_data_ch2_d0;  // 通道2数据位0移位寄存器  
  41. reg [31:0] r_island_data_ch2_d1;  // 通道2数据位1移位寄存器  
  42. reg [31:0] r_island_data_ch2_d2;  // 通道2数据位2移位寄存器  
  43. reg [31:0] r_island_data_ch2_d3;  // 通道2数据位3移位寄存器
  44. // BCH块数据计数器(每个块32个有效数据)  
  45. always @(posedge I_pixel_clk or negedge I_reste_n) begin  
  46.     if (!I_reste_n) begin  
  47.         r_block_data_cunt <= 'b0;  // 复位清零  
  48.     end  
  49.     else begin   
  50.         if (I_island_data_vaild && r_block_data_cunt <= 5'h1E)  
  51.             r_block_data_cunt <= r_block_data_cunt + 1;  // 有效数据计数  
  52.         else   
  53.             r_block_data_cunt <= 'b0;  // 计数器归零  
  54.     end  
  55. end
  56. // BCH块有效信号生成(计数满30周期触发)  
  57. always @(posedge I_pixel_clk or negedge I_reste_n) begin  
  58.     if (!I_reste_n)   
  59.         r_block_data_vaild <= 'b0;  
  60.     else if (r_block_data_cunt == 5'h1E)  // 达到30计数时  
  61.         r_block_data_vaild <= 1;          // 置位有效信号  
  62.     else   
  63.         r_block_data_vaild <= 'b0;  
  64. end
  65. // 有效信号延迟一拍  
  66. always @(posedge I_pixel_clk or negedge I_reste_n) begin  
  67.     if (!I_reste_n)   
  68.         r_island_data_vaild <= 'b0;  
  69.     else   
  70.         r_island_data_vaild <= r_block_data_vaild;  // 同步时序  
  71. end
  72. // 输出有效信号生成  
  73. always @(posedge I_pixel_clk) begin  
  74.     if (!I_reste_n)   
  75.         O_block_data_vaild <= 'b0;  
  76.     else   
  77.         O_block_data_vaild <= r_island_data_vaild;  // 最终有效信号  
  78. end
  79. // 数据移位寄存器处理(通道1&2数据重组)  
  80. always @(posedge I_pixel_clk or negedge I_reste_n) begin  
  81.     if (!I_reste_n) begin  // 复位初始化  
  82.         r_island_data_ch0_d2 <= 'b0;  
  83.         r_island_data_ch1_d0 <= 'b0;  
  84.         r_island_data_ch1_d1 <= 'b0;  
  85.         r_island_data_ch1_d2 <= 'b0;  
  86.         r_island_data_ch1_d3 <= 'b0;  
  87.         r_island_data_ch2_d0 <= 'b0;  
  88.         r_island_data_ch2_d1 <= 'b0;  
  89.         r_island_data_ch2_d2 <= 'b0;  
  90.         r_island_data_ch2_d3 <= 'b0;  
  91.     end  
  92.     else if (I_island_data_vaild) begin  // 有效数据周期  
  93.         // 通道0数据移位(bit2)  
  94.         r_island_data_ch0_d2 <= {I_island_data_ch0[2],r_island_data_ch0_d2[31:1]};  
  95.         // 通道1四bit数据分别移位  
  96.         r_island_data_ch1_d0 <= {I_island_data_ch1[0],r_island_data_ch1_d0[31:1]};  
  97.         r_island_data_ch1_d1 <= {I_island_data_ch1[1],r_island_data_ch1_d1[31:1]};  
  98.         r_island_data_ch1_d2 <= {I_island_data_ch1[2],r_island_data_ch1_d2[31:1]};  
  99.         r_island_data_ch1_d3 <= {I_island_data_ch1[3],r_island_data_ch1_d3[31:1]};  
  100.         // 通道2四bit数据分别移位(同通道1)  
  101.         r_island_data_ch2_d0 <= {I_island_data_ch2[0],r_island_data_ch2_d0[31:1]};  
  102.         r_island_data_ch2_d1 <= {I_island_data_ch2[1],r_island_data_ch2_d1[31:1]};  
  103.         r_island_data_ch2_d2 <= {I_island_data_ch2[2],r_island_data_ch2_d2[31:1]};  
  104.         r_island_data_ch2_d3 <= {I_island_data_ch2[3],r_island_data_ch2_d3[31:1]};  
  105.     end  
  106.     else begin  // 非有效周期清零  
  107.         r_island_data_ch0_d2 <= 'b0;  
  108.         r_island_data_ch1_d0 <= 'b0;  
  109.         r_island_data_ch1_d1 <= 'b0;  
  110.         r_island_data_ch1_d2 <= 'b0;  
  111.         r_island_data_ch1_d3 <= 'b0;  
  112.         r_island_data_ch2_d0 <= 'b0;  
  113.         r_island_data_ch2_d1 <= 'b0;  
  114.         r_island_data_ch2_d2 <= 'b0;  
  115.         r_island_data_ch2_d3 <= 'b0;  
  116.     end  
  117. end
  118. // 通道0 bit0数据延迟链(生成HSYNC)  
  119. always @(posedge I_pixel_clk or negedge I_reste_n) begin  
  120.     if (!I_reste_n) begin  
  121.         r_island_data_ch0_d0 <= 'b0;  
  122.     end  
  123.     else   
  124.         r_island_data_ch0_d0 <= I_island_data_ch0[0];  // 同步输入数据  
  125. end
  126. // HSYNC信号输出  
  127. always @(posedge I_pixel_clk or negedge I_reste_n) begin  
  128.     if (!I_reste_n) begin  
  129.         O_hsync <= 'b0;  
  130.     end  
  131.     else   
  132.         O_hsync <= r_island_data_ch0_d0;  // 直接输出延迟后的信号  
  133. end
  134. // 通道0 bit1数据延迟链(生成VSYNC)  
  135. always @(posedge I_pixel_clk or negedge I_reste_n) begin  
  136.     if (!I_reste_n) begin  
  137.         r_island_data_ch0_d1 <= 'b0;  
  138.     end  
  139.     else   
  140.         r_island_data_ch0_d1 <= I_island_data_ch0[1];  // 同步输入数据  
  141. end
  142. // VSYNC信号输出  
  143. always @(posedge I_pixel_clk or negedge I_reste_n) begin  
  144.     if (!I_reste_n) begin  
  145.         O_vsync <= 'b0;  
  146.     end  
  147.     else   
  148.         O_vsync <= r_island_data_ch0_d1;  // 直接输出延迟后的信号  
  149. end
  150. // BCH块0组装逻辑(通道1&2数据交叉排列)
  151. always @(posedge I_pixel_clk or negedge I_reste_n) begin
  152.     if (!I_reste_n) begin
  153.         O_BCH_block_0 <= 'b0;
  154.     end
  155.     else  begin
  156.         if (r_island_data_vaild)
  157.             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],
  158.                               r_island_data_ch2_d0[29],r_island_data_ch1_d0[29],r_island_data_ch2_d0[28],r_island_data_ch1_d0[28],   
  159.                               r_island_data_ch2_d0[27],r_island_data_ch1_d0[27],r_island_data_ch2_d0[26],r_island_data_ch1_d0[26],
  160.                               r_island_data_ch2_d0[25],r_island_data_ch1_d0[25],r_island_data_ch2_d0[24],r_island_data_ch1_d0[24],
  161.                               r_island_data_ch2_d0[23],r_island_data_ch1_d0[23],r_island_data_ch2_d0[22],r_island_data_ch1_d0[22],                        
  162.                               r_island_data_ch2_d0[21],r_island_data_ch1_d0[21],r_island_data_ch2_d0[20],r_island_data_ch1_d0[20],
  163.                               r_island_data_ch2_d0[19],r_island_data_ch1_d0[19],r_island_data_ch2_d0[18],r_island_data_ch1_d0[18],
  164.                               r_island_data_ch2_d0[17],r_island_data_ch1_d0[17],r_island_data_ch2_d0[16],r_island_data_ch1_d0[16],
  165.                               r_island_data_ch2_d0[15],r_island_data_ch1_d0[15],r_island_data_ch2_d0[14],r_island_data_ch1_d0[14],
  166.                               r_island_data_ch2_d0[13],r_island_data_ch1_d0[13],r_island_data_ch2_d0[12],r_island_data_ch1_d0[12],
  167.                               r_island_data_ch2_d0[11],r_island_data_ch1_d0[11],r_island_data_ch2_d0[10],r_island_data_ch1_d0[10],
  168.                               r_island_data_ch2_d0[9 ],r_island_data_ch1_d0[9 ],r_island_data_ch2_d0[8 ],r_island_data_ch1_d0[8 ],
  169.                               r_island_data_ch2_d0[7 ],r_island_data_ch1_d0[7 ],r_island_data_ch2_d0[6 ],r_island_data_ch1_d0[6 ],
  170.                               r_island_data_ch2_d0[5 ],r_island_data_ch1_d0[5 ],r_island_data_ch2_d0[4 ],r_island_data_ch1_d0[4 ],
  171.                               r_island_data_ch2_d0[3 ],r_island_data_ch1_d0[3 ],r_island_data_ch2_d0[2 ],r_island_data_ch1_d0[2 ],
  172.                               r_island_data_ch2_d0[1 ],r_island_data_ch1_d0[1 ],r_island_data_ch2_d0[0 ],r_island_data_ch1_d0[0 ]};
  173.         else  O_BCH_block_0 <= 'b0;
  174.     end
  175.         
  176. end
  177. // BCH块1组装逻辑(通道1&2数据交叉排列)
  178. always @(posedge I_pixel_clk or negedge I_reste_n) begin
  179.     if (!I_reste_n) begin
  180.         O_BCH_block_1 <= 'b0;
  181.     end
  182.     else begin
  183.         if (r_island_data_vaild)
  184.             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],
  185.                               r_island_data_ch2_d1[29],r_island_data_ch1_d1[29],r_island_data_ch2_d1[28],r_island_data_ch1_d1[28],
  186.                               r_island_data_ch2_d1[27],r_island_data_ch1_d1[27],r_island_data_ch2_d1[26],r_island_data_ch1_d1[26],
  187.                               r_island_data_ch2_d1[25],r_island_data_ch1_d1[25],r_island_data_ch2_d1[24],r_island_data_ch1_d1[24],
  188.                               r_island_data_ch2_d1[23],r_island_data_ch1_d1[23],r_island_data_ch2_d1[22],r_island_data_ch1_d1[22],
  189.                               r_island_data_ch2_d1[21],r_island_data_ch1_d1[21],r_island_data_ch2_d1[20],r_island_data_ch1_d1[20],
  190.                               r_island_data_ch2_d1[19],r_island_data_ch1_d1[19],r_island_data_ch2_d1[18],r_island_data_ch1_d1[18],
  191.                               r_island_data_ch2_d1[17],r_island_data_ch1_d1[17],r_island_data_ch2_d1[16],r_island_data_ch1_d1[16],
  192.                               r_island_data_ch2_d1[15],r_island_data_ch1_d1[15],r_island_data_ch2_d1[14],r_island_data_ch1_d1[14],
  193.                               r_island_data_ch2_d1[13],r_island_data_ch1_d1[13],r_island_data_ch2_d1[12],r_island_data_ch1_d1[12],
  194.                               r_island_data_ch2_d1[11],r_island_data_ch1_d1[11],r_island_data_ch2_d1[10],r_island_data_ch1_d1[10],
  195.                               r_island_data_ch2_d1[9 ],r_island_data_ch1_d1[9 ],r_island_data_ch2_d1[8 ],r_island_data_ch1_d1[8 ],
  196.                               r_island_data_ch2_d1[7 ],r_island_data_ch1_d1[7 ],r_island_data_ch2_d1[6 ],r_island_data_ch1_d1[6 ],
  197.                               r_island_data_ch2_d1[5 ],r_island_data_ch1_d1[5 ],r_island_data_ch2_d1[4 ],r_island_data_ch1_d1[4 ],
  198.                               r_island_data_ch2_d1[3 ],r_island_data_ch1_d1[3 ],r_island_data_ch2_d1[2 ],r_island_data_ch1_d1[2 ],
  199.                               r_island_data_ch2_d1[1 ],r_island_data_ch1_d1[1 ],r_island_data_ch2_d1[0 ],r_island_data_ch1_d1[0 ]};
  200.         else  
  201.             O_BCH_block_1 <= 'b0;
  202.     end
  203. end
  204. // BCH块2组装逻辑(通道1&2数据交叉排列)
  205. always @(posedge I_pixel_clk or negedge I_reste_n) begin
  206.     if (!I_reste_n) begin
  207.         O_BCH_block_2 <= 'b0;
  208.     end
  209.     else begin
  210.         if (r_island_data_vaild)
  211.             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],
  212.                               r_island_data_ch2_d2[29],r_island_data_ch1_d2[29],r_island_data_ch2_d2[28],r_island_data_ch1_d2[28],
  213.                               r_island_data_ch2_d2[27],r_island_data_ch1_d2[27],r_island_data_ch2_d2[26],r_island_data_ch1_d2[26],
  214.                               r_island_data_ch2_d2[25],r_island_data_ch1_d2[25],r_island_data_ch2_d2[24],r_island_data_ch1_d2[24],
  215.                               r_island_data_ch2_d2[23],r_island_data_ch1_d2[23],r_island_data_ch2_d2[22],r_island_data_ch1_d2[22],
  216.                               r_island_data_ch2_d2[21],r_island_data_ch1_d2[21],r_island_data_ch2_d2[20],r_island_data_ch1_d2[20],
  217.                               r_island_data_ch2_d2[19],r_island_data_ch1_d2[19],r_island_data_ch2_d2[18],r_island_data_ch1_d2[18],
  218.                               r_island_data_ch2_d2[17],r_island_data_ch1_d2[17],r_island_data_ch2_d2[16],r_island_data_ch1_d2[16],
  219.                               r_island_data_ch2_d2[15],r_island_data_ch1_d2[15],r_island_data_ch2_d2[14],r_island_data_ch1_d2[14],
  220.                               r_island_data_ch2_d2[13],r_island_data_ch1_d2[13],r_island_data_ch2_d2[12],r_island_data_ch1_d2[12],
  221.                               r_island_data_ch2_d2[11],r_island_data_ch1_d2[11],r_island_data_ch2_d2[10],r_island_data_ch1_d2[10],
  222.                               r_island_data_ch2_d2[9 ],r_island_data_ch1_d2[9 ],r_island_data_ch2_d2[8 ],r_island_data_ch1_d2[8 ],
  223.                               r_island_data_ch2_d2[7 ],r_island_data_ch1_d2[7 ],r_island_data_ch2_d2[6 ],r_island_data_ch1_d2[6 ],
  224.                               r_island_data_ch2_d2[5 ],r_island_data_ch1_d2[5 ],r_island_data_ch2_d2[4 ],r_island_data_ch1_d2[4 ],
  225.                               r_island_data_ch2_d2[3 ],r_island_data_ch1_d2[3 ],r_island_data_ch2_d2[2 ],r_island_data_ch1_d2[2 ],
  226.                               r_island_data_ch2_d2[1 ],r_island_data_ch1_d2[1 ],r_island_data_ch2_d2[0 ],r_island_data_ch1_d2[0 ]};  
  227.         else
  228.             O_BCH_block_2 <= 'b0;
  229.     end
  230. end
  231. // BCH块3组装逻辑(通道1&2数据交叉排列)
  232. always @(posedge I_pixel_clk or negedge I_reste_n) begin
  233.     if (!I_reste_n) begin
  234.         O_BCH_block_3 <= 'b0;
  235.     end
  236.     else begin
  237.         if (r_island_data_vaild)
  238.             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],
  239.                               r_island_data_ch2_d3[29],r_island_data_ch1_d3[29],r_island_data_ch2_d3[28],r_island_data_ch1_d3[28],
  240.                               r_island_data_ch2_d3[27],r_island_data_ch1_d3[27],r_island_data_ch2_d3[26],r_island_data_ch1_d3[26],
  241.                               r_island_data_ch2_d3[25],r_island_data_ch1_d3[25],r_island_data_ch2_d3[24],r_island_data_ch1_d3[24],
  242.                               r_island_data_ch2_d3[23],r_island_data_ch1_d3[23],r_island_data_ch2_d3[22],r_island_data_ch1_d3[22],
  243.                               r_island_data_ch2_d3[21],r_island_data_ch1_d3[21],r_island_data_ch2_d3[20],r_island_data_ch1_d3[20],
  244.                               r_island_data_ch2_d3[19],r_island_data_ch1_d3[19],r_island_data_ch2_d3[18],r_island_data_ch1_d3[18],
  245.                               r_island_data_ch2_d3[17],r_island_data_ch1_d3[17],r_island_data_ch2_d3[16],r_island_data_ch1_d3[16],
  246.                               r_island_data_ch2_d3[15],r_island_data_ch1_d3[15],r_island_data_ch2_d3[14],r_island_data_ch1_d3[14],
  247.                               r_island_data_ch2_d3[13],r_island_data_ch1_d3[13],r_island_data_ch2_d3[12],r_island_data_ch1_d3[12],
  248.                               r_island_data_ch2_d3[11],r_island_data_ch1_d3[11],r_island_data_ch2_d3[10],r_island_data_ch1_d3[10],
  249.                               r_island_data_ch2_d3[9 ],r_island_data_ch1_d3[9 ],r_island_data_ch2_d3[8 ],r_island_data_ch1_d3[8 ],
  250.                               r_island_data_ch2_d3[7 ],r_island_data_ch1_d3[7 ],r_island_data_ch2_d3[6 ],r_island_data_ch1_d3[6 ],
  251.                               r_island_data_ch2_d3[5 ],r_island_data_ch1_d3[5 ],r_island_data_ch2_d3[4 ],r_island_data_ch1_d3[4 ],
  252.                               r_island_data_ch2_d3[3 ],r_island_data_ch1_d3[3 ],r_island_data_ch2_d3[2 ],r_island_data_ch1_d3[2 ],
  253.                               r_island_data_ch2_d3[1 ],r_island_data_ch1_d3[1 ],r_island_data_ch2_d3[0 ],r_island_data_ch1_d3[0 ]};
  254.         else
  255.             O_BCH_block_3 <= 'b0;
  256.     end
  257. end  
  258. // BCH块4组装逻辑(直接赋值)   
  259. always @(posedge I_pixel_clk or negedge I_reste_n) begin
  260.     if (!I_reste_n) begin
  261.         O_BCH_block_4 <= 'b0;
  262.     end
  263.     else begin
  264.         if (r_island_data_vaild)
  265.             O_BCH_block_4 <= r_island_data_ch0_d2;
  266.         else
  267.             O_BCH_block_4 <= 'b0;
  268.     end
  269. end     
  270. endmodule
复制代码
3.2hdmi_audio_packet_decoder.v模块

该模块为HDMI音频包解码器,主要负责从BCH编码数据块中提取并校验音频信息。通过BCH_32_24BCH_64_56双校验单元对包头和音频数据进行纠错验证,采用两级寄存器锁存保证时序同步,通过同步FIFO实现音频数据缓冲。当检测到有效音频包(包头标识0x02且双校验通过)时,将24PCM立体声数据分离为左右声道输出,并配合外部请求信号实现流量控制,满足HDMI 1.4b规范对音频数据包的处理要求,确保音频流传输的完整性和实时性。


  1. `timescale 1ns / 1ps  
  2. //////////////////////////////////////////////////////////////////////////////////  
  3. // 模块功能:HDMI音频数据提取与校验  
  4. // 设计规范:  
  5. // 1. 同步复位(低电平有效)  
  6. // 2. 严格遵循IEEE 1364-2001 Verilog标准  
  7. // 3. 所有输出寄存器复位初始化  
  8. // 4. 模块端口符合输入/输出方向命名规范  
  9. //////////////////////////////////////////////////////////////////////////////////  
  10. module hdmi_audio_packet_decoder(  
  11.     // 系统基础信号  
  12.     input  wire         I_pixel_clk,       // 像素时钟
  13.     input  wire         I_reset_n,         // 低有效异步复位
  14.    
  15.     // BCH数据块输入接口  
  16.     input  wire [63:0]  I_BCH_block_0,     // BCH编码数据块0  
  17.     input  wire [63:0]  I_BCH_block_1,     // BCH编码数据块1   
  18.     input  wire [63:0]  I_BCH_block_2,     // BCH编码数据块2  
  19.     input  wire [63:0]  I_BCH_block_3,     // BCH编码数据块3  
  20.     input  wire [31:0]  I_BCH_block_4,     // BCH编码包头数据
  21.     input  wire         I_block_data_vaild,// 块数据有效标志
  22.     input  wire         I_audio_packet_req,
  23.     // 音频输出接口  
  24.     output reg          O_audio_valid,     // 音频数据有效信号
  25.     output reg [23:0]   O_audio_left_data, // 左声道PCM数据
  26.     output reg [23:0]   O_audio_right_data // 右声道PCM数据
  27. );  
  28. //------------------------------------------------------------------------------  
  29. // 内部信号声明(严格位宽声明)  
  30. //------------------------------------------------------------------------------  
  31. wire        w_fifo_full  ;   
  32. wire        w_fifo_empty ;
  33. wire [7:0]  w_header_ecc, w_body_ecc;        // ECC校验结果  
  34. wire [7:0]  w_header_ecc_base, w_body_ecc_base; // ECC传输结果
  35. wire [23:0] w_header;
  36. wire [55:0] w_body;
  37. wire [63:0] w_fifo_dout;
  38. wire [63:0] w_audio_data;
  39. wire        w_rd_en;
  40. reg         r_audio_valid;
  41. reg  [63:0] r_BCH_block_0;   // 数据块0寄存器  
  42. reg  [63:0] r_BCH_block_1;   // 数据块1寄存器  
  43. reg  [63:0] r_BCH_block_2;   // 数据块2寄存器  
  44. reg  [63:0] r_BCH_block_3;   // 数据块3寄存器  
  45. reg  [31:0] r_BCH_block_4;   // 包头数据寄存器  
  46. reg  [63:0] r_BCH_block_0d;   // 数据块0寄存器  
  47. reg  [63:0] r_BCH_block_1d;   // 数据块1寄存器  
  48. reg  [63:0] r_BCH_block_2d;   // 数据块2寄存器  
  49. reg  [63:0] r_BCH_block_3d;   // 数据块3寄存器  
  50. reg  [31:0] r_BCH_block_4d;   // 包头数据寄存器  
  51. //------------------------------------------------------------------------------  
  52. // BCH校验逻辑(严格时序控制)  
  53. //------------------------------------------------------------------------------  
  54. assign w_header_ecc_base = r_BCH_block_4[31:24];   // 包头校验码提取  
  55. assign w_body_ecc_base   = r_BCH_block_0[63:56];   // 包体验证码提取  
  56. assign w_header          = I_BCH_block_4[23:0];
  57. assign w_body            = I_BCH_block_0[55:0];
  58. assign w_rd_en           = w_fifo_empty ? 1'b0 : I_audio_packet_req;      //非空时才接入需求信号
  59. assign w_audio_data      = w_fifo_empty ? 64'h000000 : w_fifo_dout; //数据速度不够发送静音数据
  60. BCH_32_24_encode u_BCH_32_24_encode(
  61.     .I_clk         (I_pixel_clk ),
  62.     .I_data_in     (w_header    ),
  63.     .O_bch_ecc_out (w_header_ecc)
  64. );
  65. BCH_64_56_encode u_BCH_64_56_encode(
  66.     .I_clk         (I_pixel_clk),
  67.     .I_data_in     (w_body     ),
  68.     .O_bch_ecc_out (w_body_ecc )
  69. );
  70. //------------------------------------------------------------------------------  
  71. // 数据锁存逻辑(严格时序控制)  
  72. //------------------------------------------------------------------------------  
  73. always @(posedge I_pixel_clk or negedge I_reset_n) begin  
  74.     if (!I_reset_n) begin  
  75.         // 异步复位初始化  
  76.         r_BCH_block_0 <= 64'h0;  
  77.         r_BCH_block_1 <= 64'h0;  
  78.         r_BCH_block_2 <= 64'h0;  
  79.         r_BCH_block_3 <= 64'h0;  
  80.         r_BCH_block_4 <= 32'h0;  
  81.     end  
  82.     else if (I_block_data_vaild) begin  
  83.         // 数据有效时锁存整个数据包  
  84.         r_BCH_block_0 <= I_BCH_block_0;  
  85.         r_BCH_block_1 <= I_BCH_block_1;  
  86.         r_BCH_block_2 <= I_BCH_block_2;  
  87.         r_BCH_block_3 <= I_BCH_block_3;   
  88.         r_BCH_block_4 <= I_BCH_block_4;
  89.     end  
  90.     else begin
  91.         r_BCH_block_0 <= 64'h0;
  92.         r_BCH_block_1 <= 64'h0;
  93.         r_BCH_block_2 <= 64'h0;
  94.         r_BCH_block_3 <= 64'h0;
  95.         r_BCH_block_4 <= 32'h0;
  96.     end
  97. end  
  98. always @(posedge I_pixel_clk or negedge I_reset_n) begin  
  99.     if (!I_reset_n) begin  
  100.         // 异步复位初始化  
  101.         r_BCH_block_0d <= 64'h0;  
  102.         r_BCH_block_1d <= 64'h0;  
  103.         r_BCH_block_2d <= 64'h0;  
  104.         r_BCH_block_3d <= 64'h0;  
  105.         r_BCH_block_4d <= 32'h0;  
  106.     end  
  107.     else  begin  
  108.         r_BCH_block_0d <= r_BCH_block_0;  
  109.         r_BCH_block_1d <= r_BCH_block_1;  
  110.         r_BCH_block_2d <= r_BCH_block_2;  
  111.         r_BCH_block_3d <= r_BCH_block_3;   
  112.         r_BCH_block_4d <= r_BCH_block_4;
  113.     end  
  114. end  
  115. //------------------------------------------------------------------------------  
  116. // 音频数据提取逻辑(满足建立/保持时间)  
  117. //------------------------------------------------------------------------------  
  118. always @(posedge I_pixel_clk or negedge I_reset_n) begin  
  119.     if (!I_reset_n) begin  
  120.         // 复位时清空音频输出  
  121.         r_audio_valid <= 1'b0;  
  122.     end  
  123.     else begin  
  124.         // 复合校验条件:包头类型+双校验通过  
  125.         if ((r_BCH_block_4[7:0] == 8'h02) && (w_header_ecc == w_header_ecc_base) &&  (w_body_ecc == w_body_ecc_base))begin  
  126.             if ((r_BCH_block_0[55:0] != 56'h00))
  127.                 r_audio_valid <= 1'b1;  
  128.             else
  129.                 r_audio_valid <= 1'b0;  
  130.         end  
  131.         else   
  132.             r_audio_valid <= 1'b0;  // 保持数据有效信号严格单周期  
  133.     end  
  134. end  
  135. //=======================================================================  
  136. // 包有效状态机
  137. //=======================================================================  
  138. always @(posedge I_pixel_clk or negedge I_reset_n) begin  
  139.     if (!I_reset_n) begin  
  140.         O_audio_valid <= 1'b0;  
  141.     end else begin  
  142.         if (I_audio_packet_req && !w_fifo_empty) begin  
  143.             O_audio_valid <= 1'b1;
  144.         end else begin  
  145.             O_audio_valid <= 1'b0;  
  146.         end  
  147.     end  
  148. end  
  149. always @(posedge I_pixel_clk or negedge I_reset_n) begin  
  150.     if (!I_reset_n) begin  
  151.         O_audio_right_data <= 'b0;  
  152.     end else begin  
  153.         O_audio_right_data <= w_audio_data[47:24];
  154.     end  
  155. end  
  156. always @(posedge I_pixel_clk or negedge I_reset_n) begin  
  157.     if (!I_reset_n) begin  
  158.         O_audio_left_data <= 'b0;  
  159.     end else begin  
  160.         O_audio_left_data <= w_audio_data[23:0];
  161.     end  
  162. end  
  163. xpm_fifo_sync #(   
  164.     .DOUT_RESET_VALUE    ("0"     ), // 复位输出值  
  165.     .ECC_MODE            ("no_ecc"), // 关闭ECC校验  
  166.     .FIFO_MEMORY_TYPE    ("auto"  ), // 自动选择存储类型  
  167.     .FIFO_READ_LATENCY   (1       ), // 标准模式读延迟  
  168.     .FIFO_WRITE_DEPTH    (1024    ), // 物理深度=2^log2(FIFO_DEPTH)  
  169.     .FULL_RESET_VALUE    (0       ), // 复位时FULL信号状态  
  170.     .READ_DATA_WIDTH     (64      ), // 必须与WRITE_DATA_WIDTH成整数倍关系  
  171.     .READ_MODE           ("fwft"  ), // 推荐使用FWFT模式降低延迟  
  172.     .SIM_ASSERT_CHK      (0       ), // 关闭仿真断言  
  173.     .WRITE_DATA_WIDTH    (64      )  // 必须与READ_DATA_WIDTH匹配或成比例  
  174. ) u_audio_fifo (  
  175.     .rst        (!I_reset_n                      ), // 异步复位连接  
  176.     .wr_clk     (I_pixel_clk                     ),  
  177.     .wr_en      (r_audio_valid                   ),  
  178.     .din        ({16'h0000, r_BCH_block_0d[47:0]}),  
  179.     .full       (w_fifo_full                     ),  
  180.     .rd_en      (w_rd_en                         ),  
  181.     .dout       (w_fifo_dout                     ),  
  182.     .empty      (w_fifo_empty                    )  
  183. );  
  184. endmodule
复制代码
4代码仿真
4.1 data_island_bch_assembler.v模块仿真

检查解析出的BCH block数据,BCH block4数据就是Header包数据,BCH block0数据是Body包数据,符合模拟发送的数据。

640?wx_fmt=png&from=appmsg

恢复出的island data中的HSYNCVSYNC数据。

640?wx_fmt=png&from=appmsg
4.2 hdmi_audio_packet_decoder.v模块仿真

从仿真结果看,左右声道数据解析为24bit24h7FFFF0,符合我们仿真发送的原始数据,模块校验通过。

640?wx_fmt=png&from=appmsg
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

0

关注

0

粉丝

303

主题
精彩推荐
热门资讯
网友晒图
图文推荐

  • 微信公众平台

  • 扫描访问手机版