题目:
试用 FPGA 实现如下 32bit 数据 32‘hCA535A7E 的 CMI 码,FPGA 输入时钟 30M,码流输出时钟为 5M,给出代码并仿真。
分析:
为了提高通信系统的有效性,一般需要对将要发送的数据进行 信源编码 ,通信信号信源编码的主要任务有两个:一是将信源送出的模拟信号数字化,即 A/D变换,用一定的数字脉冲组合来表示信号的一定幅度。通常将这种过程称为脉冲编码调制(PCM),简称为编码。二是提高信号传输的有效性,进行压缩编码。
编码信号反转码(CMI 码) :编码信号反转码(CMI 码)是由 CCITT 建议、适合于光信道传输的码型之一。其具体的编码规则是:二进制代码中的“1”码交替 地用 “11”和“00”表示;“0”码则固定地用“01”表示 。CMI 码是一种二元码。CMI 码的特点是电平随二进制数码依次跳变,因而便于恢复定时信号,尤其当用负跳变直接提取定时信号时,不会产生相位不确定问题。其具有检测错误的能力,因为在这种传输码中,只有 00、11、01 这三种码组,而没有 10 这一码组。编码规则如图所示:
![](https://img-blog.csdnimg.cn/2c0e14807ec24183b7198bffe3a1e6fe.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5ruH6KW_55S16YCa5bCP5a2m55Sf,size_20,color_FFFFFF,t_70,g_se,x_16)
为实现题目所需功能,需要设计一个编码模块,对输入数据进行编码,转换规则按照 CMI 的编码规则来编写,注意转码时钟的处理。由上图可知,一位的输入码字将编码为两位的码字,速率为原来的两倍。按照一位一位的转换,还需要一个将并行输入数据转为串行 的处理方法,这样就可以对每一位进行转换,完成编码过程。
主要设计框图如下所示:
![](https://img-blog.csdnimg.cn/3ea8daca32124b8c9a53274d713e2b7e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5ruH6KW_55S16YCa5bCP5a2m55Sf,size_20,color_FFFFFF,t_70,g_se,x_16)
设计代码如下:
//CMI 编码:
//二进制代码中的"1"码交替地用 "11"和"00"表示;"0"码则固定地用"01"表 示
module CMIcode(input clk,input rst,input [31:0]data,output [1:0]cmicode,output signal
);
parameter clkfreq=30000000, //系统时钟 30MHzdatafreq=5000000,freqcnt=clkfreq/datafreq;
reg dataclk; //码流时钟
reg [3:0] cnt;
reg [7:0] N;
reg [1:0] cmicode;
reg signal;
reg DATA;
reg [4:0] i;
reg [4:0] bitcnt;
//分频产生 5MHz 时钟
always @(posedge clk or negedge rst) beginif(!rst) begincnt<=1'b0;dataclk<=1'b0;endelse if(cnt==(freqcnt>>1)-1'b1) begindataclk<=~dataclk;cnt<=1'b0;endelsecnt<=cnt+1'b1;
end
always@(posedge dataclk or negedge rst) begin if(!rst) begini<=5'd31;endelse begini<=i-1'b1;if(i==1'b0) begini<=5'd31;endend
end
always@(posedge clk or negedge rst) begin if(!rst) beginDATA<=1'b0;endelse beginDATA<=data[i];end
end
always@(posedge dataclk or negedge rst) beginif(!rst) beginN<=0;cmicode<=0;endelse beginif(DATA==1'b0) begincmicode<=2'b01;endelse beginN<=N+1'b1;if(N[0]==1'b0) begincmicode<=2'b11;endelse begincmicode<=2'b00;end if(N==32) beginN<=1'b0;endend end
end
always@(posedge dataclk or negedge rst) beginif(!rst) beginsignal<=1'b0;bitcnt<=1'b0;endelse beginbitcnt<=bitcnt+1'b1;if(bitcnt==5'd31) beginsignal<=1'b1;bitcnt<=1'b0;endelse beginsignal<=1'b0;endend
end
endmodule
仿真的部分结果如下所示:
![](https://img-blog.csdnimg.cn/5e7383aa34824d3cbbd49ac261f31b93.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5ruH6KW_55S16YCa5bCP5a2m55Sf,size_20,color_FFFFFF,t_70,g_se,x_16)
由图可知,输入数值 32‘hCA535A7E 写成二进制形式后,被编码为 64 位的新二进制数,编码规则满足 CMI 编码,且在最后一位编码完毕后产生了脉冲,与理论结果一致,仿真正确。如按照一定速率传入所需要的输入数据,则可实现串行的 CMI 编码输出。
仿真代码如下:
`timescale 1ns / 1ps
module CMIcode_tb();
reg clk;
reg rst;
reg [31:0] data;
wire [1:0] cmicode;
wire signal;
always #16.67 clk<=~clk;
initial beginclk<=1'b0;rst<=1'b0;data<=32'b0;#20 rst<=1'b1;#20 data<=32'hCA535A7E;end
CMIcode code(.clk(clk),.rst(rst),.data(data),.cmicode(cmicode),.signal(signal)
);
endmodule