2017-04-09 93 views
1

我的PRN發生器不工作。我想用線性反饋移位寄存器來做到這一點。輸出保持不變

模擬和編譯工作沒有問題,但輸出是錯誤的(lfsr_out ='0'),並沒有改變。

代碼:在output_logic

library ieee; 
use ieee.std_logic_1164.all; 
use ieee.std_logic_unsigned.all; 
use ieee.numeric_std.all; 

entity lfsr_counter is 
    generic(
    WIDTH : integer := 10 
); 
    port(
    clk  : in std_logic;  --clock 
    rst  : in std_logic;  --positiv rst 
    lfsr_out : out std_logic  --1 bit output of lfsr 
); 
end lfsr_counter; 

------------------------------------------------------------------- 

architecture behavioral of lfsr_counter is 
    type state_type is (state_rst, state_go); --rst: reset; go: lfsr 
shifts 

    signal present_state : state_type; 
    signal next_state : state_type; 
    signal lfsr   : std_logic_vector((WIDTH - 1) downto 0) := 
(others => '0'); 
    signal d0   : std_logic        := '0'; 
--stores the current feedbackvalue 

begin 

    --sequencial logic: 
    ------------------------------------------------------------------- 
    state_register : process(clk, rst) 
    begin 
    if (rst = '1') then 
     present_state <= state_rst; --default state on reset. 
    elsif (rising_edge(clk)) then 
     present_state <= next_state; --state change 
    end if; 
    end process; 

    -- combinatorial logic 
    ------------------------------------------------------------------- 

    comb_logic : process(present_state, rst) 
    begin 
    case present_state is 
     when state_rst => 
     if (rst = '1') then 
      next_state <= state_rst; 
     else 
      next_state <= state_go; 
     end if; 
     when state_go => 
     if (rst = '1') then 
      next_state <= state_rst; 
     else 
      next_state <= state_go; 
     end if; 
    end case; 
    end process; 

    output_logic : process(present_state) 
    begin 
    if (present_state = state_go) then 
     --assert ((WIDTH >= 3) and (WIDTH <= 10)) 
     --report "Error: the LFSR width must be between 3 and 10" severity 
failure; 
     case WIDTH is    --definitions for the feedback 
     when 3  => d0 <= lfsr(2) xnor lfsr(1); 
     when 4  => d0 <= lfsr(3) xnor lfsr(2); 
     when 5  => d0 <= lfsr(4) xnor lfsr(2); 
     when 6  => d0 <= lfsr(5) xnor lfsr(4); 
     when 7  => d0 <= lfsr(6) xnor lfsr(5); 
     when 8  => d0 <= lfsr(7) xnor lfsr(5) xnor lfsr(4) xnor 
lfsr(3); 
     when 9  => d0 <= lfsr(8) xnor lfsr(4); 
     when 10  => d0 <= lfsr(9) xnor lfsr(6); 
     when others => null; 
     end case; 
     lfsr  <= std_logic_vector(unsigned(lfsr) sll 1); --shifting all 
bits to left by 1 
     lfsr_out <= lfsr(WIDTH - 1); --MSB to output 
     lfsr  <= lfsr(WIDTH - 1 downto 1) & d0; --concatenate the 
feedback to the lfsr 
    else 
     lfsr  <= (others => '0'); --reset state -> lfsr contains only 
'0' 
     lfsr_out <= '0'; 
    end if; 
    end process; 
end architecture; 

如果將 「lfsr_out < = '1'」,輸出將保持 '1'。我的代碼有什麼問題?

+0

不要同時使用'std_logic_unsigned'和'numeric_std'。使用後者並正確使用'signed'和'unsigned'(首選)。或者使用未簽名的std_logic_vector(不易讀取的imho)寫入所有內容。 – JHBonarius

回答

3

我的代碼有什麼問題?

您的移位寄存器值爲全0和XNOR將產生1的輸出d0。這是'1'的來源。

您可以使用generate語句生成d0,而不是帶有case語句的進程語句。

