fpga曼彻斯特译码器设计(fpga 编解码)

实验简述

将输入的数据流经过曼彻斯特编码器编码后经过解码器恢复为原来的输入序列。

 

一、曼彻斯特码简介

曼彻斯特码(Manchester code),又称数字双向码、分相码或相位编码(PE),是一种常用的二源码线路编码方式之一,被物理层使用来编码一个同步位流的时钟和数据。在通信技术中,用来表示所要发送比特流中的数据宇定时信号所结合起来的代码。常用在以太网通信,列车总线控制,工业总线等领域。

 

二、编码规则

有两个输入时钟,一个是基带时钟(起同步信号作用),一个是频带时钟。输入的数据流是基带时钟域信号,经过编码后变成频带时钟域信号输出。曼彻斯特编码是将输入为1的变成输出前半拍为1,后半拍为0,输入为0的变成前半拍为0,后半拍为1的频带信号。

 

三、时序图

输入序列以101为例,经过编码后应为100110

fpga曼彻斯特译码器设计(fpga 编解码)

四、FPGA实现

1、顶层架构

fpga曼彻斯特译码器设计(fpga 编解码)

 

2、信号说明

 

fpga曼彻斯特译码器设计(fpga 编解码)

 

3、顶层代码

module manchester(clk_b, clk_f, rst_n, enc_in, enc_en, dec_out, dec_en);

 

input clk_b, clk_f, rst_n;

input enc_in;

input enc_en;

output dec_out;

input dec_en;

wire enc_out;

manchester_enc ENC(

.clk_f(clk_f),

.clk_b(clk_b),

.rst_n(rst_n),

.enc_en(enc_en),

.enc_in(enc_in),

.enc_out(enc_out)

);

manchester_dec DEC(

.clk_f(clk_f),

.clk_b(clk_b),

.rst_n(rst_n),

.dec_en(dec_en),

.enc_out(enc_out),

.dec_out(dec_out)

);

endmodule

 

fpga曼彻斯特译码器设计(fpga 编解码)

4、编码模块

 

采用状态机来实现编码模块。

当检测到编码使能为高时,状态机开始执行,判断clk_b的值为1时,在S1状态等待,当clk_b的值为0时,判断输入的值是1还是0。(clk_b主要起基频同步作用)如果是1,跳转到S2状态,并将enc_out赋值为1。到S2状态后,无条件跳回S1状态,并将enc_out赋值为0。如果是0,跳转到S3状态,并将enc_out赋值为0。到S3状态后,无条件跳回S1状态,并将enc_out赋值为1。

状态转移图如下:

 

fpga曼彻斯特译码器设计(fpga 编解码)

说明:圆圈代表状态,→ 代表转移,转移下面的文本框代表转移时的动作。以后文章的状态转移图均按此绘制。

 

编码模块代码

module manchester_enc(clk_f, clk_b, rst_n, enc_en, enc_in, enc_out);

 

input clk_f, clk_b, rst_n;

input enc_en;

input enc_in;

output reg enc_out;

reg [2:0] state_c, state_n;

localparam S1 = 3'b001;

localparam S2 = 3'b010;

localparam S3 = 3'b100;

wire S12S2_start ;

wire S12S3_start ;

wire S22S1_start ;

wire S33S1_start ;

//四段式状态机

 

//第一段:同步时序always模块,格式化描述次态寄存器迁移到现态寄存器(不需更改-

always@(posedge clk_f or negedge rst_n)begin

if(!rst_n)begin

state_c <= S1;

end

else begin

state_c <= state_n;

end

end

 

//第二段:组合逻辑always模块,描述状态转移条件判斍

always@(*)begin

if(enc_en)

case(state_c)

S1:begin

if(S12S2_start)begin

state_n = S2;

end

else if(S12S3_start)begin

state_n = S3;

end

else begin

state_n = state_c;

end

end

S2:begin

if(S22S1_start)begin

state_n = S1;

end

else begin

state_n = state_c;

end

end

S3:begin

if(S33S1_start)begin

state_n = S1;

end

else begin

state_n = state_c;

end

end

default:begin

