2021-08-31

基于FPGA的密勒(Miller)编解码 实现


一、Miller编码基本原理

上篇文章《曼切斯特编解码实现》,介绍了曼切斯特编解码的实现,本篇介绍Miller编解码的实现。

密勒码(Miller码)也称延迟调制码,是一种变形双相码。其编码规则:对原始符号“1”码元起始不跃变,中心点出现跃变来表示,即用10或01表示。信息码连“1”时,后面的“1”要交错编码;信息码中的“0”编码为双极非归零码“00”或者“11”,即码元中间不跳变;信息码单个“0”时,其前沿、中间时刻、后沿均不跳变;信息码连“0”时,两个“0”码元的间隔跳变。

简单来说由于密勒码是特殊的数字双相码(曼彻斯特编码),即当信息中数据为1的时候就用01或者10表示,当数据为0的时候,就是用00与11进行交替。

Miller码如下图所示

在这里插入图片描述
从图中可以看出,Miller码编码后,频率变换相对Manchester码缓慢了许多

二、Miller编码实现

Miller编码模块如下图所示
示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。
Bit_out:表示要编码的bit数据
Bit_out_valid:表示当前bit数据有效
Bit_out_tready:表示当前bit以完成编码输出
Miller_BitOut:表示Miller编码后输出

module Miller_Module(
 		input   clk,   //32M  
        
        input   Bit_out,
        input   Bit_out_valid,
        output  Bit_out_tready,
        
        output  Miller_BitOut  //2M  
    );
    
    //reg             Bit_out_tready=0;
    reg             Miller_BitOut=0; 
    reg     [7:0]   clk_cnt = 0;
    
    reg     [2:0]   state_reg = 0;
    reg     [1:0]   send_tmp  = 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
    reg [1:0]    pre_send_tmp  = 0;
    always @ (posedge clk) begin
            if(clk_cnt==15) begin                
                if(Bit_out==0 && (pre_send_tmp==2'b00  || pre_send_tmp==2'b01))
                    send_tmp<=2'b11;
                else if(Bit_out==0 && (pre_send_tmp==2'b11 || pre_send_tmp==2'b10))
                    send_tmp<=2'b00;
                else if(Bit_out==1 && (pre_send_tmp==2'b00  || pre_send_tmp==2'b10))
                    send_tmp<=2'b01;
                else if(Bit_out==1 && (pre_send_tmp==2'b11  || pre_send_tmp==2'b01))
                    send_tmp<=2'b10;
             end
             
             if(clk_cnt==0)  
                pre_send_tmp<= send_tmp;        
    end
    
    always @ (posedge clk) begin
        if(state_reg==1)
        begin
            if(clk_cnt==0)
                Miller_BitOut<=send_tmp[1];
            else if(clk_cnt==8)
                Miller_BitOut<=send_tmp[0];
        end
        else
                Miller_BitOut<=0;
    end
    
    assign   Bit_out_tready = (clk_cnt==13) ? 1'b1 :1'b0;  //提前2个时钟置高
endmodule

三、Miller解码实现

Miller解码模块如下图所示

在这里插入图片描述
Bit_in:表示解码的bit数据
Bit_in_valid:表示解码的bit数据有效
Miller_BitIn:表示要解码的Miller编码输入

在Miller解码时,首先需要寻找4个连0或连1,即2个码元宽度的00或11,因为4个连0前后都是1,4个连1前后都是0,找到4个连0或连1,就找到了解码的起始,之后就可以正确解出码元。

代码如下