第一次分配給lfsr將不起作用,可以刪除。任何預定時間只有一個預計輸出波形。沒有後續延遲的分配將導致增量循環。兩個在相同的三角洲週期和最後一個將生效。因此,您不需要包std_logic_unsigned(Synopsys)或numeric_std(IEEE)。

合成結果

LFSR是不是一個時鐘控制寄存器,它是一個組合循環總是生產中合成硬件「1」。這是由於缺乏順序轉換造成的。

此外,您的模擬如何在沒有問題的情況下工作?過程output_logic將僅恢復present_state上的事件。

扔掉分離狀態機實現時鐘LFSR移位寄存器和使用產生語句:

library ieee; 
use ieee.std_logic_1164.all; 
-- use ieee.std_logic_unsigned.all; 
-- use ieee.numeric_std.all; 

entity lfsr_counter is 
    generic (
     -- WIDTH: integer := 10 
     WIDTH: positive range 3 to 10 := 10 
    ); 
    port (
     clk:  in std_logic; 
     rst:  in std_logic;  -- positive rst 
     lfsr_out: out std_logic 
    ); 
end entity lfsr_counter; 

architecture behavioral of lfsr_counter is 
    -- type state_type is (state_rst, state_go); 
    -- signal present_state: state_type; 
    -- signal next_state:  state_type; 
    signal lfsr: std_logic_vector((WIDTH - 1) downto 0) := (others => '0'); 
    signal d0:    std_logic := '0'; 
begin 
-- state_register: 
--  process (clk, rst) 
--   begin 
--   if rst = '1' then 
--    present_state <= state_rst; 
--   elsif rising_edge(clk) then 
--    present_state <= next_state; 
--   end if; 
--  end process; 

-- comb_logic: 
    -- process (present_state, rst) 
    -- begin 
    --  case present_state is 
    --   when state_rst => 
    --    if rst = '1' then 
    --     next_state <= state_rst; 
    --    else 
    --     next_state <= state_go; 
    --    end if; 
    --   when state_go => 
    --    if rst = '1' then 
    --     next_state <= state_rst; 
    --    else 
    --     next_state <= state_go; 
    --    end if; 
    --  end case; 
    -- end process; 

-- Using VHDL -2008 you could use a case generate or elsif 
WIDTH3: 
    if WIDTH = 3 generate 
     d0 <= lfsr(2) xnor lfsr(1); 
    end generate; 
WIDTH4: 
    if WIDTH = 4 generate 
     d0 <= lfsr(3) xnor lfsr(2); 
    end generate; 
WIDTH5: 
    if WIDTH = 5 generate 
     d0 <= lfsr(4) xnor lfsr(2); 
    end generate; 
WIDTH6: 
    if WIDTH = 6 generate 
     d0 <= lfsr(5) xnor lfsr(4); 
    end generate; 
WIDTH7: 
    if WIDTH = 7 generate 
     d0 <= lfsr(6) xnor lfsr(5); 
    end generate; 
WIDTH8: 
    if WIDTH = 8 generate 
     d0 <= lfsr(7) xnor lfsr(5) xnor lfsr(4) xnor lfsr(3); 
    end generate; 
WIDTH9: 
    if WIDTH = 9 generate 
     d0 <= lfsr(8) xnor lfsr(4); 
    end generate; 
WIDTH10: 
    if WIDTH = 10 generate 
     d0 <= lfsr(9) xnor lfsr(6); 
    end generate; 
