-1

在这里,我发布了 prbs 的快照

我的prbs模块代码是

-- Module Name:    prbs - Behavioral 
-- Project Name:   modulator

-- Description: 
--To make it of N bit replace existing value of N with desired value of N
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity prbs is
    Port ( pclock : in  STD_LOGIC;
            preset : IN std_logic := '0';
           prbsout : out  STD_LOGIC);
end prbs;

architecture Behavioral of prbs is

COMPONENT dff is
    PORT(
        dclock : IN std_logic;
        dreset : IN std_logic;
        din : IN std_logic ;          
        dout : OUT std_logic 
        );
    END COMPONENT;


signal dintern : std_logic_vector (4 downto 1); --Change value of N to change size of shift register
signal feedback : std_logic := '0';

begin

instdff : dff port map (pclock , preset , feedback , dintern(1));
genreg : for i in 2 to 4 generate --Change Value of N Here to generate that many instance of d flip flop
begin
instdff : dff port map ( pclock , preset , dintern(i-1) , dintern(i));
end generate genreg;

main : process(pclock)

begin
    if pclock'event and pclock = '1' then   
            if preset = '0'  then
                if dintern /= "0" then

                    feedback <= dintern(1) xor dintern(3); -- For N equals four;
                    --feedback <= dintern(4) xor dintern(5) xor dintern(6) xor dintern(8); -- For N equals eight;
                    --feedback <= dintern(11) xor dintern(13) xor dintern(14) xor dintern(16); -- For N equals sixteen;
                    --feedback <= dintern(1) xor dintern(2) xor dintern(22) xor dintern(32); -- For N equals thirty two                     

                else
                feedback <= '1';
                end if;
            end if;                                     
    end if; 
end process main;

prbsout <= dintern(4) ; --Change Value of N Here to take output to top entity 

end Behavioral;

在其中我正在实例化广告触发器模块

d ff 模块代码

----------------------------------------------------------------------------------
-- Module Name:    dff - Behavioral 
-- Project Name: 
-- Description: 
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity dff is
    Port ( dclock : in  STD_LOGIC ;
           dreset : in  STD_LOGIC ;
           din : in  STD_LOGIC;
           dout : out  STD_LOGIC);
end dff;

architecture Behavioral of dff is

begin
process(dclock)

begin
    if dclock'event and dclock = '1' then
        if dreset = '0' then
            dout <= din;
      else
            dout <= '1';
        end if;
    end if;
end process;


end Behavioral;

但我没有得到想要的输出。在顶级实体中,prbsout 信号我总是得到 1。

当我尝试模拟时,prbsout 信号变得未定义。

我错过了什么?

4

2 回答 2

2

prbs模块 reset atpreset不适用于信号,可能是因为其feedback意图是使用在feedback信号声明中分配的初始值 0。但是,由于dff模块使用同步复位,并且dintern信号在启动时是未驱动U的,并且此后feedback使用 xor 计算下一个值dintern(1),因此反馈将在启动后立即变得不确定,并且无法恢复,即使很长应用复位。请参阅下面的 ModelSim 波形。

在将预设应用于反馈之前

重置问题的直接解决方法是feedback在此main过程中也应用重置:

...
else  -- preset /= '0'
  feedback <= '0';
...

现在至少重置工作,并且可以使prbs生成序列。见下面的波形。

预设应用于反馈后

在代码中,只需对代码添加一些额外的注释:

  • 而不是dclock'event and dclock = '1'你可以使用rising_edge(dclock),我认为读者会发现它更容易理解,而且更不容易出错

  • 对于大多数工具来说,没有必要像模块那样只为触发器制作单独的dff模块,因为即使使用高级表达式进行信号分配,工具也可以直接从过程中推断出触发器。

但是,我不认为输出是你真正想要的。根据您的设计以及为 LFSR 选择的抽头,您似乎想要生成最大长度的 LFSR 序列,即长度为 2 ** N - 1 的序列,LFSR 寄存器为 N 位长。

