一、什么是曼切斯特编码?
曼切斯特编码(Manchester Encoding)是一种用于数字信号传输的编码方式,它通过将每个比特分成两个部分来表示数据。曼切斯特编码的主要特点是每个比特周期内都有电平变化,这种变化有助于确保信号的同步和直流平衡。对于现在高速串行通信系统来说,传输过程都不带时钟同步线,为了保证数据能够正确的恢复,我们就需要使其传输的信号保持直流均衡,避免长时间的直流偏置。曼切斯特编码就有以下的优点:
- 良好的同步性:曼切斯特编码每个比特周期内都有电平变化,这使得接收方能够轻松识别比特的边界。这种频繁的电平变化有助于保持发送方和接收方之间的时间同步,减少了数据传输中的错误。
- 直流平衡:曼切斯特编码通过确保每个比特周期内都有电平变化,有效地消除了直流偏移问题。这使得信号在长时间内不会偏移到一个固定的电平,有助于在某些传输介质(如光纤或无线)中保持信号质量。
- 抗干扰能力强:由于信号频繁变化,曼切斯特编码对噪声和干扰具有较好的抗干扰能力。即使在信号中存在一定的干扰,电平变化仍然可以帮助接收方正确解码数据。
二、曼切斯特编码原理
将输入的信号视为基带信号,输出为频带信号。我们知道曼切斯特是将每个bit分成两个部分来传输,因此频带与基带的数据频率为2:1 。即:传输1bit基带信号,将输出2bit频带信号。编码规则如下:
- 如果输入的基带信号为单bit的1,那么输出的频带信号为 1,0
- 如果输入的基带信号为单bit的0,那么输出的频带信号为 0,1
其编码示意图如下所示:
- T0时刻,clk_fre检测到clk_base上升沿到来,并且此时输入信号为0,所以输出信号为 0,1
- T2时刻,clk_fre检测到clk_base上升沿到来,并且此时输入信号为0,所以输出信号为 0,1
- T4时刻,clk_fre检测到clk_base上升沿到来,并且此时输入信号为0,所以输出信号为 0,1
- T6时刻,clk_fre检测到clk_base上升沿到来,并且此时输入信号为0,所以输出信号为 0,1
- T8时刻,clk_fre检测到clk_base上升沿到来,并且此时输入信号为1,所以输出信号为 1,0
- T10时刻,clk_fre检测到clk_base上升沿到来,并且此时输入信号为0,所以输出信号为 0,1
- T12时刻,clk_fre检测到clk_base上升沿到来,并且此时输入信号为1,所以输出信号为 1,0
- T14时刻,clk_fre检测到clk_base上升沿到来,并且此时输入信号为1,所以输出信号为 1,0
- T16时刻,clk_fre检测到clk_base上升沿到来,并且此时输入信号为0,所以输出信号为 0,1
由波形示意图可以看出,曼切斯特编码后的信号在每个时钟周期都有反转,这很好的避免了长时间的直流偏置。
三、Verilog实现曼切斯特编码
编码原理非常简单,就只需要一个小状态机,检测到基带时钟上升沿到来,同时判断输入的信号是0还是1再实现跳转即可,我们设置仿真代码:
`timescale 1ns / 1ps
module tb_manchester_code_top();
reg clk_fre ;
reg clk_fre_rst ;
reg clk_base ;
reg din ;
wire q ;
initial begin
clk_fre <= 0;
clk_fre_rst <=1;
clk_base <= 0;
din <= 0;
#200
clk_fre_rst <=0;
#200
@(posedge clk_base)
din <= 1;
@(posedge clk_base)
din <= 0;
@(posedge clk_base)
din <= 1;
@(posedge clk_base)
din <= 1;
@(posedge clk_base)
din <= 0;
#100 $stop;
end
always #5 clk_fre =~clk_fre;
always @(posedge clk_fre) #0.1 clk_base =~clk_base;
manchester_code_top u_manchester_code_top(
.clk_fre ( clk_fre ),
.clk_fre_rst ( clk_fre_rst ),
.clk_base ( clk_base ),
.din ( din ),
.q ( q ),
.data_in ( data_in ),
.data_out ( data_out )
);
endmodule
我们用基带时钟发送我们绘制波形图一样的数据(1,0,1,1,0)打开仿真:
可以看出仿真波形和我们绘制的波形图一模一样。
四、曼切斯特解码原理
输入的信号视为频带编码后的信号,输出为基带信号。解码规则如下:
-
如果输入的频带信号为单bit的1(前1后0),那么输出的基带信号为1
-
如果输入的基带信号为单bit的0(前0后1),那么输出的频带信号为0
-
T0时刻,clk_fre检测到clk_base下升沿到来,并且此时输入信号为0,所以输出信号为 0
-
T2时刻,clk_fre检测到clk_base下升沿到来,并且此时输入信号为0,所以输出信号为 0
-
T4时刻,clk_fre检测到clk_base下升沿到来,并且此时输入信号为0,所以输出信号为 0
-
T6时刻,clk_fre检测到clk_base下升沿到来,并且此时输入信号为0,所以输出信号为 0
-
T8时刻,clk_fre检测到clk_base下升沿到来,并且此时输入信号为0,所以输出信号为 0
-
T10时刻,clk_fre检测到clk_base下升沿到来,并且此时输入信号为1,所以输出信号为1
-
T12时刻,clk_fre检测到clk_base下升沿到来,并且此时输入信号为0,所以输出信号为 0
-
T14时刻,clk_fre检测到clk_base下升沿到来,并且此时输入信号为1,所以输出信号为 1
-
T16时刻,clk_fre检测到clk_base下升沿到来,并且此时输入信号为1,所以输出信号为 1
-
T18时刻,clk_fre检测到clk_base下升沿到来,并且此时输入信号为0,所以输出信号为 0
最终恢复出我们最开始发送的基带信号(1,0,1,1,0)
五、Verilog实现曼切斯特解码
解码就是编码反正来,我们把仿真文件里,编码后输出的q接到解码的输入里,代码如下:
`timescale 1ns / 1ps
module tb_manchester_code_top();
reg clk_fre ;
reg clk_fre_rst ;
reg clk_base ;
reg din ;
wire q ;
initial begin
clk_fre <= 0;
clk_fre_rst <=1;
clk_base <= 0;
din <= 0;
#200
clk_fre_rst <=0;
#200
@(posedge clk_base)
din <= 1;
@(posedge clk_base)
din <= 0;
@(posedge clk_base)
din <= 1;
@(posedge clk_base)
din <= 1;
@(posedge clk_base)
din <= 0;
#100 $stop;
end
always #5 clk_fre =~clk_fre;
always @(posedge clk_fre) #0.1 clk_base =~clk_base;
manchester_code_top u_manchester_code_top(
.clk_fre ( clk_fre ),
.clk_fre_rst ( clk_fre_rst ),
.clk_base ( clk_base ),
.din ( din ),
.q ( q ),
.data_in ( q ),
.data_out ( data_out )
);
endmodule
可以看到最后解码后的信号和一开始输入信号din一模一样。