-- output_logic: 
--  process (present_state) 
--  begin 
--  if present_state = state_go then 
--   case WIDTH is 
--    when 3 => 
--     d0 <= lfsr(2) xnor lfsr(1); 
--    when 4 => 
--     d0 <= lfsr(3) xnor lfsr(2); 
--    when 5 => 
--     d0 <= lfsr(4) xnor lfsr(2); 
--    when 6 => 
--     d0 <= lfsr(5) xnor lfsr(4); 
--    when 7 => 
--     d0 <= lfsr(6) xnor lfsr(5); 
--    when 8 => 
--     d0 <= lfsr(7) xnor lfsr(5) xnor lfsr(4) xnor lfsr(3); 
--    when 9 => 
--     d0 <= lfsr(8) xnor lfsr(4); 
--    when 10 => 
--     d0 <= lfsr(9) xnor lfsr(6); 
--    when others => 
--     null; 
--   end case; 
--   -- lfsr  <= lfsr sll 1; 
--   lfsr_out <= lfsr(WIDTH - 1); 
--   lfsr  <= lfsr(WIDTH - 1 downto 1) & d0; 
--  else 
--   lfsr  <= (others => '0'); 
--   lfsr_out <= '0'; 
--   end if; 
--  end process; 
lfsr_reg: 
    process (rst, clk) 
    begin 
     if rst = '1' then 
      lfsr <= (others =>'0'); 
     elsif rising_edge(clk) then 
      lfsr <= lfsr(WIDTH - 2 downto 0) & d0; -- WAS WIDTH - 1 downto 1 
     end if; 
    end process; 

    lfsr_out <= lfsr(WIDTH - 1); -- not separately registered 

end architecture; 

與生成聲明(S)位做什麼有趣的,但是從合成卸載工作,這將有在門檻綜合報告中選擇所有這些任務。

另外用一個附加的測試臺創建一個Minimal, Complete and Verifiable example我們看到lfsr並沒有實際向左移動。的修復程序中示出在上面的代碼,並涉及一個變化:

lfsr <= lfsr(WIDTH - 2 downto 0) & d0; -- WAS WIDTH - 1 downto 1 

測試平臺:

library ieee; 
use ieee.std_logic_1164.all; 

entity lfsr_counter_tb is -- a testbench 
end entity; 

architecture foo of lfsr_counter_tb is 
    constant WIDTH: positive range 1 to 10 := 10; -- test full length 
    signal clk:  std_logic := '1'; 
    signal rst:  std_logic := '0'; 
    signal lfsr_out: std_logic; 
begin 
DUT: 
    entity work.lfsr_counter 
     generic map (
      WIDTH => WIDTH 
     ) 
     port map (
      clk => clk, 
      rst => rst, 
      lfsr_out => lfsr_out 
     ); 
CLOCK: 
    process 
    begin 
     wait for 10 ns; 
     clk <= not clk; 
     if now > 550 ns then 
      wait; 
     end if; 
    end process; 
STIMULUS: 
    process 
    begin 
     wait for 11 ns; 
     rst <= '1'; 
     wait for 99 ns; 
     rst <= '0'; 
     wait; 
    end process; 
end architecture; 

模擬:

lfsr_counter_tb.png

而且lfsr_counter應合成和功能以及。

嗯。在我們的數字設計課程中從未聽說過關於生成語句這在某些情況下可能非常有用。謝謝你的這個例子。我瞭解你的代碼。這真的很簡單,自我解釋。你也可以避免組合循環。但是,這是一種不同的方法。我仍然希望將它作爲FSM來實現,並理解FSM的機制。現在,我知道output_logic部分沒有計時,這導致梳子。循環。此外,只有lfsr的最後一條語句正在執行。我需要編輯什麼才能使其工作?

就像他們說的是一個不同的問題。一個特別的,今天只。

您的代碼顯示編程語言思維,而VHDL是硬件描述語言。例如,當任何進程尚未恢復或隨後在當前模擬循環中暫停時,不發生信號更新。這意味着d0不想成爲一個信號,或者它的任務想要處於一個單獨的過程中。

信號在進程之間進行通信。對於僅在流程內部使用的對象,如果在賦值後評估值,則應該使用變量。

還有使用WIDTH分配d0的多路複用器。它代表硬件在合成過程中會讓門吃掉,因爲WIDTH不變,作爲一個通用常量傳遞。

通用常量可以定義標量範圍:

library ieee; 
use ieee.std_logic_1164.all; 
-- use ieee.std_logic_unsigned.all; 
-- use ieee.numeric_std.all; 

