环顾四周,逻辑中“X”位最常见的来源似乎是由于信号的多个驱动器造成的。据我所知,我的代码中没有针对任何信号的多个驱动程序。我使用一个函数将两个 32 位浮点值相加并返回结果以设置下一个中间信号,据我所知,我可以做到这一点。当我运行模拟时,我看到输出在复位过程停止后的第一个时钟周期重置为“000000000..”,但在下一个前沿,我开始在输出上获取符号和尾数位的“X”位。我觉得这可能是我所缺少的 VHDL 基础知识,但我不确定它是什么。谢谢!
代码:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.std_logic_unsigned.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.MATH_REAL.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 leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity DM_module is
Port ( clk_in : in STD_LOGIC;
reset : in STD_LOGIC;
v0 : in STD_LOGIC_VECTOR (31 downto 0);
v1 : in STD_LOGIC_VECTOR (31 downto 0);
v2 : in STD_LOGIC_VECTOR (31 downto 0);
v3 : in STD_LOGIC_VECTOR (31 downto 0);
v4 : in STD_LOGIC_VECTOR (31 downto 0);
v5 : in STD_LOGIC_VECTOR (31 downto 0);
v6 : in STD_LOGIC_VECTOR (31 downto 0);
v7 : in STD_LOGIC_VECTOR (31 downto 0);
v8 : in STD_LOGIC_VECTOR (31 downto 0);
v9 : in STD_LOGIC_VECTOR (31 downto 0);
v10 : in STD_LOGIC_VECTOR (31 downto 0);
v11 : in STD_LOGIC_VECTOR (31 downto 0);
v12 : in STD_LOGIC_VECTOR (31 downto 0);
v13 : in STD_LOGIC_VECTOR (31 downto 0);
v14 : in STD_LOGIC_VECTOR (31 downto 0);
v15 : in STD_LOGIC_VECTOR (31 downto 0);
v16 : in STD_LOGIC_VECTOR (31 downto 0);
v17 : in STD_LOGIC_VECTOR (31 downto 0);
v18 : in STD_LOGIC_VECTOR (31 downto 0);
v19 : in STD_LOGIC_VECTOR (31 downto 0);
v20 : in STD_LOGIC_VECTOR (31 downto 0);
v21 : in STD_LOGIC_VECTOR (31 downto 0);
v22 : in STD_LOGIC_VECTOR (31 downto 0);
v23 : in STD_LOGIC_VECTOR (31 downto 0);
v24 : in STD_LOGIC_VECTOR (31 downto 0);
v25 : in STD_LOGIC_VECTOR (31 downto 0);
v26 : in STD_LOGIC_VECTOR (31 downto 0);
v27 : in STD_LOGIC_VECTOR (31 downto 0);
v28 : in STD_LOGIC_VECTOR (31 downto 0);
v29 : in STD_LOGIC_VECTOR (31 downto 0);
v30 : in STD_LOGIC_VECTOR (31 downto 0);
v31 : in STD_LOGIC_VECTOR (31 downto 0);
sum_out : out STD_LOGIC_VECTOR (31 downto 0));
end DM_module;
architecture Behavioral of DM_module is
--function to sum float values
function myFloatSum(A_in: std_logic_vector(31 downto 0);
B_in: std_logic_vector(31 downto 0)) return std_logic_vector is
variable sum : unsigned(31 downto 0) := (others => '0');
variable sign, signA, signB : std_logic;
variable expA, expB, intExp : integer;
variable eshift : natural;
variable manA, manB, manNew : signed(25 downto 0);
variable newExp : std_logic_vector(7 downto 0);
begin
--signs extracted
signA := A_in(31);
signB := B_in(31);
--exponents extracted
expA := conv_integer(A_in(30 downto 23)) - 127;
expB := conv_integer(B_in(30 downto 23)) - 127;
--mantissas extracted and placed in oversized vectors to allow for implied bit, over flow, and signs
manA(25) := '0';
manA(24) := '0';
manA(23) := '1';
manA := signed(A_in(22 downto 0));
ManB(25) := '0';
manB(24) := '0';
manB(23) := '1';
manB := signed(B_in(22 downto 0));
--tests for exponent cases, determines the shift required, and generates the intermediate exponent
if expA = expB then
eShift := 0;
intExp := expA;
elsif expA > expB then
eShift := expA - expB;
manB := signed(shift_right(unsigned(manB), eShift));
intExp := expA;
else
eShift := expB - expA;
manA := signed(shift_right(unsigned(manA), eShift));
intExp := expB;
end if;
--signs checked and mantissas converted to 2's complement as needed
if signA ='1' then
manA := -manA;
end if;
if signB ='1' then
manB := -manB;
end if;
-- sums the two values
manNew := manA + manB;
--processes the sum to determine whether or not the result is negative and if so, reverts to a positive format and enables the float output sign bit
sum(31) := manNew(25);
if manNew(25) = '1' then
manNew := -manNew;
end if;
--if the sum overflowed, a logical shift is performed and the exponent incremented
if manNew(24) = '1' then
manNew := signed(shift_right(unsigned(manNew), 1));
intExp := intExp + 1;
end if;
--the output is assembled
sum(22 downto 0) := unsigned(manNew(22 downto 0));
sum(30 downto 23) := to_unsigned(intExp, 8);
return(std_logic_vector(sum));
end myFloatSum;
--initial signals
signal v0sig, v1sig, v2sig, v3sig, v4sig, v5sig, v6sig, v7sig : std_logic_vector(31 downto 0) := "00000000000000000000000000000000";
signal v8sig, v9sig, v10sig, v11sig, v12sig, v13sig, v14sig, v15sig : std_logic_vector(31 downto 0) := "00000000000000000000000000000000";
signal v16sig, v17sig, v18sig, v19sig, v20sig, v21sig, v22sig, v23sig : std_logic_vector(31 downto 0) := "00000000000000000000000000000000";
signal v24sig, v25sig, v26sig, v27sig, v28sig, v29sig, v30sig, v31sig : std_logic_vector(31 downto 0) := "00000000000000000000000000000000";
--first stage sums
signal s1n0, s1n1, s1n2, s1n3, s1n4, s1n5, s1n6, s1n7 : std_logic_vector(31 downto 0) := "00000000000000000000000000000000";
signal s1n8, s1n9, s1n10, s1n11, s1n12, s1n13, s1n14, s1n15 : std_logic_vector(31 downto 0) := "00000000000000000000000000000000";
--second stage sums
signal s2n0, s2n1, s2n2, s2n3, s2n4, s2n5, s2n6, s2n7 : std_logic_vector(31 downto 0) := "00000000000000000000000000000000";
--third stage sums
signal s3n0, s3n1, s3n2, s3n3 : std_logic_vector(31 downto 0) := "00000000000000000000000000000000";
--fourth stage sums
signal s4n0, s4n1 : std_logic_vector(31 downto 0) := "00000000000000000000000000000000";
--final sum
signal final_sum : std_logic_vector(31 downto 0) := "00000000000000000000000000000000";
begin
--reset process
process(clk_in, reset)
begin
if reset = '1' then
-- Reset logic: set all registers and signals to their initial values.
-- For example, you can set all signals to '0'.
v0sig <= (others => '0');
v1sig <= (others => '0');
-- Initialize other signals and variables as needed.
elsif rising_edge(clk_in) then
--inputs assigned to signals
v0sig <= v0;
v1sig <= v1;
v2sig <= v2;
v3sig <= v3;
v4sig <= v4;
v5sig <= v5;
v6sig <= v6;
v7sig <= v7;
v8sig <= v8;
v9sig <= v9;
v10sig <= v10;
v11sig <= v11;
v12sig <= v12;
v13sig <= v13;
v14sig <= v14;
v15sig <= v15;
v16sig <= v16;
v17sig <= v17;
v18sig <= v18;
v19sig <= v19;
v20sig <= v20;
v21sig <= v21;
v22sig <= v22;
v23sig <= v23;
v24sig <= v24;
v25sig <= v25;
v26sig <= v26;
v27sig <= v27;
v28sig <= v28;
v29sig <= v29;
v30sig <= v30;
v31sig <= v31;
--first stage sums
s1n0 <= myFloatSum(A_in => v0sig, B_in => v1sig);
s1n1 <= myFloatSum(A_in => v2sig, B_in => v3sig);
s1n2 <= myFloatSum(A_in => v4sig, B_in => v5sig);
s1n3 <= myFloatSum(A_in => v6sig, B_in => v7sig);
s1n4 <= myFloatSum(A_in => v8sig, B_in => v9sig);
s1n5 <= myFloatSum(A_in => v10sig, B_in => v11sig);
s1n6 <= myFloatSum(A_in => v12sig, B_in => v13sig);
s1n7 <= myFloatSum(A_in => v14sig, B_in => v15sig);
s1n8 <= myFloatSum(A_in => v16sig, B_in => v17sig);
s1n9 <= myFloatSum(A_in => v18sig, B_in => v19sig);
s1n10 <= myFloatSum(A_in => v20sig, B_in => v21sig);
s1n11 <= myFloatSum(A_in => v22sig, B_in => v23sig);
s1n12 <= myFloatSum(A_in => v24sig, B_in => v25sig);
s1n13 <= myFloatSum(A_in => v26sig, B_in => v27sig);
s1n14 <= myFloatSum(A_in => v28sig, B_in => v29sig);
s1n15 <= myFloatSum(A_in => v30sig, B_in => v31sig);
--second stage sums
s2n0 <= myFloatSum(A_in => s1n0, B_in => s1n8);
s2n1 <= myFloatSum(A_in => s1n1, B_in => s1n9);
s2n2 <= myFloatSum(A_in => s1n2, B_in => s1n10);
s2n3 <= myFloatSum(A_in => s1n3, B_in => s1n11);
s2n4 <= myFloatSum(A_in => s1n4, B_in => s1n12);
s2n5 <= myFloatSum(A_in => s1n5, B_in => s1n13);
s2n6 <= myFloatSum(A_in => s1n6, B_in => s1n14);
s2n7 <= myFloatSum(A_in => s1n7, B_in => s1n15);
--third stage sums
s3n0 <= myFloatSum(A_in => s2n0, B_in => s2n4);
s3n1 <= myFloatSum(A_in => s2n1, B_in => s2n5);
s3n2 <= myFloatSum(A_in => s2n2, B_in => s2n6);
s3n3 <= myFloatSum(A_in => s2n3, B_in => s2n7);
--fourth stage sums
s4n0 <= myFloatSum(A_in => s3n0, B_in => s3n2);
s4n1 <= myFloatSum(A_in => s3n1, B_in => s3n3);
--final sum
final_sum <= myFloatSum(A_in => s4n0, B_in => s4n1);
sum_out <= final_sum;
end if;
end process;
end Behavioral;
测试台:
-- Libraries
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
-- Entity declaration for the Test Bench
entity DM_TB is
end DM_TB;
-- Architecture for the Test Bench
architecture TB_ARCH of DM_TB is
-- Constants
constant CLOCK_PERIOD : time := 10 ns; -- Define your clock period here
constant HALF_PERIOD : time := 5 ns;
constant TEST_CASE_DELAY : time := 100 ns; -- Delay between test cases
-- Signals
signal clk, TBclk_en : std_logic := '0';
signal v0i, v1i, v2i, v3i, v4i, v5i, v6i, v7i : STD_LOGIC_VECTOR (31 downto 0);
signal v8i, v9i, v10i, v11i, v12i, v13i, v14i, v15i : STD_LOGIC_VECTOR (31 downto 0);
signal v16i, v17i, v18i, v19i, v20i, v21i, v22i, v23i : STD_LOGIC_VECTOR (31 downto 0);
signal v24i, v25i, v26i, v27i, v28i, v29i, v30i, v31i : STD_LOGIC_VECTOR (31 downto 0);
signal TBoutput : std_logic_vector(31 downto 0) := (others => '0');
begin
-- Instantiate the Unit Under Test (UUT)
uut: entity work.DM_module
port map (
clk_in => clk,
v0 => v0i,
v1 => v1i,
v2 => v2i,
v3 => v3i,
v4 => v4i,
v5 => v5i,
v6 => v6i,
v7 => v7i,
v8 => v8i,
v9 => v9i,
v10 => v10i,
v11 => v11i,
v12 => v12i,
v13 => v13i,
v14 => v14i,
v15 => v15i,
v16 => v16i,
v17 => v17i,
v18 => v18i,
v19 => v19i,
v20 => v20i,
v21 => v21i,
v22 => v22i,
v23 => v23i,
v24 => v24i,
v25 => v25i,
v26 => v26i,
v27 => v27i,
v28 => v28i,
v29 => v29i,
v30 => v30i,
v31 => v31i,
reset => TBclk_en,
sum_out => TBoutput
-- Map your design's ports here
);
-- Clock generation process
clk_process: process
begin
while now < 2000 ns loop -- Adjust simulation time as needed
clk <= '0';
wait for HALF_PERIOD;
clk <= '1';
wait for HALF_PERIOD;
end loop;
wait;
end process clk_process;
-- Reset process
reset_process: process
begin
TBclk_en <= '1';
wait for 500 ns; -- Reset duration
TBclk_en <= '0';
wait;
end process reset_process;
--declare
--variable expected_result : std_logic_vector (31 downto 0) := "01000000111111011111010101101001";
-- Test cases
test_process: process
begin
--input values applied to inputs
v0i <= "00111110100100111101011100001010";
v1i <= "00111001101000101000011101111111";
v2i <= "10111011101000111101011100001010";
v3i <= "00111111010111000100100110111010";
v4i <= "00111111100111000011110010011111";
v5i <= "10111110111001101000000010011101";
v6i <= "10110111111010110010000111110111";
v7i <= "00111111100000000000000000000000";
v8i <= "00111111000111101011101001001001";
v9i <= "10111011001001101110101110010010";
v10i <= "00111110100000000000000000000000";
v11i <= "10111110101100110011001100110011";
v12i <= "00111111001010110000100010011010";
v13i <= "10111100111110000110110000100010";
v14i <= "00111011000100111011011111011000";
v15i <= "00111110010011001100110011001101";
v16i <= "10111011100001001011010111011101";
v17i <= "00111111111011100001010001111010";
v18i <= "10110111001001111100010110101100";
v19i <= "00111110101001100010010011011101";
v20i <= "00111111100111100000010000011001";
v21i <= "10110110100101101111111010110101";
v22i <= "00111011101010100110010011000011";
v23i <= "00111111001110000111001010110000";
v24i <= "00111111101010101110000101001000";
v25i <= "10111111010000000011010001101110";
v26i <= "00111100111110011101101100100011";
v27i <= "00111110011000101101000011100101";
v28i <= "00111101111000111011110011010011";
v29i <= "00111101110011011111001001100111";
v30i <= "10111000011000100111111000001111";
v31i <= "00111100110111000100100001101011";
-- Wait for a moment before checking the result
wait for TEST_CASE_DELAY;
-- End simulation
wait;
end process test_process;
模拟输出:
我尝试了各种初始化信号的方法,尝试重写求和函数,仔细检查潜在的多个驱动程序情况..
我终于找到了另一个 FPGA 大脑可以交谈,我遇到问题的原因有几个。第一个主要问题——当我编写函数时,我的思维框架是基于我在 C 中的经验,并且不能像在 C 中那样对待变量。特别是当涉及到整数和自然值时,我不知道设置后您无法执行数学或更改它们的值。
第二——我选择使用函数,因为它似乎是简化代码的一种方法,但使用函数来执行我尝试执行的任务的问题是,它会产生很多松弛,因为它不是一个时钟进程或以某种方式同步到系统的其余部分。