差别
这里会显示出您选择的修订版和当前版本之间的差别。
两侧同时换到之前的修订记录 前一修订版 | |||
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观察运行结果。 | ||