LFSR 的原理和用于反馈生成的抽头在 Wikipedia:线性反馈移位寄存器中进行了描述。

但是,由于feedback信号是作为触发器生成的,它成为 LSFR 移位寄存器的一部分,因此长度增加了一个位,但抽头值仅基于dinternLFSR 的部分,抽头将是错误的。选择错误的位将导致 LFSR 序列小于最大序列,并且您还可以在仿真输出中看到,其中序列只有 6 个周期长,即使通过dintern(4 downto 1)+feedback一起构成一个 5 位寄存器。

prbs因此,如果您想要生成最大长度的 PRBS 序列,则需要对模块进行更彻底的重写,下面是如何prbs编写模块的示例:

library ieee;
use ieee.std_logic_1164.all;

entity prbs_new is
  generic(
    BITS : natural);
  port(
    clk_i  : in  std_logic;
    rst_i  : in  std_logic;
    prbs_o : out std_logic);
end entity;


library ieee;
use ieee.numeric_std.all;

architecture syn of prbs_new is

  signal lfsr : std_logic_vector(BITS downto 1);  -- Flip-flops with LFSR state

  function feedback(slv : std_logic_vector) return std_logic is  -- For maximum length LFSR generation
  begin
    case slv'length is
      when  3     => return slv( 3) xor slv( 2);
      when  4     => return slv( 4) xor slv( 3);
      when  8     => return slv( 8) xor slv( 6) xor slv( 5) xor slv(4);
      when 16     => return slv(16) xor slv(15) xor slv(13) xor slv(4);
      when 32     => return slv(32) xor slv(22) xor slv( 2) xor slv(1);
      when others => report "feedback function not defined for slv'lenght as " & integer'image(slv'length)
                     severity FAILURE;
                     return 'X';
    end case;
  end function;

begin

  process (clk_i, rst_i) is
  begin
    if rising_edge(clk_i) then
      if unsigned(lfsr) /= 0 then
        lfsr <= lfsr(lfsr'left - 1 downto lfsr'right) & feedback(lfsr);  -- Left shift with feedback in
      end if;
    end if;
    if rst_i = '1' then  -- Asynchronous reset
      lfsr <= std_logic_vector(to_unsigned(1, BITS));  -- Reset assigns 1 to lfsr signal
    end if;
  end process;

  prbs_o <= lfsr(BITS);  -- Drive output

end architecture;

对“prbs_new”模块的评论

  • 添加了通用 BITS,因此可以从相同的代码中生成不同的 LFSR 长度。

  • 端口用“_i”命名输入,用“_o”命名输出,因为这种命名约定在使用多个模块在顶层跟踪信号时非常有用。

  • 使用 VHDL 标准包ieee.numeric_std代替非标准包ieee.std_logic_unsigned

  • 信号声明中使用异步复位代替同步复位和初始值。

    • 与同步复位相比,异步复位通常适用于 FPGA 和 ASIC 技术中触发器的专用输入,而不是潜在的时序关键数据路径,因此设计可以更快。

    • 与信号衰减初始值相比的优势在于 FPGA 和 ASIC 技术更有可能实现这一点;有些情况下不支持初始值。此外,功能复位可以在测试台上重新启动,而无需重新加载模拟器。

  • 在此过程中不检查lfsr信号的全 0 值,因为lfsr如果使用适当的最大长度抽头,将永远不会获得全 0 值,并且lfsr信号被重置为非 0 值。

于 2013-08-30T15:22:34.477 回答
0

看起来您从未将内部状态(dtern)设置为已知值。由于所有后续状态都是根据您的初始 dtern 值计算的,因此它们也是未知的。尝试为 dintern 分配一个初始状态,或者修复您的预设代码以在预设高时实际执行某些操作(然后在您的测试平台开始时断言它)。

于 2013-08-30T14:42:17.030 回答