entity lfsr_counter is 
    generic (
     -- WIDTH: integer := 10 
     WIDTH: positive range 3 to 10 := 10 
    ); 
    port (
     clk:  in std_logic; 
     rst:  in std_logic;  -- positive rst 
     lfsr_out: out std_logic 
    ); 
end entity lfsr_counter; 

這樣寫VHDL設計描述不具有處理之外你用什麼值。所有額外的邏輯都會被吃掉,但是你可以引入錯誤。

因此,與D0做出一個變量,寬度限制以及lsfr_out分配移動到併發聲明:

architecture behave of lfsr_counter is 
    type state_type is (state_rst, state_go); 
    signal present_state: state_type; 
    signal next_state:  state_type; 
    signal lfsr: std_logic_vector((WIDTH - 1) downto 0) := (others => '0'); 
    -- signal d0:    std_logic := '0'; 
begin 
state_register: 
    process (clk, rst) 
     begin 
     if rst = '1' then 
      present_state <= state_rst; 
     elsif rising_edge(clk) then 
      present_state <= next_state; 
     end if; 
    end process; 

comb_logic: 
    process (present_state, rst) 
    begin 
     case present_state is 
      when state_rst => 
       if rst = '1' then 
        next_state <= state_rst; 
       else 
        next_state <= state_go; 
       end if; 
      when state_go => 
       if rst = '1' then 
        next_state <= state_rst; 
       else 
        next_state <= state_go; 
       end if; 
     end case; 
    end process; 

output_logic: 
    process (clk) -- (present_state) 
     variable d0: std_logic; 
    begin 
     if rising_edge(clk) then 
      if present_state = state_go then 
       case WIDTH is 
        when 3 => 
         d0 := lfsr(2) xnor lfsr(1); 
        when 4 => 
         d0 := lfsr(3) xnor lfsr(2); 
        when 5 => 
         d0 := lfsr(4) xnor lfsr(2); 
        when 6 => 
         d0 := lfsr(5) xnor lfsr(4); 
        when 7 => 
         d0 := lfsr(6) xnor lfsr(5); 
        when 8 => 
         d0 := lfsr(7) xnor lfsr(5) xnor lfsr(4) xnor lfsr(3); 
        when 9 => 
         d0 := lfsr(8) xnor lfsr(4); 
        when 10 => 
         d0 := lfsr(9) xnor lfsr(6); 
        -- when others => 
        --  null; 
       end case; 
       -- lfsr  <= lfsr sll 1; 
       -- lfsr_out <= lfsr(WIDTH - 1); 
       -- lfsr  <= lfsr(WIDTH - 1 downto 1) & d0; 
       lfsr <= lfsr(WIDTH - 2 downto 0) & d0; 
      else 
       lfsr  <= (others => '0'); -- a synchronous reset 
       -- lfsr_out <= '0'; 
      end if; 
     end if; 
    end process; 

    lfsr_out <= lfsr(WIDTH - 1); -- not separately registered, a mux 

end architecture behave; 

所有從你的第一架構變化顯示,原代碼註釋。這使用相同的測試平臺進行分析,闡述和模擬,併產生相同的結果。

移動lfsr_out賦值的原因基於與d0相同的問題,並帶有另一個觀察結果。 output_logic進程只會在找到靈敏度列表的信號上發生事件時纔會恢復執行。

這意味着您可能會錯過lfsr_out上的轉換來模擬您的第一個設計,或者意味着在上述行爲體系結構中使用帶時鐘的lfsr寄存器來延遲半個時鐘(用於下一個clk邊沿)。

您可以注意到lsfr分配更改實際上提供了一個轉換,如頂層代碼示例中的lfsr_reg過程。你會注意到,第一次分配給lfsr仍然被註釋掉了。

+0

不要將lfsr重置爲全零,否則將進入無效狀態。 – gsm

+1

@gsm - 您的評論不正確,請觀察波形。 – user1155120

+0

確實;我忽略了使用XNOR而不是XOR,其中全1的狀態是無效的 – gsm