曼切斯特 编解码 实现
一、曼切斯特码简介
曼彻斯特编码,也叫做相位编码(PE),是一个同步时钟编码技术。
曼彻斯特码是通过电平的跳变来对二进制数据“0”和“1”进行编码的。有两种不同的数据约定:第一种约定是由G. E. Thomas,Andrew S. Tanenbaum等人在1949年提出的,它规定“0”是由低到高的电平跳变表示,“1”是由高到低的电平跳变;第二种约定则是在IEEE 802.4(令牌总线)以及IEEE 802.3 (以太网)中规定,按照这样的说法,由低到高的电平跳变表示“1”,由高到低的电平跳变表示“0”。
曼切斯特编码如下图所示
二、曼彻斯特编解码器设计
曼彻斯特编码:本文采用第二种编码约定,即“1”的时候输出“01”,“0”的时候输出“10”
曼彻斯特解码:由编码器的特定,当曼彻斯特编码数据流中出现“00”,则“00”前后的码元必定是“1”;如果曼彻斯特编码数据流中出现“11”,则“11”前后的码元必定是“0”,因此,我们可以将“00”与“11”作为曼彻斯特码译码的标志位。 我们使用缓存器,储存上一个时钟采集到的信号和当前时钟采集到的信号,当缓存器的内容是“01”时,输出“1”;当缓存器的内容是“10”时,输出“0”;当缓存器的内容是“00”或“11”时,输出维持不变。
三、曼彻斯特编解码器实现
1.曼切斯特编码
曼切斯特编码模块如下图所示
Bit_out:表示要编码的bit数据
Bit_out_valid:表示当前bit数据有效
Bit_out_tready:表示当前bit以完成编码输出
Mqst_BitOut:表示曼切斯特编码后输出
module Mqst_Module(
input clk, //32M
input Bit_out,
input Bit_out_valid,
output Bit_out_tready,
output Mqst_BitOut //2M
);
reg Mqst_BitOut=0;
reg [1:0] send_tmp = 0;
reg [7:0] clk_cnt = 0;
reg [2:0] state_reg = 0;
reg Bit_out_valid_r1 = 0;
reg Bit_out_valid_r2 = 0;
wire Bit_out_valid_posedge = Bit_out_valid_r1 && (~Bit_out_valid_r2);
always @(posedge clk) begin
Bit_out_valid_r1<=Bit_out_valid;
Bit_out_valid_r2<=Bit_out_valid_r1;
end
always @ (posedge clk) begin
case (state_reg)
0:begin //数据有效后,开始编码
if(Bit_out_valid_posedge)
state_reg<=1;
end
1:begin
if(clk_cnt==32/2-1) begin//输入时钟32M、曼切斯特速率2M
clk_cnt<=0;
if(Bit_out_valid==0)
state_reg<=0;
end
else
clk_cnt<=clk_cnt+1;
end
endcase
end
always @ (posedge clk) begin //编码 0:编码为2'b10 1:编码为2’b01
if(Bit_out_valid==1)
begin
if(Bit_out==0)
send_tmp<=2'b10;
else
send_tmp<=2'b01;
end
else
send_tmp<=2'b00;
end
always @ (posedge clk) begin //曼切斯特编码输出
if(state_reg==1)
begin
if(clk_cnt==0)
Mqst_BitOut<=send_tmp[1];
else if(clk_cnt==8)
Mqst_BitOut<=send_tmp[0];
end
else
Mqst_BitOut<=0;
end
assign Bit_out_tready = (clk_cnt==13) ? 1'b1 :1'b0; //提前2个时钟置高
endmodule
2.曼切斯特解码
曼切斯特解码模块如下图所示
Bit_in:表示解码的bit数据
Bit_in_valid:表示解码的bit数据有效
Mqst_BitIn:表示要解码的曼切斯特编码输入
module Mqst_Demodule(
input clk, //32M
output Bit_in,
output Bit_in_valid,
input Mqst_BitIn //2M
);
reg Bit_in = 0;
reg Bit_in_valid = 0;
reg [7:0] clk_cnt = 0;
reg bit_cnt = 0;
reg [2:0] Mqst_BitIn_tmp = 0;
reg Bit_sync = 0; //同步 当收到2'b00或2'b11 作为解码的同步标志
reg [2:0] state_reg = 0;
reg Mqst_BitIn_r1 = 0;
wire Mqst_BitIn_posedge = Mqst_BitIn && (~Mqst_BitIn_r1);
always @(posedge clk) begin
Mqst_BitIn_r1<=Mqst_BitIn;
end
always @ (posedge clk) begin
case (state_reg)
0:begin
clk_cnt<=0;
Bit_sync<=0;
if(Mqst_BitIn_posedge)
state_reg<=1;
end
1:begin
if(clk_cnt==7) //输入时钟32M、曼切斯特速率2M
clk_cnt<=0;
else
clk_cnt<=clk_cnt+1;
if(clk_cnt==7)
begin
if((Mqst_BitIn_tmp[1:0]==2'b00 || Mqst_BitIn_tmp[1:0]==2'b11) && Bit_sync==0)//寻找 同步头
Bit_sync<=1;
else if((Mqst_BitIn_tmp[1:0]==2'b00 || Mqst_BitIn_tmp[1:0]==2'b11) && bit_cnt==1) //同步头 丢失后 重新寻找同步头
Bit_sync<=0;
else if(Mqst_BitIn_tmp[2:0] == 3'b000) //当收到3个零时,数据错误,重新开始解码
state_reg<=0;
end
end
endcase
end
always @ (posedge clk) begin //当 bit_cnt==1 时,才解码输出
if(clk_cnt==4 && Bit_sync==1)
bit_cnt<=bit_cnt+1;
end
always @ (posedge clk) begin //数据缓存
if(clk_cnt==4)
Mqst_BitIn_tmp[2:0]<={Mqst_BitIn_tmp[1:0],Mqst_BitIn};
end
always @ (posedge clk) begin //曼切斯特解码
if(clk_cnt==7 && bit_cnt==1) begin
case(Mqst_BitIn_tmp[1:0])
2'b01:Bit_in<=1;
2'b10:Bit_in<=0;
default:Bit_in<=0;
endcase
end
end
always @ (posedge clk) begin //曼切斯特 解码正确后Bit_in_valid有效
if(bit_cnt==1 && clk_cnt==7) begin
if(Mqst_BitIn_tmp[1:0]==2'b01 || Mqst_BitIn_tmp[1:0]==2'b10)
Bit_in_valid<=1;
else
Bit_in_valid<=0;
end
else
Bit_in_valid<=0;
end
endmodule
3.曼切斯特编解码仿真
编写曼切斯特编解码顶层模块,顶层模块如下图所示,顶层模块使用AXI-Lite接口。
仿真时,将Mqst_BitOut与Mqst_BitIn直接相连
module Mqst_top(
input clk,
input rst_p,
input [7:0] data_in,
input data_in_valid,
output data_tready,
output [7:0] data_out,
output data_out_valid,
input Mqst_BitIn,
output Mqst_BitOut
);
reg Bit_out =0 ; //1bit发送数据
reg Bit_out_valid =0 ;//1bit发送数据有效信号
wire Bit_out_tready; //发送1bit结束
wire Bit_in ; //1bit解码数据
wire Bit_in_valid; //1bit解码数据有效信号
reg [7:0] data_in_reg;
reg [7:0] bit_cnt = 0;
reg [2:0] state_reg = 0;
reg data_in_valid_r1 = 0;
reg data_in_valid_r2 = 0;
wire data_in_valid_posedge = data_in_valid_r1 && (~data_in_valid_r2);
/
always @(posedge clk) begin
data_in_valid_r1<=data_in_valid;
data_in_valid_r2<=data_in_valid_r1;
end
always @ (posedge clk) begin //编码8bit,
case (state_reg)
0:begin
if(data_in_valid_posedge)
begin
Bit_out_valid<=1;
state_reg<=1;
end
end
1:begin
if(Bit_out_tready) begin
if(bit_cnt==7) begin
bit_cnt<=0;
if(data_in_valid==0) begin
Bit_out_valid<=0;
state_reg<=0;
end
end
else
bit_cnt<=bit_cnt+1;
end
end
endcase
end
always @ (posedge clk) begin //字节数据输入
if(bit_cnt==0)
data_in_reg<=data_in;
end
always @ (posedge clk) begin //bit数据 进入曼切斯特编码模块
case(bit_cnt)
0:Bit_out<=data_in_reg[7];
1:Bit_out<=data_in_reg[6];
2:Bit_out<=data_in_reg[5];
3:Bit_out<=data_in_reg[4];
4:Bit_out<=data_in_reg[3];
5:Bit_out<=data_in_reg[2];
6:Bit_out<=data_in_reg[1];
7:Bit_out<=data_in_reg[0];
endcase
end
assign data_tready = (bit_cnt==7) ? 1: 0;
///曼切斯特 编码//
Mqst_Module Mqst_tx(
.clk(clk),
.Bit_out(Bit_out),
.Bit_out_valid(Bit_out_valid),
.Bit_out_tready(Bit_out_tready),
.Mqst_BitOut(Mqst_BitOut)
);
///曼切斯特 解码//
Mqst_Demodule Mqst_rx(
.clk(clk),
.Bit_in(Bit_in),
.Bit_in_valid(Bit_in_valid),
.Mqst_BitIn(Mqst_BitOut)//Mqst_BitIn
);
endmodule
仿真文件入下所示,每次发送完8bit,data_in[7:0]加1
module test_mqst(
);
reg clk;
reg rst_p;
reg [7:0] data_in = 0;
reg data_in_valid;
wire data_tready;
wire [7:0] data_out;
wire data_out_valid;
reg Mqst_BitIn;
wire Mqst_BitOut;
Mqst_top Mqst_top(
.clk(clk),
.rst_p(rst_p),
.data_in(data_in),
.data_in_valid(data_in_valid),
.data_tready(data_tready) ,
.data_out(data_out),
.data_out_valid(data_out_valid),
.Mqst_BitIn(Mqst_BitIn) ,
.Mqst_BitOut(Mqst_BitOut)
);
initial begin
#0
clk = 0;
rst_p =1;
data_in_valid = 0;
#100
rst_p = 0;
data_in_valid = 1;
end
always #15 clk =~clk;
always @ (posedge data_tready) begin
if(data_in==11)
begin
data_in<=0;
data_in_valid<=0;
end
else
data_in<=data_in+1;
end
endmodule
仿真结果如下图所示
图中,解码时,只有同步上之后数据才会输出,当连续收到3个0时,重新开始解码