如何在FPGA中正确存储寄存器
How to correctly storage registers in an FPGA
我需要用 VHDL 编写一个使用 i2c 初始化传感器寄存器的程序。我的问题是编写一个不浪费所有 FPGA space 的高效程序。我需要存储的寄存器个数是400个由8位地址和8位数据组成的寄存器。
我写的程序是:
entity i2cReg is
port (
RegSel : in std_logic;
Address : out std_logic_vector (15 downto 0);
Data : out std_logic_vector (7 downto 0);
RegStop : out std_logic;
ModuleEN : in std_logic
);
end i2cReg;
architecture i2cReg_archi of i2cReg is
signal counter :integer := 0;
begin
process(RegSel, ModuleEN)
begin
if ModuleEN = '0' then
Address <= x"10";
Data <= x"10";
RegStop <= '0';
counter <= 0;
elsif rising_edge(RegSel) then
counter <= counter + 1;
case counter is
when 0 =>
Address <= x"10";
Data <= x"10";
when 1 =>
Address <= x"10";
Data <= x"10";
when 2 =>
Address <= x"10";
Data <= x"10";
when 3 =>
Address <= x"10";
Data <= x"10";
when 4 =>
Address <= x"10";
Data <= x"10";
when 5 =>
Address <= x"10";
Data <= x"10";
when 400 =>
RegStop <= '1';
when others =>
end case;
end if;
end process;
end i2cReg_archi;
有办法优化这段代码吗?或者你建议我使用外部 eeprom?
Yaro - 您没有提到 FPGA 供应商或设备,但答案是:是的,您可以在 FPGA 中初始化 ROM,以便在配置后显示您需要的值。 Altera 和 Xilinx 都允许您在综合期间提供包含初始值的文件。
凯文
如果您使用的是 Xilinx 或 Altera,则初始化 BlockRAM 通常是正确的解决方案。
但也有逻辑实现也可以工作的例外情况:
例如,如果您的 400 个寄存器的内容具有重复模式或许多具有相同值的寄存器(如您的示例代码)。在这种情况下,如果您将其实现为逻辑,您的综合工具将对其进行大量优化。如果寄存器内容非常重复,您实际上可能会得到非常少量的逻辑。有时也可以通过巧妙地重新排序寄存器来改进优化。
100-200 个逻辑单元通常被认为 "cheaper" 而不是 BlockRAM。但这主要取决于您的特定应用程序中哪种资源最稀缺。
无论您是使用初始化的 BlockRAM 还是逻辑,我都建议您将其建模为 std_logic_vector 的数组,而不是使用 case/when。
"array of std_logic_vector" 方法与平台无关,可以综合为 BlockRAM 或逻辑。您的综合工具通常会尝试自动 select 最佳实现。但您也可以通过使用供应商特定属性强制综合工具使用逻辑或 BlockRAM。 (我不能告诉你使用哪些属性,因为我不知道你使用的是哪个平台)
示例:
type REG_TYPE is array (0 to 3) of std_logic_vector(15 downto 0);
constant REGISTERS : REG_TYPE :=
(x"0000",
x"0001",
x"0010",
x"0100");
在您的过程中,类似:
if rising_edge(RegSel) then
Address <= REGISTERS( counter )(15 downto 8);
Data <= REGISTERS( counter )( 7 downto 0);
end if;
我需要用 VHDL 编写一个使用 i2c 初始化传感器寄存器的程序。我的问题是编写一个不浪费所有 FPGA space 的高效程序。我需要存储的寄存器个数是400个由8位地址和8位数据组成的寄存器。
我写的程序是:
entity i2cReg is
port (
RegSel : in std_logic;
Address : out std_logic_vector (15 downto 0);
Data : out std_logic_vector (7 downto 0);
RegStop : out std_logic;
ModuleEN : in std_logic
);
end i2cReg;
architecture i2cReg_archi of i2cReg is
signal counter :integer := 0;
begin
process(RegSel, ModuleEN)
begin
if ModuleEN = '0' then
Address <= x"10";
Data <= x"10";
RegStop <= '0';
counter <= 0;
elsif rising_edge(RegSel) then
counter <= counter + 1;
case counter is
when 0 =>
Address <= x"10";
Data <= x"10";
when 1 =>
Address <= x"10";
Data <= x"10";
when 2 =>
Address <= x"10";
Data <= x"10";
when 3 =>
Address <= x"10";
Data <= x"10";
when 4 =>
Address <= x"10";
Data <= x"10";
when 5 =>
Address <= x"10";
Data <= x"10";
when 400 =>
RegStop <= '1';
when others =>
end case;
end if;
end process;
end i2cReg_archi;
有办法优化这段代码吗?或者你建议我使用外部 eeprom?
Yaro - 您没有提到 FPGA 供应商或设备,但答案是:是的,您可以在 FPGA 中初始化 ROM,以便在配置后显示您需要的值。 Altera 和 Xilinx 都允许您在综合期间提供包含初始值的文件。
凯文
如果您使用的是 Xilinx 或 Altera,则初始化 BlockRAM 通常是正确的解决方案。
但也有逻辑实现也可以工作的例外情况: 例如,如果您的 400 个寄存器的内容具有重复模式或许多具有相同值的寄存器(如您的示例代码)。在这种情况下,如果您将其实现为逻辑,您的综合工具将对其进行大量优化。如果寄存器内容非常重复,您实际上可能会得到非常少量的逻辑。有时也可以通过巧妙地重新排序寄存器来改进优化。
100-200 个逻辑单元通常被认为 "cheaper" 而不是 BlockRAM。但这主要取决于您的特定应用程序中哪种资源最稀缺。
无论您是使用初始化的 BlockRAM 还是逻辑,我都建议您将其建模为 std_logic_vector 的数组,而不是使用 case/when。 "array of std_logic_vector" 方法与平台无关,可以综合为 BlockRAM 或逻辑。您的综合工具通常会尝试自动 select 最佳实现。但您也可以通过使用供应商特定属性强制综合工具使用逻辑或 BlockRAM。 (我不能告诉你使用哪些属性,因为我不知道你使用的是哪个平台)
示例:
type REG_TYPE is array (0 to 3) of std_logic_vector(15 downto 0);
constant REGISTERS : REG_TYPE :=
(x"0000",
x"0001",
x"0010",
x"0100");
在您的过程中,类似:
if rising_edge(RegSel) then
Address <= REGISTERS( counter )(15 downto 8);
Data <= REGISTERS( counter )( 7 downto 0);
end if;