实验(yàn)簡述:
本(běn)实验(yàn)的(de)目的(de)是(shì)实現(xiàn)漢明(míng)糾錯碼的(de)編碼和(hé)解(jiě)碼
一(yī)、漢明(míng)碼簡介
漢明(míng)碼,是(shì)在(zài)電(diàn)信(xìn)領域的(de)一(yī)種(zhǒng)線(xiàn)性(xìng)調試碼,以(yǐ)發(fà)明(míng)者(zhě)理查德 衛斯理 漢明(míng)的(de)名字(zì)命名。漢明(míng)碼在(zài)傳輸的(de)消息流中(zhōng)插入(rù)验(yàn)證碼,當計(jì)算機(jī)存儲或(huò)移動(dòng)數據(jù)时(shí),可(kě)能(néng)会(huì)産生(shēng)數據(jù)位錯誤,以(yǐ)偵测并更(gèng)正(zhèng)單一(yī)比特(tè)錯誤。由(yóu)于(yú)漢明(míng)編碼簡單,他(tā)们(men)被(bèi)廣泛應(yìng)用(yòng)于(yú)內(nèi)存。
與(yǔ)其他(tā)的(de)錯誤校(xiào)验(yàn)碼類(lèi)似,漢明(míng)碼也(yě)利用(yòng)了(le)奇偶校(xiào)验(yàn)位的(de)概念,通(tòng)过(guò)在(zài)數據(jù)位後(hòu)面(miàn)增加一(yī)些比特(tè),可(kě)以(yǐ)验(yàn)證數據(jù)的(de)有(yǒu)效性(xìng)。利用(yòng)一(yī)个(gè)以(yǐ)上(shàng)的(de)校(xiào)验(yàn)位,漢明(míng)碼不(bù)僅可(kě)以(yǐ)檢验(yàn)數據(jù)是(shì)否有(yǒu)效,還(huán)能(néng)在(zài)數據(jù)出(chū)錯的(de)情(qíng)況下(xià)指明(míng)錯誤的(de)位置。(漢明(míng)碼可(kě)以(yǐ)檢测两(liǎng)位錯誤,糾正(zhèng)一(yī)位錯誤)。
二(èr)、編碼規則
理解(jiě)漢明(míng)碼首先(xiān)要(yào)理解(jiě)奇偶校(xiào)验(yàn),奇校(xiào)验(yàn)就(jiù)是(shì)在(zài)一(yī)串編碼里(lǐ)增加一(yī)位校(xiào)验(yàn)位使这(zhè)一(yī)串編碼里(lǐ)的(de)1的(de)个(gè)數位奇數。偶校(xiào)验(yàn)同(tóng)理,使編碼里(lǐ)1的(de)个(gè)數为(wèi)偶數。
漢明(míng)碼的(de)編碼位數n與(yǔ)糾錯碼的(de)位數k的(de)關(guān)系(xì):2^k >= n+k+1。这(zhè)里(lǐ)給(gěi)出(chū)常用(yòng)的(de)n和(hé)k的(de)值:
|
n |
1 |
2-4 |
5-11 |
12-26 |
27-57 |
58-120 |
|
k |
2 |
3 |
4 |
5 |
6 |
7 |
我(wǒ)们(men)将糾錯碼加入(rù)到(dào)相應(yìng)的(de)編碼里(lǐ),糾錯碼的(de)位置必須在(zài)2^n位置上(shàng)。以(yǐ)10101100为(wèi)例進(jìn)行編碼。这(zhè)个(gè)序列为(wèi)8位,需要(yào)4个(gè)糾錯碼。
我(wǒ)们(men)先(xiān)将序列從1到(dào)8編号(hào)
|
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
|
1 |
0 |
1 |
0 |
1 |
1 |
0 |
0 |
然後(hòu)将糾錯碼(p1,p2,p3,p4)加到(dào)这(zhè)个(gè)序列里(lǐ) 的(de)2^n的(de)位置,并用(yòng)二(èr)進(jìn)制重(zhòng)新編号(hào)
|
0001 |
0010 |
0011 |
0100 |
0101 |
0110 |
0111 |
1000 |
1001 |
1010 |
1011 |
1100 |
|
p1 |
p2 |
1 |
p3 |
0 |
1 |
0 |
p4 |
1 |
1 |
0 |
0 |
然後(hòu)我(wǒ)们(men)要(yào)求出(chū)p1,p2,p3,p4的(de)值,先(xiān)将上(shàng)面(miàn)的(de)序列分(fēn)組編号(hào)为(wèi)xxx1的(de)分(fēn)为(wèi)一(yī)組,xx1x的(de)分(fēn)为(wèi)一(yī)組,x1xx的(de)分(fēn)为(wèi)一(yī)組,1xxx的(de)分(fēn)为(wèi)一(yī)組:
xxx1:p1,1,0,0,1,0
xx1x:p2,1,1,0,1,0
x1xx:p3,0,1,0,0
1xxx:p4,1,1,0,0
我(wǒ)们(men)采用(yòng)偶校(xiào)验(yàn),所(suǒ)以(yǐ)p1 = 1,p2 = 1, p3 = 1, p4 = 0。这(zhè)樣(yàng)我(wǒ)们(men)就(jiù)得到(dào)了(le)10101100的(de)漢明(míng)碼111101001100。
那(nà)麼(me)漢明(míng)碼是(shì)如(rú)何来(lái)糾錯的(de)呢?
我(wǒ)们(men)将p4,p3,p2,p1按这(zhè)个(gè)順序排列得到(dào)0111,这(zhè)个(gè)就(jiù)是(shì)出(chū)錯的(de)位數,由(yóu)于(yú)是(shì)二(èr)進(jìn)制傳輸,所(suǒ)以(yǐ)就(jiù)将相應(yìng)位取(qǔ)反(fǎn)就(jiù)可(kě)以(yǐ)得到(dào)正(zhèng)确的(de)序列了(le)。
三(sān)、FPGA实現(xiàn)
对(duì)于(yú)p1,p2,p3,p4的(de)計(jì)算在(zài)用(yòng)fpga实現(xiàn)时(shí)只(zhī)需進(jìn)行按位异(yì)或(huò)就(jiù)行。輸入(rù)數據(jù)位8位,需要(yào)四(sì)个(gè)糾錯位。
1、頂层架構
信(xìn)号(hào)说(shuō)明(míng):
|
信(xìn)号(hào) |
功能(néng) |
说(shuō)明(míng) |
|
clk |
工作时(shí)鐘(zhōng) |
外(wài)部(bù)輸入(rù) |
|
rst_n |
系(xì)統複位 |
外(wài)部(bù)輸入(rù) |
|
data |
輸入(rù)數據(jù) |
外(wài)部(bù)輸入(rù) |
|
wren |
写使能(néng) |
外(wài)部(bù)輸入(rù) |
|
rden |
读(dú)使能(néng) |
外(wài)部(bù)輸入(rù) |
|
q |
輸出(chū)數據(jù) |
輸出(chū) |
|
hc_out |
經(jīng)过(guò)漢明(míng)編碼後(hòu)輸出(chū) |
輸出(chū) |
|
hc_in |
輸入(rù)的(de)漢明(míng)碼 |
外(wài)部(bù)輸入(rù) |
頂层代(dài)碼:
2、 編碼模块(kuài)
編碼模块(kuài)只(zhī)需将分(fēn)組之後(hòu)的(de)每一(yī)組數據(jù)(不(bù)包(bāo)括p)按位异(yì)或(huò)後(hòu)賦值給(gěi)p就(jiù)可(kě)以(yǐ)。
編碼模块(kuài)代(dài)碼:
3、解(jiě)碼模块(kuài)
解(jiě)碼模块(kuài)只(zhī)需判斷哪位出(chū)錯,然後(hòu)取(qǔ)反(fǎn),并将糾錯位删除即可(kě)。
解(jiě)碼模块(kuài)代(dài)碼:
|
module hamming_decoder(clk, rst_n, rden, q, hc_in);
input clk, rst_n; input rden; output reg [7:0] q; input [11:0] hc_in;
wire g0_error, g1_error, g2_error,g3_error;
assign g0_error = hc_in[10] ^ hc_in[8] ^ hc_in[6] ^ hc_in[4] ^ hc_in[2] ^ hc_in[0]; assign g1_error = hc_in[10] ^ hc_in[9] ^ hc_in[6] ^ hc_in[5] ^ hc_in[2] ^ hc_in[1]; assign g2_error = hc_in[11] ^ hc_in[6] ^ hc_in[5] ^ hc_in[4] ^ hc_in[3]; assign g3_error = hc_in[11] ^ hc_in[10] ^ hc_in[9] ^ hc_in[8] ^ hc_in[7];
always @ (posedge clk or negedge rst_n)begin if(!rst_n) q <= 0; else if(rden) case ({g3_error, g2_error, g1_error, g0_error}) 4'b0000 : q <= {hc_in[11:8], hc_in[6:4], hc_in[2]}; 4'b0001 : q <= {hc_in[11:8], hc_in[6:4], hc_in[2]}; 4'b0010 : q <= {hc_in[11:8], hc_in[6:4], hc_in[2]}; 4'b0011 : q <= {hc_in[11:8], hc_in[6:4], ~hc_in[2]}; 4'b0100 : q <= {hc_in[11:8], hc_in[6:4], hc_in[2]}; 4'b0101 : q <= {hc_in[11:8], hc_in[6:5], ~hc_in[4], hc_in[2]}; 4'b0110 : q <= {hc_in[11:8], hc_in[6], ~hc_in[5], hc_in[4], hc_in[2]}; 4'b0111 : q <= {hc_in[11:8], ~hc_in[6], hc_in[5], hc_in[4], hc_in[2]}; 4'b1000 : q <= {hc_in[11:8], hc_in[6], hc_in[5], hc_in[4], hc_in[2]}; 4'b1001 : q <= {hc_in[11:9], ~hc_in[8], hc_in[6:4], hc_in[2]}; 4'b1010 : q <= {hc_in[11:10], ~hc_in[9], hc_in[8], hc_in[6:4], hc_in[2]}; 4'b1011 : q <= {hc_in[11], ~hc_in[10], hc_in[9], hc_in[8], hc_in[6:4], hc_in[2]}; 4'b1100 : q <= {~hc_in[11], hc_in[10], hc_in[9], hc_in[8], hc_in[6:4], hc_in[2]}; default : q <= 0; endcase else q <= 0; end
endmodule
|
四(sì)、仿真(zhēn)验(yàn)證
我(wǒ)们(men)用(yòng)$random系(xì)統函(hán)數産生(shēng)的(de)随機(jī)數来(lái)作为(wèi)編碼模块(kuài)數據(jù),用(yòng)$random系(xì)統函(hán)數産生(shēng)的(de)随機(jī)數来(lái)将hc_out的(de)哪一(yī)位取(qǔ)反(fǎn)来(lái)模拟噪聲。并判斷輸入(rù)的(de)數據(jù)和(hé)輸出(chū)的(de)數據(jù)是(shì)否相等,以(yǐ)验(yàn)證糾錯功能(néng)。用(yòng)$display和(hé)$error系(xì)統函(hán)數来(lái)生(shēng)成(chéng)報告。
测試文(wén)件(jiàn)代(dài)碼:
module humming_coder12_8_tb;
reg clk, rst_n;
reg [7:0] data;
reg rden, wren;
wire [11:0] hc_out;
reg [11:0] hc_in;
wire [7:0] q;
reg [7:0] temp1, temp2;
humming_coder12_8 DUT(
.clk(clk),
.rst_n(rst_n),
.data(data),
.wren(wren),
.q(q),
.rden(rden),
.hc_out(hc_out),
.hc_in(hc_in)
);
integer pn, i;
initial begin
pn = 0;
hc_in = 0;
forever begin
@ (posedge clk)
pn = {$random} %12;
#1
for (i=0; i<12; i=i+1) begin
if (i!= pn)
hc_in[i] = hc_out[i];
else
hc_in[i] = ~hc_out[i];
end
end
end
always @ (posedge clk)
begin
temp1 <= data;
temp2 <= temp1;
end
always @ (*)
begin
if (wren) begin
#1
if (temp2 == q)
$display("OK:time=%0t data=%0d q=%0d", $time, temp2, q);
else
$error("ERROR:time=%0t data=%0d q=%0d", $time, temp2, q);
end
end
initial begin
clk = 1;
rst_n = 0;
data = 0;
rden = 0;
wren = 0;
#200
@ (posedge clk)
rst_n = 1;
#200
forever begin
@ (posedge clk)
wren = 1;
data = {$random} % 9'b10000_0000;
@ (posedge clk)
wren = 1;
data = {$random} % 9'b10000_0000;
rden = 1;
end
end
always #10 clk = ~clk;
initial #5000 $stop;
endmodule
生(shēng)成(chéng)的(de)報告,我(wǒ)们(men)可(kě)以(yǐ)看(kàn)到(dào)錯誤的(de)數據(jù)可(kě)以(yǐ)被(bèi)修改成(chéng)原来(lái)正(zhèng)确的(de)數據(jù),證明(míng)我(wǒ)们(men)的(de)編碼解(jiě)碼模块(kuài)功能(néng)正(zhèng)确。

















