我的代碼有什麼問題?
您的移位寄存器值爲全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應合成和功能以及。
嗯。在我們的數字設計課程中從未聽說過關於生成語句這在某些情況下可能非常有用。謝謝你的這個例子。我瞭解你的代碼。這真的很簡單,自我解釋。你也可以避免組合循環。但是,這是一種不同的方法。我仍然希望將它作爲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仍然被註釋掉了。
不要同時使用'std_logic_unsigned'和'numeric_std'。使用後者並正確使用'signed'和'unsigned'(首選)。或者使用未簽名的std_logic_vector(不易讀取的imho)寫入所有內容。 – JHBonarius