我一直在与一个相当大的项目进行斗争,我陷入了僵局,下面的代码模拟并按预期工作除了它在信号分配时将所有内存地址重新分配给UU 。该代码描述了具有集成堆栈指针的完全下降的堆栈。我正在尝试避免用于计时目的的进程语句,我真的希望内存块保留为信号数组(而不是变量数组)以进行调试。
所选地址数据必须在时钟上升沿(立即)出现,并且必须完全存储并准备好在不迟于同一时钟信号的下降沿重新读取。
也许我只是盯着我的描述太久了,但是我不明白为什么当我写一个地址时它会给UU重新分配每个值。肯定有一条我在这里打破的VHDL规则。我想要一个异步复位来清除整个数组,以及同步读/写。如果可取的话,我想最终完全消除时钟依赖性。
以下是相关的代码块:
-- Fully Descending Stack with integrated Stack Pointer --
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
ENTITY STACK IS
GENERIC(
BIT_WIDTH : INTEGER := 10;
BIT_DEPTH : INTEGER := 5
);
PORT(
CLK : IN STD_LOGIC;
CE : IN STD_LOGIC;
RESET : IN STD_LOGIC;
LOAD : IN STD_LOGIC;
PUSH : IN STD_LOGIC;
POINTER_WRITE_ADDRESS : IN STD_LOGIC_VECTOR(BIT_DEPTH - 1 DOWNTO 0);
STACK_DATA_IN : IN std_logic_vector(BIT_WIDTH - 1 DOWNTO 0);
-- OUTPUT SIGNALS --
POINTER_ADDRESS : OUT STD_LOGIC_VECTOR(BIT_DEPTH - 1 DOWNTO 0) := (OTHERS => '0');
STACK_DATA_OUT : OUT std_logic_vector(BIT_WIDTH - 1 DOWNTO 0) := (OTHERS => '0');
STACK_FULL : OUT STD_LOGIC := '0';
STACK_EMPTY : OUT STD_LOGIC := '1'
);
END STACK;
ARCHITECTURE Behavioral OF STACK IS
CONSTANT STACK_DEPTH : INTEGER := (2**BIT_DEPTH) - 1;
SUBTYPE WORD_SIZE IS std_logic_vector(BIT_WIDTH - 1 DOWNTO 0);
TYPE MEMORY IS ARRAY (STACK_DEPTH DOWNTO 0) OF WORD_SIZE;
SIGNAL STACK_MEMORY : MEMORY := (OTHERS => (OTHERS => '0'));
SIGNAL STACK_POINTER : INTEGER := STACK_DEPTH;
BEGIN
STACK_MEMORY <= (OTHERS => (OTHERS => '0')) WHEN RESET = '1' ELSE
(to_integer(unsigned(POINTER_WRITE_ADDRESS)) => STACK_DATA_IN) WHEN LOAD = '1' AND rising_edge(CLK) ELSE
( STACK_POINTER => STACK_DATA_IN) WHEN (PUSH = '1' AND CE = '1' AND NOT (STACK_POINTER = 0)) AND rising_edge(CLK);
STACK_POINTER <= (STACK_POINTER + 1) WHEN PUSH = '0' AND CE = '1'AND NOT(STACK_POINTER = STACK_DEPTH) AND rising_edge(CLK)ELSE
(STACK_POINTER - 1) WHEN PUSH='1' AND CE = '1' AND NOT (STACK_POINTER = 0) AND rising_edge(CLK);
STACK_EMPTY <= '1' WHEN STACK_POINTER = STACK_DEPTH else '0';
STACK_FULL <= '1' WHEN STACK_POINTER = 0 else '0';
STACK_DATA_OUT <= STACK_MEMORY(STACK_POINTER+1) WHEN CE = '1' AND PUSH='0' AND (NOT(STACK_POINTER = STACK_DEPTH)) ELSE
STACK_DATA_IN WHEN LOAD='1' or (CE = '1' AND PUSH='1' AND
NOT(STACK_POINTER = 0))ELSE
(OTHERS => '0') WHEN (STACK_POINTER = STACK_DEPTH);
POINTER_ADDRESS <= std_logic_vector(to_unsigned(STACK_POINTER,
POINTER_ADDRESS'length));
END Behavioral;
------------------------------ EDIT ---------------- ----------------
好的,我已经看了一些参考资料并重写了我的代码如下:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
ENTITY STACK IS
GENERIC(
-- DATA STORAGE GENERICS --
BIT_WIDTH : INTEGER := 10;
BIT_DEPTH : INTEGER := 8
);
PORT(
-- NON-SPECIFIC INPUT SIGNALS --
CLK : IN STD_LOGIC;
CE : IN STD_LOGIC;
RESET : IN STD_LOGIC;
-- STACK OPERATION INPUT SIGNALS --
LOAD : IN STD_LOGIC;
PUSH : IN STD_LOGIC;
POINTER_WRITE_ADDRESS : IN STD_LOGIC_VECTOR(BIT_DEPTH - 1 DOWNTO 0);
STACK_DATA_IN : IN std_logic_vector(BIT_WIDTH - 1 DOWNTO 0);
-- OUTPUT SIGNALS --
POINTER_ADDRESS : OUT STD_LOGIC_VECTOR(BIT_DEPTH - 1 DOWNTO 0) := (OTHERS => '0');
STACK_DATA_OUT : OUT std_logic_vector(BIT_WIDTH - 1 DOWNTO 0) := (OTHERS => '0');
STACK_FULL : OUT STD_LOGIC := '0';
STACK_EMPTY : OUT STD_LOGIC := '1'
);
END STACK;
ARCHITECTURE Behavioral OF STACK IS
CONSTANT STACK_TOP : INTEGER := (2**BIT_DEPTH) - 1;
SUBTYPE WORD_SIZE IS STD_LOGIC_VECTOR(BIT_WIDTH - 1 DOWNTO 0);
TYPE MEMORY IS ARRAY (STACK_TOP DOWNTO 0) OF WORD_SIZE;
SIGNAL STACK_MEMORY : MEMORY := (OTHERS => (OTHERS => '0'));
SIGNAL STACK_POINTER : INTEGER := STACK_TOP;
SIGNAL STACK_POINTER_INPUT : INTEGER := 0;
BEGIN
STACK_POINTER_INPUT <= to_integer(unsigned(POINTER_WRITE_ADDRESS));
POINTER_ADDRESS <= std_logic_vector(to_unsigned(STACK_POINTER, POINTER_ADDRESS'length));
STACK_POINTER_CONTROL : PROCESS(CLK)
BEGIN
IF (Rising_Edge(CLK)) THEN
IF (RESET = '1') THEN
STACK_POINTER <= STACK_TOP;
ELSIF (LOAD = '1') THEN
STACK_POINTER <= STACK_POINTER_INPUT;
ELSIF (CE = '1' AND PUSH = '0' AND STACK_POINTER < STACK_TOP) THEN
STACK_POINTER <= STACK_POINTER + 1;
ELSIF (CE = '1' AND PUSH = '1' AND STACK_POINTER > 0) THEN
STACK_POINTER <= STACK_POINTER - 1;
END IF;
END IF;
END PROCESS STACK_POINTER_CONTROL;
BLOCK_MEMORY_CONTROL : PROCESS(CLK)
BEGIN
IF (Rising_Edge(CLK)) THEN
IF (RESET = '1') THEN
STACK_MEMORY <= (OTHERS => (OTHERS => '0'));
-- POP | Erase data from popped address --
ELSIF (CE = '1' AND PUSH = '0') THEN
STACK_MEMORY(STACK_POINTER) <= (OTHERS => '0');
-- PUSH | Write data to stack pointer --
ELSIF (CE = '1' AND PUSH = '1') THEN
STACK_MEMORY(STACK_POINTER) <= STACK_DATA_IN;
END IF;
END IF;
END PROCESS BLOCK_MEMORY_CONTROL;
STACK_DATA_OUT <= (OTHERS => '0') WHEN RESET = '1'
ELSE STACK_DATA_IN WHEN STACK_POINTER = 255
ELSE STACK_MEMORY(STACK_POINTER + 1);
STACK_EMPTY <= '1' WHEN STACK_POINTER = STACK_TOP else '0';
STACK_FULL <= '1' WHEN STACK_POINTER = 0 else '0';
END Behavioral;
现在似乎在所有模拟测试中都能正常运行,但我担心状态之间的时序冲突。有没有更好的方法来改进这种设计?