本章具体介绍误码率测试仪的基本功能的设计方法以及各部分的具体电路设计。主要包括 FPGA 内部的码型发生单元,误码插入单元、误码检测单元,同步单元,误码计数单元,模拟信道单元和显示单元组成。
本节将介绍各个功能模块的功能和实现的核心代码等。
码型发生单元主要描述的是伪随机序列产生模块,伪随机序列产生有两种方式:串行和并行。本节主要研究串行伪随机序列的产生方法,编写伪随机序列的产生代码。
(1)串行 m 序列生成模块
串行方式生成的m序列可以用于低速测试,在低速测试时,将测试数据通过接口直接发送到被测设备,不需要经过高速收发器进行转换。本设计采用线性反馈移位寄存器的方式设计m序列生成电路。在设计m序列时,关键是首先要确定寄存器的反馈方式,根据m序列本原多项式确定本设计的不同长度伪随机序列。移位寄存器的连接方式见表3-1。
表3-1 移位寄存器连接方式
以27-1伪随机序列为例,介绍串行m序列的生成方法。由表3-1可知,27-1伪随机序列的本原多项式为f ( x)=1+x6+x7,表示寄存器的第七级和第六级参与反馈,其VHDL核心代码如下:
误码插入单元主要实现在发送码中插入一定的误码,可以实现单一误码插入或者是插入一定比例的误码,插入一个误码的原理主要是对一个正确的码元取反,就是在随机序列产生模块的输出端设计一个取反电路,当选择插入一个误码时,取反电路开始工作,插入一个误码。 也可以在发从的码中插入一定比例的误码,其VHDL核心代码如下:
process(clk)
begin
if rising_edge(clk)then
case cnt_m is-----取反12位
when 11 =>m_o<=not m_i;
when 33 =>m_o<=not m_i
when 55=>m_o<=not m_i;
when 88 =>m_o<=not m_i;
when 111 =>m_o<=not m_i;
when 133 =>m_o<=not m_i;
when 155 =>m_o<=not m_i;
when 166 =>m_o<=not m_i;
when 199 =>m_o<=not m_i;
when 211 =>m_o<=not m_i;
when 233 =>m_o<=not m_i;
when 245 =>m_o<=not m_i;
when others=>m_o<=m_i;
end case;
end if;
end process;
误码检测单元及误码统计模块集成在一个模块里。同步信号提取及状态检测是误码统计的前提,该部分将在接下来进行介绍。误码统计模块统计误码个数。本节主要设计误码检测单元的各部分逻辑模块。下面是本模块的核心代码。
process(clk,rst,start)
begin
if rst='0'then
m<=0;
cnt<=1;
elsif rising_edge(clk)then
if start='0' then
m<=0;
cnt<=1;
else--同步成功使能有效时
if cnt>=255 then--循环255个时钟周期内,对比接收和本地M序列,统计误码数
err_cnt<=m;
cnt<=1;
m<=0;
else
cnt<=cnt+1;
end if;
if m_1 /= m_loc then--对比不相同,误码数+1
m<=m+1;
end if;
end if;
end if;
end process;
在接收端,要产生与发送端相同的 m 序列,然后进行两列数据的对比统计,这就要求两列数据具有相同的时钟控制,以保证数据相位的一致性和状态的一致性。在串行测试时,采用数字锁相环的方式提取出同步信号,同步信号同时控制本地 m 序列生成模块以及误码检测的其他模块工作。本模块采用了状态机进行功能实现,其状态转移图如下
图3-1 状态关系转移图
在该模块中,st0为初始状态,对收到的一串码和本地产生的伪随机码进行比对,如果连续的7个码中误码数不超过3个就认为本地的码和接受到的码已经同步,可以进行误码计数。St1的功能是比对本地和接收到的码,对其进行计数,用于st2判断误码的个数,st3是本地码和接收码未同步,对本地码进行暂停一个周期,加快对同步的检测。
该显示模块是对255个时钟周期内的误码个数进行显示,通过部分使用的是8段数码管,显示的有效值是误码的个数。该核心代码包括数码管的扫描,有效位数的提取等核心程序。其代码如下
process(clk)
variable m: integer range 0 to 24999;
begin
if rising_edge(clk)then--产生数码管显示使能跳转时钟
if m=24999 then
m:=0;
clk_1k<=not clk_1k;
else
m:=m+1;
end if;
end if;
end process;
--------------------------------------------------------
process(clk,rst,err_cnt)
begin
if rst='0'then
d3<=0;
d2<=0;
d1<=0;
err<=err_cnt;--载入误码数
elsif rising_edge(clk)then--提取各位显示数据
if err>=100 then
err<=err-100;
d3<=d3+1;
else
if err>=10 then
err<=err-10;
d2<=d2+1;
else
--err<=err_cnt;
d1<=err;
end if;
end if;
end if;
end process;
----------------------------------------------------
process(clk_1k)
begin
if rising_edge(clk_1k)then
if cnt=3 then
cnt<=1;
else
cnt<=cnt+1;
end if;
end if;
end process;
------------------------------------------------
process(clk)
begin
if rising_edge(clk)then
case cnt is
when 3=> scan<="011";
data<=d3;
when 2=> scan<="101";
data<=d2;
when 1=> scan<="110";
data<=d1;
when others=>
null;
end case;
end if;
end process;
-------------------------------------------
process(data)
begin
case data is
when 0=>seg<="11000000";
when 1=>seg<="11111001";
when 2=>seg<="10100100";
when 3=>seg<="10110000";
when 4=>seg<="10011001";
when 5=>seg<="10010010";
when 6=>seg<="10000010";
when 7=>seg<="11111000";
when 8=>seg<="10000000";
when 9=>seg<="10011000";
when others =>null;
end case;
end process;
本模块是为了验证设计的误码测试仪的正确性而设计的验证单元,其主要功能是模仿实际信道,对传输的码中加入一定的误码,然后将生成的序列发送给接收部分。其误码的加入调用了前面的误码产生模块。其核心代码如下
component sim_channel
port ( clk : in std_logic;
-- rst : in std_logic;
m_i : in std_logic;--模拟信道M序列输入
cnt_m : in integer;
m_o : out std_logic--模拟信道M序列输出
);
end component;
begin
sim_cha : sim_channel port map ( clk,m_i,cnt_m,m_o);
为了方便大家了解顶层电路各个模块的链接方式,已将各个子模块生成了symbol,然后也创建了一个原理图,下面贴出来供大家方便的了解该设计的主要思想。
你
图3-2误码检测顶层模块