P
Paul Uiterlinden
Guest
andyesquire@hotmail.com wrote:
differences in simulation results (RTL versus synthesis).
latch <= std_logic_vector(signed(a_reg) - signed(b_reg));
COMB_B : process (x_reg,a_reg,b_reg,d_reg) is
begin
if d_reg = '1' then
...
Or make it completely local (my preference) by assigning the common
expression to a variable:
COMB_B : process (x_reg,a_reg,b_reg,d_reg) is
variable a_min_b : std_logic_vector(31 downto 0);
begin
a_min_b := (others => '0'); -- Avoid latch
if (d_reg = '1') then
a_min_b := std_logic_vector(signed(a_reg) - signed(b_reg));
if (signed(x_reg) > signed(a_min_b)) then
r <= x_reg;
else
r <= a_min_b;
end if;
else
r <= (others => '0');
end if;
end process;
A further (textual) optimization would be declaring r, a_reg, b_reg,
x_reg and a_min_b as signed, in stead of std_logic_vector. This would
avoid most of the conversions. The resulting code (untested):
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity test_latch is
port (clk : in std_logic;
rst : in std_logic;
d_in : in std_logic;
a_in : in std_logic_vector(31 downto 0);
b_in : in std_logic_vector(31 downto 0);
x_in : in std_logic_vector(31 downto 0);
r_out : out std_logic_vector(31 downto 0)
);
end test_latch;
architecture Behavioral of test_latch is
signal a_reg,b_reg,x_reg : signed(31 downto 0);
signal d_reg : std_logic;
signal r : signed(31 downto 0);
begin
SEQ1 : process (clk, rst) is
begin
if rst ='1' then
a_reg <= (others => '0');
b_reg <= (others => '0');
x_reg <= (others => '0');
d_reg <= '0';
elsif rising_edge(clk) then
if d_reg = '1' then
a_reg <= signed(a_in);
b_reg <= signed(b_in);
x_reg <= signed(x_in);
d_reg <= d_in;
end if;
end if;
end process;
COMB_B : process (x_reg, a_reg, b_reg, d_reg) is
variable a_min_b : signed(31 downto 0);
begin
a_min_b := (others => '0'); -- Avoid latch
if d_reg = '1' then
a_min_b := a_reg - b_reg;
if x_reg > a_min_b then
r <= x_reg;
else
r <= a_min_b;
end if;
else
r <= (others => '0');
end if;
end process;
SEQ2 : process (clk, rst) is
begin
if rst ='1' then
r_out <= (others => '0'); -- This was missing (intentional?)
elsif rising_edge(clk) then
r_out <= std_logic_vector(r);
end if;
end process;
end Behavioral;
--
Signal 'latch' is missing in the sensitivity list. This could causeA simplified example is shown below, COMB_B process contains the latch
and does some trivial calculation. Whereas COMB_A does the same
calculation, but without a latch, and a lot slower.
differences in simulation results (RTL versus synthesis).
Just make it a signal, assigned by a concurrent signal assignment:Or is there is a way to make XST avoid inferring two lots of (a_reg -
b_reg) logic in COMB_A? It's this logic that causes the 50Mhz hit and
why I used a latch COMB_B.
latch <= std_logic_vector(signed(a_reg) - signed(b_reg));
COMB_B : process (x_reg,a_reg,b_reg,d_reg) is
begin
if d_reg = '1' then
...
Or make it completely local (my preference) by assigning the common
expression to a variable:
COMB_B : process (x_reg,a_reg,b_reg,d_reg) is
variable a_min_b : std_logic_vector(31 downto 0);
begin
a_min_b := (others => '0'); -- Avoid latch
if (d_reg = '1') then
a_min_b := std_logic_vector(signed(a_reg) - signed(b_reg));
if (signed(x_reg) > signed(a_min_b)) then
r <= x_reg;
else
r <= a_min_b;
end if;
else
r <= (others => '0');
end if;
end process;
A further (textual) optimization would be declaring r, a_reg, b_reg,
x_reg and a_min_b as signed, in stead of std_logic_vector. This would
avoid most of the conversions. The resulting code (untested):
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity test_latch is
port (clk : in std_logic;
rst : in std_logic;
d_in : in std_logic;
a_in : in std_logic_vector(31 downto 0);
b_in : in std_logic_vector(31 downto 0);
x_in : in std_logic_vector(31 downto 0);
r_out : out std_logic_vector(31 downto 0)
);
end test_latch;
architecture Behavioral of test_latch is
signal a_reg,b_reg,x_reg : signed(31 downto 0);
signal d_reg : std_logic;
signal r : signed(31 downto 0);
begin
SEQ1 : process (clk, rst) is
begin
if rst ='1' then
a_reg <= (others => '0');
b_reg <= (others => '0');
x_reg <= (others => '0');
d_reg <= '0';
elsif rising_edge(clk) then
if d_reg = '1' then
a_reg <= signed(a_in);
b_reg <= signed(b_in);
x_reg <= signed(x_in);
d_reg <= d_in;
end if;
end if;
end process;
COMB_B : process (x_reg, a_reg, b_reg, d_reg) is
variable a_min_b : signed(31 downto 0);
begin
a_min_b := (others => '0'); -- Avoid latch
if d_reg = '1' then
a_min_b := a_reg - b_reg;
if x_reg > a_min_b then
r <= x_reg;
else
r <= a_min_b;
end if;
else
r <= (others => '0');
end if;
end process;
SEQ2 : process (clk, rst) is
begin
if rst ='1' then
r_out <= (others => '0'); -- This was missing (intentional?)
elsif rising_edge(clk) then
r_out <= std_logic_vector(r);
end if;
end process;
end Behavioral;
--