本篇文章主要介绍了HDB3码的基本规则,相关的解码、编码方法,以及用MATLAB实现。最终的目的是使用Verilog语言完成一个HDB3的编码器和译码器。
HDB3全称(High Density Bipolar of order 3 code,三阶高密度双极性码)在学习通信原理这门课的时候有了解到这样的编码方式,但时间久远,我甚至连名字都记不起来了。我们可以简单的看一下HDB3码的百度百科。可以看到HDB3码是对AMI码的一个进阶。下面就了解一下编码规则以及机器实现的简便方法。
了解编码规则之前,先了解一下其中的关键名词。
了解了基本的编码规则,手算的方法有很多, 细心总能得到最后的结果。但是对于机器而言,应该有一种比较简单的方法,下面就介绍一下适合机器的编码方法。
1、源码是1时,暂时不变;
2、连0不超过3个时不变,有4个或以上连0时把每4个0换为取代节,即B00V;
3、确定B是0还是±1:第一个B一般取0,若两个取代节之间1的个数为偶,易推得后者的B一定是±1,此时B和1遵循的规则完全相同,可以直接记为1,即100V;为奇则一定是0,记为0,即000V。
4、统一确定极性:第一个非0符一般取-1,之后,根据前一个非0符极性,V取同,1取反;
我是按照这个步骤自己一步一步写的,效率比较低,网上有很多效率很高的代码,大家也可以去学习。
准备工作
%给出一个源码
Sn = [ 1 0 0 0 0 1 0 0 0 0 1 1 0 0 0 0 1 1 ];
n = length(sn);
codeSn = Sn;
第一步:找出源码中的取代节 V用2表示 B用3表示
count = 0; %用来记录 连0 的个数
for i = 1:n
if(codeSn(i) == 1)
count = 0; %遇到1 连0的计数器清零
else
count = count + 1;
if count == 4 % 0000 转成 取代节
codeSn(i) = 2;
codeSn(i-3) = 3;
count = 0; %计数清零
end
end
end
结果:
Sn = [ 1 0 0 0 0 1 0 0 0 0 1 1 0 0 0 0 1 1 ];
codeSn = [1 3 0 0 2 1 3 0 0 2 1 1 3 0 0 2 1 1];
可以看到四个连0 全部变成了取代节 3002 也就等价于 B00V。
第二步:处理取代节中B的值
flagB = 1;
count_1 = 0;
pV = 0;
pB = 0;
for i = 1:n
if (codeSn(i) == 3) && (flagB == 1) %将第一个B 置 0
codeSn(i) = 0;
flagB = 0;
end
if codeSn(i) == 2 %找到前一个取代节的V
pV = i;
else if codeSn(i) == 3 %找到后一个取代节的B
pB = i;
end
end
if(pB > pV)
for j = pV+1 : pB-1 %不要将B 和 V的值包含进去
count_1 = count_1 + codeSn(j); %计算两个之间 1 的个数
end
if mod(count_1 , 2) == 1 %奇数个
codeSn(pB) = 0;
else
codeSn(pB) = 1; %偶数个
end
%将变量归零,等待下一次找两个取代节的成功
pV = 0;
pB = 0;
count_1 = 0;
end
end
这一步的过程我写的太过于复杂。这要的功能是两个。
第一个:将第一个B转成0.
第二个:找到后一个取代节和前一个取代节之间1的个数,奇数个就将B变成0,偶数个就变成 1.
结果:codeSn =[1 0 0 0 2 1 0 0 0 2 1 1 1 0 0 2 1 1]
可以看到其中第一个B转成了0,后续一个变成了0,一个变成1;
第三步:%统一确定极性
%统一确定极性
even = 0; % 用来翻转 1 的极性
evenV = 0;% 用来翻转 V 的极性
for i = 1:n
if codeSn(i) == 1
codeSn(i) = -1; %第一个 1 转成 -1
break;
end
end
for i = 1:n
if codeSn(i) == 1 %将 1 的极性正负翻转
if even == 0
codeSn(i) = 1;
else
codeSn(i) = -1;
end
even = ~even;
else if codeSn(i) == 2 %将 V 的极性正负翻转 同时变回 数值 1
evenV = even; %第一个V的极性与前一个非零符号相同
if evenV == 0
codeSn(i) = -1;
else
codeSn(i) = 1;
end
evenV = ~evenV;
end
end
end
通过这一步来实现极性的全部分配,B在上一步已经全部变成1了,只要将1的极性正负交替就行。V的极性也要正负交替,第一个也给他整成-1能保持,V的两个特性了:1.自身极性交替。2.与前一个非0符号的极性相同。
结果:codeSn =[-1 0 0 0 -1 1 0 0 0 1 -1 1 -1 0 0 -1 1 -1];
到这里编码已经完成。下面将源码的图像和编码后的图像,打印出来,看一看区别。
实现代码:
%绘图部分
figure(1);
subplot(2,1,1);
stairs(0:length(Sn)-1,Sn);
axis([0 length(Sn) -2 2]);
title('源码图'); grid; %打开网格
subplot(2,1,2);
stairs(0:length(codeSn)-1,codeSn);
axis([0 length(codeSn) -2 2]);
title('hdb3编码图'); grid; %打开网格
完成hdb3的编码之后,下一步就是进行解码。解码的方式根据百度百科的介绍就可以,相对于编码,解码的过程比较简单。
%hdb3 解码部分
Sn = [-1 0 0 0 -1 1 0 0 0 1 -1 1 -1 0 0 -1 1 -1 ];
dchdbn = Sn; %定义一个输出数组
count = 0;
for j = 1 : length(Sn)
if Sn(j) == 0
count = count + 1;
if count == 3 %若3连“0”前后非零脉冲同极性,则将最后一个非零元素译为零
if dchdbn(j + 1) * dchdbn(j - 3) == 1
dchdbn(j + 1) = 0;
end
end
if count == 2 %若2连 “0”前后非零脉冲极性相同,则两零前后都译为零
if dchdbn(j + 1) * dchdbn(j - 2) == 1;
dchdbn(j - 2) = 0;
dchdbn(j + 1) = 0;
end
end
else
count = 0;
end
end
%极性变换
for n = 1 : length(Sn) %再将所有的-1变换成+1后,就可以得到原消息代码
if dchdbn(n) == -1
dchdbn(n) = 1;
end
end
结果:dchdbn = [1 0 0 0 0 1 0 0 0 0 1 1 0 0 0 0 1 1];
这里就不绘图展示最后的结果了。
总而言之,hdb3的编码规则就是这样,具体如何实现,看自己的思路了。之前学习过matlab但是,使用的次数不多,其中有很多功能还不知道。多多练习才是最近的捷径。MATLAB的仿真就是这样下面进行FPGA中的实验。将语言的风格转变为并行风格,又需要怎么样的编程思路那?
已经根据评论做出指正(2021.11.13)。