module Miller_Demodule(
 		input   clk,   //32M  
        
        output   Bit_in,
        output   Bit_in_valid,        
        input    Miller_BitIn       //2M  
    );
    
    
    reg             Bit_in  = 0;
    reg             Bit_in_valid  = 0;
    reg     [7:0]   clk_cnt = 0;
    reg             bit_cnt = 0;
    reg     [4:0]   Miller_BitIn_tmp = 0;
    
    reg             Bit_sync  = 0;
    
    reg     [2:0]   state_reg = 0;
    
    reg             Miller_BitIn_r1 = 0;
    wire            Miller_BitIn_posedge = Miller_BitIn && (~Miller_BitIn_r1);

    always @(posedge clk) begin
        Miller_BitIn_r1<=Miller_BitIn;
    end
    
        
    always @ (posedge clk) begin
        case (state_reg)
        0:begin
            clk_cnt<=0;
            Bit_sync<=0;
            if(Miller_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((Miller_BitIn_tmp[3:0]==4'b0000 || Miller_BitIn_tmp[3:0]==4'b1111) && Bit_sync==0)//寻找 同步头   
                    Bit_sync<=1;                    
                else 
                if((Miller_BitIn_tmp[3:0]==4'b0000 || Miller_BitIn_tmp[3:0]==4'b0010
                    || Miller_BitIn_tmp[3:0]==4'b0100 || Miller_BitIn_tmp[3:0]==4'b0101  
                    || Miller_BitIn_tmp[3:0]==4'b1010  || Miller_BitIn_tmp[3:0]==4'b1011
                    || Miller_BitIn_tmp[3:0]==4'b1101  || Miller_BitIn_tmp[3:0]==4'b1111) 
                    && bit_cnt==1) //同步头 丢失后 重新寻找头
                begin
                    Bit_sync<=0;
                    state_reg<=0;
                end
                //else if(Miller_BitIn_tmp[4:0] == 5'b00000 || Miller_BitIn_tmp[4:0] == 5'b11111)  //当超过5个0或5个1时,Miller解码结束
                //    state_reg<=0;                 
            end   
                              
        end       
       endcase 
    end
    

    always @ (posedge clk) begin
    if(Bit_sync==1)
    begin
        if(clk_cnt==4)
            bit_cnt<=bit_cnt+1;
     end
     else
            bit_cnt<=0;
    end
    
    
    always @ (posedge clk) begin
    if(state_reg==1) begin
        if(clk_cnt==4)
            Miller_BitIn_tmp[4:0]<={Miller_BitIn_tmp[3:0],Miller_BitIn};
    end
    else
            Miller_BitIn_tmp[4:0]<=0;
    end
    
    always @ (posedge clk) begin
        if(clk_cnt==7 && bit_cnt==1) begin
            case(Miller_BitIn_tmp[1:0])
                2'b01,2'b10:Bit_in<=1;
                2'b11,2'b00:Bit_in<=0;
                default:Bit_in<=0;
         endcase
       end
    end
    
    always @ (posedge clk) begin
        if(bit_cnt==1 && clk_cnt==0 && Bit_sync==1) begin              
                Bit_in_valid<=1;              
        end
        else
               Bit_in_valid<=0; 

    end

endmodule

在上面代码中,当同步头丢失之后,需要重新寻找同步头,使用了如下语句判断同步头是否丢失。
可以思考一下为什么。

				if((Miller_BitIn_tmp[3:0]==4'b0000 || Miller_BitIn_tmp[3:0]==4'b0010
                    || Miller_BitIn_tmp[3:0]==4'b0100 || Miller_BitIn_tmp[3:0]==4'b0101  
                    || Miller_BitIn_tmp[3:0]==4'b1010  || Miller_BitIn_tmp[3:0]==4'b1011
                    || Miller_BitIn_tmp[3:0]==4'b1101  || Miller_BitIn_tmp[3:0]==4'b1111) 
                    && bit_cnt==1) //同步头 丢失后 重新寻找头
                begin
                    Bit_sync<=0;
                    state_reg<=0;
                end

四、Miller编解码实现

Miller编解码顶层模块如下图所示,顶层模块使用AXI-Lite接口。
在这里插入图片描述

module Miller_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         Miller_BitIn,
    output        Miller_BitOut    
    );
    
    
    reg         Bit_out  ;         //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
        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
        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;
    
///Miller 编码//    
    
    
    Miller_Module Miller_tx(
        .clk(clk),
        .Bit_out(Bit_out),
        .Bit_out_valid(Bit_out_valid),
        .Bit_out_tready(Bit_out_tready),
        .Miller_BitOut(Miller_BitOut)    
    );
       
 ///Miller 解码//    
   Miller_Demodule Miller_rx(
        .clk(clk),
        .Bit_in(Bit_in),
        .Bit_in_valid(Bit_in_valid),
  
        .Miller_BitIn(Miller_BitOut)//Mqst_BitIn    
    );
    
    
    
endmodule

仿真代码如下所示,与上篇Manchester编解码代码一样

module test_miller(

    );
    
     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         Miller_BitIn;
    wire        Miller_BitOut; 
    
        Miller_top Miller_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),
        .Miller_BitIn(Miller_BitIn) ,
        .Miller_BitOut(Miller_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
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mhlicq

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值