差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
book_excise_bch_coding [2021/08/23 11:22]
zili
book_excise_bch_coding [2021/08/23 11:30] (当前版本)
zili
行 47: 行 47:
 6. decoder是BCH的译码模块。 6. decoder是BCH的译码模块。
 {{ :​图16-1.png |图16-1 程序总体模块图}} {{ :​图16-1.png |图16-1 程序总体模块图}}
 +<WRAP centeralign>​
 +**图16-1 程序总体模块图**
 +</​WRAP>​
  
 +#### 3.2 m_serial模块(m_serial.v)
 +m_serial模块产生一个的M序列作为数据用作BCH的数据输入,M序列的产生电路如所图 16 2示。每四个时钟周期产生一个输出,用计数器counter来控制。当counter等于3时,输出一个比特,一个使能data_en信号,data_en给encoder模块用于信号采样,在data_en为高电平时,时钟上升延采样。
 +{{ :​图16-2.png |图16-2 M序列生成电路}}
 +<WRAP centeralign>​
 +**图16-2 M序列生成电路**
 +</​WRAP>​
  
 +<code verilog> ​
  
-\\ +input clk; ​       //​时钟输入。 
-\\ +input    reset; ​      ​ //​复位输入。 
-### 4. 仿真结果+input    load;       ​ //​load信号用于初始化M序列多项式系数。 
 +output ​  ​data_en; ​   //​M序列输出使能信号,高电平有效。 
 +output ​  ​data_out; ​   //​M序列输出。
  
 +always @(posedge clk) begin
 +if (!reset) begin
 +     a7 <= 0;
 + a6 <= 0;
 + a5 <= 0; 
 + a4 <= 0; 
 + a3 <= 0; 
 + a2 <= 0;
 + a1 <= 0;
 + a0 <= 0;
 + data_en <= 0;
 + end
 + else begin
 +     if (!load) begin //​当load为低时,重新初始化M序列多项式系数。
 + a7 <= 1;
 + a6 <= 0;
 + a5 <= 0; 
 + a4 <= 0; 
 + a3 <= 0; 
 + a2 <= 0;
 + a1 <= 0;
 + a0 <= 0; 
 + data_en <= 0;
 + end
 + else begin
 + //​counter是一个0~3的计数器。当counter==3时,输出一个比特。
 +if (counter==3) begin
 +data_en <= 1;
 +a0 <= a1;
 +a1 <= a2;
 +a2 <= a3;
 +a3 <= a4;
 +a4 <= a5;
 +a5 <= a6;
 +a6 <= a7;
 +a7 <= a4^a3^a2^a0;​
 +end
 +else 
 +data_en <= 0;
 + end
 + end
 + end
  
 +</​code>​
  
 +#### 3.3 encoder模块(encoder.v)
 +encoder模块完成BCH编码,在采得7位信息位后对它进行编码,然后将15位BCH码串行输出,同时输出data _valid信号用于指示encode_out有效。
 +<code verilog> ​
  
 +input clk; ​       //​时钟信号。
 +input   ​reset; ​     //​同步复位信号。
 +input   ​data_en; ​    ​ //​M序列数据使能信号。
 +input   ​data_in; ​    ​ //​M序列输入。
 +output ​ encode_out; ​ //​BCH码输出。
 +output encode_valid;​ //​BCH码输出有效,​高电平有效。
  
 +//​将输入的数据保存到temp中,temp可以存储一组7比特数据。
 +always @(posedge clk) begin
 +if(!reset) begin
 + temp <= 7'​b000_0000;​
 + counter <= 3'​b000;​
 + end
 + else begin
 + if(data_en) ​
 +    ​ if(counter == 3'​b110) begin
 +     temp[6-counter] <= data_in;
 +     counter <= 3'​b000;​
 +     end
 + else begin
 +     temp[6-counter] <= data_in;
 +     counter <= counter+1;
 +     end
 + end
 + end
  
 +//​当temp接受完7比特数据后,将其送给info并对其进行编码。
 +always @(posedge clk) begin
 +if(!reset) ​
 + info[6:0] = 7'​b000_0000;​
 + else
 + if(counter == 3'b110 &&​data_en == 1 )
 + info = temp; 
 + end
  
 +//​信息码与生成矩阵相乘,实现编码功能。
 +//​data为15为编码结果,低7比特为原始数据,高8比特为校验位。
 +assign data[14:8] = info[6:0]; //​BCH前7位为信息。
 +assign data[7] = info[6]^info[2]^info[0]; ​ //​后8位效验位生成。
 +assign data[6] = info[6]^info[5]^info[2]^info[1]^info[0];​
 +assign data[5] = info[6]^info[5]^info[4]^info[2]^info[1];​
 +assign data[4] = info[5]^info[4]^info[3]^info[1]^info[0];​
 +assign data[3] = info[6]^info[4]^info[3];​
 +assign data[2] = info[5]^info[3]^info[2];​
 +assign data[1] = info[4]^info[2]^info[1];​
 +assign data[0] = info[3]^info[1]^info[0];​
 +
 +//​将编码后的15比特数据输出。
 +always @(posedge clk) begin
 +if(!reset) begin
 + encode_out <= 15'​b000_0000_0000_0000;​
 + encode_valid <= 0;
 + end
 + else
 + //​当counter等于0时,表示完成数据输入和编码,下一个周期可以
 + //​输出数据。
 + if(counter == 3'b000 && data_en == 1) begin
 +     encode_valid <= 1; //​编码有效信号,长度为15个时钟周期。
 +         cnt<​=14;​  ​ //​cnt实现对输出数据个数的控制,为15比特。
 +     encode_out <= data[14];
 + end
 + else
 +     if(cnt <= 0)
 +     encode_valid <= 0; //​当15位编码输出结束后,编码有效位置为0。
 + else begin
 + encode_out <= data[cnt-1];//​每个时钟周期输出一位BCH码。
 + encode_valid <= 1;
 + cnt <= cnt-1;
 + end
 + end
 +end
 +
 +</​code>​
 +
 +#### 3.4 channel模块(channel.v)
 +channel模块用于模拟简单的信道,在编码后的数据中加入误码,在此将第12位和第10位加入误码。Channel模块的接口如下:
 +<code verilog> ​
 +
 +input   ​clk; ​      ​ //​时钟信号
 +input   ​data_in; ​     //​数据输入
 +input   ​data_in_valid;​ //​数据输入有效
 +output ​ data_noise; ​       //​信道噪音数据
 +程序如下:
 +always @(posedge clk) begin
 + if (!data_in_valid)
 + counter <= 0;
 + else
 +   if (counter == 14) begin
 + counter <= 0;
 + noise <= 0;
 + end
 + else
 + if (counter == 1 || counter==3) begin
 + counter <= counter+1; ​   ​
 + noise <= 1;          当counter等于1或3时,noise置为1
 + end
 + else begin
 + counter <= counter+1; ​
 + noise <= 0; 当counter等于其他数时,noise置为0
 + end
 + end
 +
 +</​code>​
 +
 +assign data_noise = noise^data_in; ​  ​信道输出为noise信号与data_in信号异或。
 +
 +#### 3.5 decoder模块(decoder.v)
 +decoder模块用于解码,在data_valid为高电平时将数据缓存起来,然后根据输入的编码算出伴随多项式。然后用查表法找到错误图样。最后将纠错的码字串行输出,同时输出decode_valid信号,此时只输出7位信息位,校验位被丢弃。
 +
 +Decoder的输入输出接口如下:
 +<code verilog> ​
 +
 +input clk; ​       //​时钟信号
 +input   ​reset; ​      ​ //​同步复位信号
 +input   ​data_in_valid;​ //​数据输入有效
 +input   ​data_in; ​           //​数据输入
 +output ​ decode_out; ​        //​BCH解码输出
 +output ​ decode_valid; ​      //​BCH解码有效
 +实现程序如下:
 +always @(posedge clk )
 + if (!reset) begin
 + temp <= 15'​b000_0000_0000_0000;​ //​temp保存了15比特的数据输入。
 + counter <= 0;
 + end
 + else begin
 + if(!data_in_valid)
 + counter <= 0;
 + else begin
 +     counter <= counter+1;
 +     temp[14-counter] <= data_in; //​当有效为1时,将输入的15位编
 +码按顺序送给Temp。
 +     end
 + end
 +end
 +
 +always @(posedge clk) begin
 +if (!reset) ​
 + info <= 0;  //​info中保存要译码的数据。
 + else
 + if (counter == 5'​b01111)
 +      info <= temp; //​当temp最后一位赋值结束后,将 temp赋值给info。
 + end
 +  //​根据输入的码组计算出伴随多项式S。
 + wire [7:0] s;
 +assign s[7] = info[14]^info[13]^info[12]^info[10]^
 +info[8]^info[7]^info[4]^info[0];​
 +assign s[6] = info[12]^info[11]^info[10]^info[9]^
 +info[7]^info[5]^info[4]^info[1];​
 +assign s[5] = info[13]^info[12]^info[11]^info[10]^
 +info[8]^info[6]^info[5]^info[2];​
 +     ​assign s[4] = info[14]^info[13]^info[12]^info[11]^
 +info[9]^info[7]^info[6]^info[3];​
 + assign s[3] = info[14]^info[10]^info[9]^info[5]^info[4]^info[0];​
 + assign s[2] = info[14]^info[13]^info[9]^info[8]^info[4]^info[3];​
 + assign s[1] = info[14]^info[12]^info[9]^info[7]^info[4]^info[2];​
 + assign s[0] = info[14]^info[13]^info[12]^info[11]^info[9]^
 +info[8]^info[7]^info[6]^info[4]^info[3]^info[2]^info[1];​
 +
 +   ​ //​利用查找表找出此输入码组的错误图样,error为错误图样。
 +reg [6:0] error;
 +always @(s)
 +     case(s)
 +     8'​b10011111 : error = 7'​b1000000;​
 +       ……………………………………… //​此处略去了查找表
 +         default ​    : error = 7'​b0000000;​
 +       endcase
 + 
 +//​info与error求异或,得到译码后的结果。
 +assign data = error^info[14:​8];​
 +
 + always @(posedge clk) begin
 + if (!reset) begin
 + decode_out <​=7'​b000_0000;​
 + cnt <= 7;​ //​输出数据为7比特,由计数器cnt来控制。
 + end
 + else begin
 + if(counter == 5'​b01111)
 + cnt <= 7;
 + else begin
 + if (cnt == 0)
 + decode_valid <= 0;
 + else begin
 + decode_out <= data[cnt-1]; ​ //​将译码后的信号依次输出。
 + decode_valid <= 1;         //​输出信号有效。
 + cnt <= cnt-1;
 + end
 + end
 + end
 + end
 +
 +</​code>​
  
 \\ \\
 \\ \\
-### 5演示程文件说明 +### 4仿真结果 
 +图 16 3为ModelSim仿真的结果。图中对7位的M列1100000进行编译码。经过BCH编码后的输出为110000010011100。再经过信道后加入噪声后,第12位和第10位发生了变化,变为111010010011100。在经过译码后输出为1100000,证译码是正确的。 
 +{{ :​图16-3.png |图16-3 ​ 程序仿真结果}} 
 +<WRAP centeralign>​ 
 +**图16-3 ​ 程序仿真结果** 
 +</​WRAP>​
  
 +\\
 +\\
  
 +### 5. 运行结果
 +图 16 4是程序运行的结果。在signaltap中可以看到编解码的正确性。编码输入为0001001,经过信道后变为000100111001100,在经过解码后输出为0001001,译码正确。
 +{{ :​图16-4.png |图16-4 ​ 程序运行结果}}
 +<WRAP centeralign>​
 +**图16-4 ​ 程序运行结果**
 +</​WRAP>​
  
 +\\
 +\\
 +### 6. 演示程序文件说明
  
 +|文件名|功能|
 +|BCH.v|主程序|
 +|clock.v|时钟分频|
 +|m_serial.v|M序列产生|
 +|encoder.v|BCH编码|
 +|channel.v|信道噪声仿真|
 +|decoder.v|BCH解码|
 +|Test.v|测试程序,用于Modelsim仿真的测试程序,对BCH.v进行仿真|
  
 \\ \\
 \\ \\
-### 6. 演示程序使用+### 7. 演示程序使用 
 +演示设备要求:核心板 
 + 
 +演示步骤:把程序下载到开发板上,reset为复位键。KEY1为load信号输入。通过SignalTap观察运行结果。 ​