state_n = S1;

end

endcase

else

state_n = S1;

end

//第三段:设计转移条件

assign S12S2_start = state_c==S1 && clk_b && !enc_in;

assign S12S3_start = state_c==S1 && clk_b && enc_in;

assign S22S1_start = state_c==S2 && 1;

assign S33S1_start = state_c==S3 && 1;

 

//第四段:同步时序always模块,格式化描述寄存器输出(可有多个输出-

always @(posedge clk_f or negedge rst_n)begin

if(!rst_n)begin

enc_out <=1'b0; //初始匍

end

else if(enc_en)

if((state_c==S1 && !enc_in) || (state_c==S3))begin

enc_out <= 1'b0;

end

else if((state_c==S1 && enc_in) || (state_c==S2))begin

enc_out <= 1'b1;

end

else begin

enc_out <= 1'b0;

end

else

enc_out <=1'b0;

end

 

endmodule

 

5、 解码模块

 

解码模块也采用状态机实现,当检测到dec_en为高时,状态机才执行,判断clk_b的值,当clk_b为0时,在S1上等待,当clk_b为1时,判断enc_out的值,为1时跳转到S2状态,并将dec_out赋值为。S2状态无条件跳转到S1状态。为0时,跳转到S3状态并将dec_out赋值为0。S3状态无条件跳转到S1状态。

状态转移图如下:

fpga曼彻斯特译码器设计(fpga 编解码)

 

解码模块代码

module manchester_dec(clk_f, clk_b, rst_n, dec_en, enc_out, dec_out);

 

input clk_f, clk_b, rst_n;

input dec_en;

input enc_out;

output reg dec_out;

reg [2:0] state_c, state_n;

localparam S1 = 3'b001;

localparam S2 = 3'b010;

localparam S3 = 3'b100;

wire S12S2_start ;

wire S12S3_start ;

wire S22S1_start ;

wire S33S1_start ;

always@(posedge clk_f or negedge rst_n)begin

if(!rst_n)begin

state_c <= S1;

end

else begin

state_c <= state_n;

end

end

 

//第二段:组合逻辑always模块,描述状态转移条件判斍

always@(*)begin

if(dec_en)

case(state_c)

S1:begin

if(S12S2_start)begin

state_n = S2;

end

else if(S12S3_start)begin

state_n = S3;

end

else begin

state_n = state_c;

end

end

S2:begin

if(S22S1_start)begin

state_n = S1;

end

else begin

state_n = state_c;

end

end

S3:begin

if(S33S1_start)begin

state_n = S1;

end

else begin

state_n = state_c;

end

end

default:begin

state_n = S1;

end

endcase

else

state_n = S1;

end

//第三段:设计转移条件

assign S12S2_start = state_c==S1 && (!clk_b) && enc_out;

assign S12S3_start = state_c==S1 && (!clk_b) && (!enc_out);

assign S22S1_start = state_c==S2 && 1;

assign S33S1_start = state_c==S3 && 1;

 

//第四段:同步时序always模块,格式化描述寄存器输出(可有多个输出-

always @(posedge clk_f or negedge rst_n)begin

if(!rst_n)begin

dec_out <=1'b0; //初始匍

end

else if(dec_en)

if(state_c==S1 && (!clk_b) && enc_out)begin

dec_out <= 1'b1;

end

else if((state_c==S1 && (!clk_b) && (!enc_out)))begin

dec_out <= 1'b0;

end

else begin

dec_out <= dec_out;

end

else

dec_out <=1'b0;

end

 

endmodule

 

6、仿真验证

 

tb文件参考工程文件夹中的sim文件夹

 

输入的数据流enc_in为1011,对应的曼彻斯特码应为10011010

fpga曼彻斯特译码器设计(fpga 编解码)

 

我们看到输入到编码模块的enc_in与解码模块的dec_out的输出是一样的

 

再来看编码之后的数据流

fpga曼彻斯特译码器设计(fpga 编解码)

enc_out为10011010与结果一致

 

解码模块图形

fpga曼彻斯特译码器设计(fpga 编解码)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发表评论

登录后才能评论