0

这是一个通用的 FPGA 设计问题,我是 FPGA 设计的新手,刚刚开始了我的第一个大型项目,构建了一些不错的线性代数求解器。这些系统非常大,因此第一次正确处理很重要。

在成功的模拟之后,我现在正在合成,但我有一个噩梦,我必须逐个组件地构建和测试它,因为在模拟中没有任何表现!我主要遇到输出未同步的状态机问题,例如这是我正在使用的数据加载器:

entity TriDiag_Data_Scheduler is
    generic( W : integer :=16;  
                AW : integer := 10 -- address width
                );
    Port ( clk : in  STD_LOGIC;
           rst : in  STD_LOGIC; --attatched to data finished
           d_ready : in  STD_LOGIC;
           din : in  STD_LOGIC_VECTOR (W-1 downto 0);
              wr_en : out STD_LOGIC_VECTOR (3 downto 0);
              dout_a, dout_b, dout_c, dout_y : out  STD_LOGIC_VECTOR (W-1 downto 0);
              addr_out : out STD_LOGIC_VECTOR (AW-1 downto 0));
end TriDiag_Data_Scheduler;

architecture Behavioral of TriDiag_Data_Scheduler is

type state is (a,b,c,y);
signal state_pr, state_next : state := y;
signal addr_reg, addr_next : std_logic_vector(AW-1 downto 0) :=(others =>'1');

signal wr_en_next : std_logic_vector(3 downto 0);

--data buffer
signal d_buff, d_buff_a, d_buff_b, d_buff_c, d_buff_y : std_logic_vector (W-1 downto 0) :=(others =>'0');
signal d_buff_a_reg, d_buff_b_reg, d_buff_c_reg, d_buff_y_reg : std_logic_vector (W-1 downto 0) :=(others =>'0');

begin

