曼彻斯特编码是一种简单的编码方案,可将基本比特流转换为串行传输。这对于确保可以使用特定带宽进行数据传输非常有用,因为无论数据位的顺序如何,传输流的频率都将是原始数据频率的两倍。它还使信号恢复变得易如反掌,因为无需尝试时钟恢复,因为只需查找数据中的边缘并异步提取即可恢复数据。曼彻斯特编码的基本方法如图 15.1 所示。
该方案的另一个优点是该方法对数据中的错误具有高度的容忍度;如果发生错误,则后续数据完全不受发送器、介质或接收器错误的影响,在立即发生故障后,数据可以继续有效传输,无需进行错误恢复。当然,原始数据可以使用某种形式的数据编码来添加纠错(例如奇偶校验或循环冗余校验,CRC)。如果我们希望为这种类型的编码方案创建一个 VHDL 模型,它实际上是相对简单的。第一步是确定我们有一个数据输入 (D) 和一个时钟 (CLK)。为什么要同步?使用同步时钟,我们可以在时钟的上升沿对输入数据进行采样,并使用时钟的两个沿来定义输出的转换。我们这样做的方式就是简单的寻找clk上的任何事件(clk’event)然后检查clk是高还是低来判断clk边沿是上升还是下降。
图 15.2
带有 XOR 的曼彻斯特编码方案。
这个 VHDL 很简单,但还有一种更简单的方法来对数据进行编码,那就是简单地将时钟与数据进行异或。如果我们查看与图 15.1 所示相同的数据序列,我们可以看到,如果我们添加一个时钟,并观察原始数据和曼彻斯特编码输出,这只是数据与时钟的 XORd,如图 15.2 所示。
因此,使用这种简单的机制,我们可以创建一个更简单的曼彻斯特编码器,它对时钟和数据进行异或运算,以获得最终的曼彻斯特编码数据流。
同步Manchester的VHDL代码如下:
1 library ieee;
2 use ieee.std_logic_1664.all; 34 entity manchester_encoder is
5 port ( 6 clk : in std_logic;
7 d : in std_logic;
8 q : out std_logic
9 );
10 end entity manchester_encoder;
11
12 architecture basic of manchester_encoder is
13 signal lastd : std_logic := 0 ;
14 begin
15 p1: process ( clk )
16 begin
17 if clk’event and clk=’1’ then
18 if (d=0 ) then
19 q <= 1 ;
20 lastd <= 0 ;
21 elsif (d=1) then
22 q <= 0 ;
23 lastd <= 1 ;
24 else
25 q <= x ;
26 lastd <= x ;
27 end if;
28 else
29 if ( lastd = 0 ) then
30 q <= 0 ;
31 elsif ( lastd = 1 ) then
32 q <= 1 ;
33 else
34 q <= x ;
35 end if
36 end if;
37 end process p1;
38 end architecture basic;
异或方式实现Manchester编码的更简单的VHDL代码如下:
解码曼彻斯特数据流也是异步和同步方法之间的选择。
我们可以使用本地 clk 并检测输入的值来评估上升沿和下降沿上的值是 0 还是 1,
分别确定数据的值作为结果,
但很明显,这取决于发送器和接收器时钟同步到合理的程度。
这样一个简单的解码器可能如下所示:
1 entity manchester_decoder is
2 port ( 3 clk : in std_logic;
4 d : in std_logic;
5 q : out std_logic
6 );
7 end entity manchester_decoder;
89 architecture basic of manchester_decoder is
10 signal lastd : std_logic := 0 ;
11 begin
12 p1 : process (clk)
13 begin
14 if clk’event and clk=’1’ then
15 lastd <= d;
16 else
17 if (lastd = 0 ) and (d = 1 ) then
18 q <= 1 ;
19 elsif (lastd = 1 ) and (d= 0 ) then
20 q <= 0 ;
21 else
22 q <= x ;
23 end if;
24 end if;
25 end process p1;
26 end architecture basic;
在这个 VHDL 模型中,时钟与发送器时钟的速率相同,
并且数据应该以包的形式发送,以确保数据不会以太大的块发送,
那样时钟就会不同步,
并且还可以检查数据的完整性以纠正错误或接收器上的时钟异相。
FPGA中同步方式实现曼彻斯特编码的verilog 代码如下:
module manchester (
clk, // clock input
d, // data input
q // encoded output
);
input clk;
input d;
output q;
reg q;
reg lastd;
always_init begin
lastd <= 0;
end
always @ (clk) begin
if clk=’1’ begin
if d=1 then
begin
q <= 1;
lastd <= 0;
end
else
begin
q <= 0;
lastd <= 1;
end
end
else
begin
if lastd = 0 then
q <= 0;
else
q = 1;
end
end
endmodule
在FPGA中通过异或方式实现曼彻斯特编码更简单的verilog代码如下:
曼彻斯特解码同样也可以选取同步或者异步方式,我们可以使用本地 clk 并检测输入的值来分别评估上升沿和下降沿的值是 0 还是 1,从而确定数据的值,但这显然取决于发送器和接收器时钟同步到合适的程度。 这样一个简单的解码器可能如下所示:
在这个 VHDL模型中,时钟与发送器时钟的速率相同,
并且数据应该以数据包的形式发送,以确保数据不会以太大的块发送,从而导致时钟不同步,
并且还可以检查数据的完整性以纠正错误或接收器上的时钟相位不同步。