process(clk,rst)
begin
    if(clk'event and clk ='1') then
        state_pr <= state_next;
        d_buff_a <= d_buff_a_reg;
        d_buff_b <= d_buff_b_reg;
        d_buff_c <= d_buff_c_reg;
        d_buff_y <= d_buff_y_reg;

        addr_reg <= addr_next;
        wr_en <= wr_en_next;
    end if;

end process;

addr_out <= addr_reg;
dout_a <= d_buff_a;
dout_b <= d_buff_b;
dout_c <= d_buff_c;
dout_y <= d_buff_y;


--Data out logic
process(state_pr, d_buff_a, d_buff_b, d_buff_c, d_buff_y, d_buff)
begin

    d_buff_a_reg <= d_buff_a;
    d_buff_b_reg <= d_buff_b;
    d_buff_c_reg <= d_buff_c;
    d_buff_y_reg <= d_buff_y;

    case state_pr is
        when a => --move data to a reg
            d_buff_a_reg <= d_buff;
        when b => --move data to b reg
            d_buff_b_reg <= d_buff;
        when c => --move data to c reg
            d_buff_c_reg <= d_buff;
        when y => 
            d_buff_y_reg <= d_buff;
    end case; 
end process;

--next state and addr logic
process(state_pr, d_ready, rst, din)
begin

    state_next <= state_pr;
    addr_next <= addr_reg;
    wr_en_next <= (others => '0');

if(rst = '1') then
    state_next <= a;
    addr_next <= (others =>'1');
    wr_en_next <= (others => '0');
elsif(d_ready = '1') then
--Read in the data to the buffer
    d_buff <= din;
--next state logic
    case state_pr is
        when a => --move data to a reg
            addr_next <= addr_reg + 1;
        --  d_buff_a_reg <= din;
            wr_en_next <= "0001";
            state_next <= b;
        when b => --move data to b reg
            wr_en_next <= "0010";
        --  d_buff_b_reg <= din;
            state_next <= c;
        when c => --move data to c reg
            wr_en_next <= "0100";
        --  d_buff_c_reg <= din;
            state_next <= y;
        when y => 
        --  d_buff_y_reg <= din;
            wr_en_next <= "1000";
            state_next <= a;
    end case; 
end if;
end process;
end Behavioral;

基本上,当通过 UART 模块接收数据时,它的工作是加载到正确的内存中(由 write_en 信号控制)。问题是在我所有的设计(这是修订版 7)中,所有 addr_out、wr_en 和正确的数据都是同步的,但在综合中我一直发现 addr 和 wr_en 与数据不同步,并且从前面读取了一半和前一个状态的一半。

我应该使用什么样的设计实践才能使我的 VHDL 更加易于综合,因为按照这种速度,我将不得不为每个组件重新编写我之前的所有辛勤工作!

非常感谢山姆

4

1 回答 1

0

工作设计,旧设计在另一个模块断言的 d_ready 信号和这个模块 clk 之间存在偏差。因此,未按最初希望同步的更改。为了解决这个问题,我在 d_tick_next 信号中断言了一个本地同步信号 d_tick,它允许所有正确的行为。吸取的一个教训(如果我错了,请纠正我)是您不能依赖假定的外部时钟信号(例如 d_ready)与接收模块 clk 同步。

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

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


-- ////////////////////////////////////////////////////////////////////
--Takes in the linear stream of data and builds up the memory structure

--INPUT DATA MUST FOLLOW SEQUENCE [a b c] x = [y] (0 if a or c do not exist) rows 0 and N respectivly 
--//////////////////////////////////////////////////////////////////////
entity TriDiag_Data_Scheduler is
    generic( W : integer :=16;  
                AW : integer := 10 -- address width
                );
    Port ( clk : in  STD_LOGIC;
           rst : in  STD_LOGIC; --attatched to data finished
           d_ready : in  STD_LOGIC;
           din : in  STD_LOGIC_VECTOR (W-1 downto 0);
              wr_en : out STD_LOGIC_VECTOR (3 downto 0);
              dout_a, dout_b, dout_c, dout_y : out  STD_LOGIC_VECTOR (W-1 downto 0);
              addr_out : out STD_LOGIC_VECTOR (AW-1 downto 0));
end TriDiag_Data_Scheduler;

architecture Behavioral of TriDiag_Data_Scheduler is

type state is (a,b,c,y);
signal state_pr, state_next : state := y;
signal addr_reg, addr_next : std_logic_vector(AW-1 downto 0) :=(others =>'1');

signal wr_en_next : std_logic_vector(3 downto 0);

signal d_tick, d_tick_next : std_logic;

--data buffer
signal d_buff, d_buff_a, d_buff_b, d_buff_c, d_buff_y : std_logic_vector (W-1 downto 0) :=(others =>'0');
signal d_buff_a_reg, d_buff_b_reg, d_buff_c_reg, d_buff_y_reg : std_logic_vector (W-1 downto 0) :=(others =>'0');

begin

process(clk,rst)
begin
    if(clk'event and clk ='1') then
        state_pr <= state_next;

        d_buff_a <= d_buff_a_reg;
        d_buff_b <= d_buff_b_reg;
        d_buff_c <= d_buff_c_reg;
        d_buff_y <= d_buff_y_reg;

        d_tick <= d_tick_next;

        addr_reg <= addr_next;
        wr_en <= wr_en_next;
    end if;

end process;

addr_out <= addr_reg;
dout_a <= d_buff_a;
dout_b <= d_buff_b;
dout_c <= d_buff_c;
dout_y <= d_buff_y;


--Data out logic
process(state_pr,d_tick,rst)
begin

    d_buff_a_reg <= d_buff_a;
    d_buff_b_reg <= d_buff_b;
    d_buff_c_reg <= d_buff_c;
    d_buff_y_reg <= d_buff_y;

    wr_en_next <= (others => '0');

if(rst = '1') then
    addr_next <= (others =>'1');
else
    addr_next <= addr_reg;
end if;

if(d_tick = '1') then
    case state_pr is
        when a => --move data to a reg
            d_buff_a_reg <= d_buff;
            addr_next <= addr_reg + 1;
            wr_en_next <= "0001";
        when b => --move data to b reg
            d_buff_b_reg <= d_buff;
            wr_en_next <= "0010";
        when c => --move data to c reg
            d_buff_c_reg <= d_buff;
            wr_en_next <= "0100";
        when y => 
            d_buff_y_reg <= d_buff;
            wr_en_next <= "1000";
    end case; 
end if;
end process;

--next state and d_tick
process(state_pr, d_ready, rst, din)
begin

    state_next <= state_pr;
    d_tick_next <='0';

if(rst = '1') then
    state_next <= y;
elsif(d_ready = '1') then
--Read in the data to the buffer
    d_buff <= din;
-- set sync tick
    d_tick_next <= '1';
--next state logic
    case state_pr is
        when a => 
            state_next <= b;
        when b => 
            state_next <= c;
        when c =>
            state_next <= y;
        when y => 
            state_next <= a;
    end case; 
end if;
end process;

结束行为;

于 2013-07-25T10:09:05.633 回答