У меня есть домашнее задание, в котором я использую предложенный ieee пакет с плавающей запятой. Я использую BRAM для перетасовки данных из PS в PL (c код для моего VHDL).
Я почти уверен, что мои номера правильно поступают в код VHDL, у меня есть 4 входа и 2 выхода, я по очереди назначил каждый вход на выход и увидел ожидаемое значение. Однако всякий раз, когда я выполняю математические операции с ними, я получаю неправильный ответ. Я никогда раньше не использовал пакет ieee, и, может быть, мне не хватает чего-то очевидного?
u1, u2, x и y назначаются через машину состояний из dataInB.
с u1 = 1, u2 = 2, x = 3, y = 4 вместо получения t1 = 1 (X "3F800000") и t2 = 1 (X "3F800000"), я вижу t1 = 0 (X "00000000") и t2 = -0,5 (X "BF000000").
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library ieee_proposed;
use ieee_proposed.fixed_float_types.all;
use ieee_proposed.float_pkg.all;
use ieee_proposed.fixed_pkg.all;
-- port inputs:
port(
signal dataInB : in std_logic_vector(31 downto 0);
signal dataOutB : out std_logic_vector(31 downto 0);
);
arch a of a_1 is
-- skipped some code, variable definitions:
signal fDataIn : float32;
signal u1 : float32 := X"00000000"; -- in
signal u2 : float32 := X"00000000"; -- in
signal x : float32 := X"00000000"; -- in
signal y : float32 := X"00000000"; -- in
signal t1 : float32 := X"00000000"; -- out
signal t2 : float32 := X"00000000"; -- out
begin
fDataIn <= to_float(dataInB); -- combinational
-- in state machine:
case read_u1:
u1 <= fDataIn; -- addr was changed in previous state to new address
case read_u2:
u2 <= fDataIn; -- addr was changed in previous state to new address
-- etc. for x and y
-- skip some code
-- calculations - combinational
t1 <= u2 - u1;
t2 <= y - x;
-- some time later in state machine:
case write_T1:
dataOutB <= std_logic_vector(t1);
case write_T2:
dataOutB <= std_logic_vector(t2);
end a_1;
Как упоминалось ранее, если я изменю t1 <= x и t2 <= u2, я увижу ожидаемые значения вернемся к моему C коду, так что я думаю, что часть BRAM работает должным образом, только не расчет. </p>
Заранее спасибо.
Я использую плату Digilent ZyboZ7010 с Xilinx Vivado 2019.1 и связанный SDK. Это внутри пользовательского IP.
Редактировать: Полный код ниже:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library ieee_proposed;
use ieee_proposed.fixed_float_types.all;
use ieee_proposed.float_pkg.all;
use ieee_proposed.fixed_pkg.all;
entity myip_v1_0_S00_AXI is
generic (
-- Users to add parameters here
-- User parameters ends
-- Do not modify the parameters beyond this line
-- Width of S_AXI data bus
C_S_AXI_DATA_WIDTH : integer := 32;
-- Width of S_AXI address bus
C_S_AXI_ADDR_WIDTH : integer := 4
);
port (
-- Users to add ports here
signal addrB : out std_logic_vector(31 downto 0) := X"00000000";
signal dataInB : in std_logic_vector(31 downto 0);
signal dataOutB : out std_logic_vector(31 downto 0);
signal enB : out std_logic := '1';
signal writeB : out std_logic_vector(3 downto 0) := X"0";
signal rstB : out std_logic := '0';
-- User ports ends
-- Do not modify the ports beyond this line
-- Global Clock Signal
S_AXI_ACLK : in std_logic;
-- Global Reset Signal. This Signal is Active LOW
S_AXI_ARESETN : in std_logic;
-- Write address (issued by master, acceped by Slave)
S_AXI_AWADDR : in std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
-- Write channel Protection type. This signal indicates the
-- privilege and security level of the transaction, and whether
-- the transaction is a data access or an instruction access.
S_AXI_AWPROT : in std_logic_vector(2 downto 0);
-- Write address valid. This signal indicates that the master signaling
-- valid write address and control information.
S_AXI_AWVALID : in std_logic;
-- Write address ready. This signal indicates that the slave is ready
-- to accept an address and associated control signals.
S_AXI_AWREADY : out std_logic;
-- Write data (issued by master, acceped by Slave)
S_AXI_WDATA : in std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
-- Write strobes. This signal indicates which byte lanes hold
-- valid data. There is one write strobe bit for each eight
-- bits of the write data bus.
S_AXI_WSTRB : in std_logic_vector((C_S_AXI_DATA_WIDTH/8)-1 downto 0);
-- Write valid. This signal indicates that valid write
-- data and strobes are available.
S_AXI_WVALID : in std_logic;
-- Write ready. This signal indicates that the slave
-- can accept the write data.
S_AXI_WREADY : out std_logic;
-- Write response. This signal indicates the status
-- of the write transaction.
S_AXI_BRESP : out std_logic_vector(1 downto 0);
-- Write response valid. This signal indicates that the channel
-- is signaling a valid write response.
S_AXI_BVALID : out std_logic;
-- Response ready. This signal indicates that the master
-- can accept a write response.
S_AXI_BREADY : in std_logic;
-- Read address (issued by master, acceped by Slave)
S_AXI_ARADDR : in std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
-- Protection type. This signal indicates the privilege
-- and security level of the transaction, and whether the
-- transaction is a data access or an instruction access.
S_AXI_ARPROT : in std_logic_vector(2 downto 0);
-- Read address valid. This signal indicates that the channel
-- is signaling valid read address and control information.
S_AXI_ARVALID : in std_logic;
-- Read address ready. This signal indicates that the slave is
-- ready to accept an address and associated control signals.
S_AXI_ARREADY : out std_logic;
-- Read data (issued by slave)
S_AXI_RDATA : out std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
-- Read response. This signal indicates the status of the
-- read transfer.
S_AXI_RRESP : out std_logic_vector(1 downto 0);
-- Read valid. This signal indicates that the channel is
-- signaling the required read data.
S_AXI_RVALID : out std_logic;
-- Read ready. This signal indicates that the master can
-- accept the read data and response information.
S_AXI_RREADY : in std_logic
);
end myip_v1_0_S00_AXI;
architecture arch_imp of myip_v1_0_S00_AXI is
-- AXI4LITE signals
signal axi_awaddr : std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
signal axi_awready : std_logic;
signal axi_wready : std_logic;
signal axi_bresp : std_logic_vector(1 downto 0);
signal axi_bvalid : std_logic;
signal axi_araddr : std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
signal axi_arready : std_logic;
signal axi_rdata : std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
signal axi_rresp : std_logic_vector(1 downto 0);
signal axi_rvalid : std_logic;
-- Example-specific design signals
-- local parameter for addressing 32 bit / 64 bit C_S_AXI_DATA_WIDTH
-- ADDR_LSB is used for addressing 32/64 bit registers/memories
-- ADDR_LSB = 2 for 32 bits (n downto 2)
-- ADDR_LSB = 3 for 64 bits (n downto 3)
constant ADDR_LSB : integer := (C_S_AXI_DATA_WIDTH/32)+ 1;
constant OPT_MEM_ADDR_BITS : integer := 1;
------------------------------------------------
---- Signals for user logic register space example
--------------------------------------------------
---- Number of Slave Registers 4
signal slv_reg0 :std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
signal slv_reg1 :std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
signal slv_reg2 :std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
signal slv_reg3 :std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
signal slv_reg_rden : std_logic;
signal slv_reg_wren : std_logic;
signal reg_data_out :std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
signal byte_index : integer;
signal aw_en : std_logic;
-- NE added
signal start : std_logic := '0';
signal done : std_logic := '0';
signal lAddr : std_logic_vector(31 downto 0) := X"00000000";
type state_type is (s_setU1Addr, s_setU2Addr, s_setX_Addr, s_setY_Addr, s_readU1Addr, s_done, s_readU2Addr, s_readX_Addr, s_readY_Addr, s_calc, s_setT1Addr, s_setT2Addr, s_writeT1, s_writeT2, s_loop, s_wait, s_inc);
signal present_state, next_state: state_type;
signal fDataIn : float32;
signal u1 : float32 := X"00000000";
signal u2 : float32 := X"00000000";
signal x : float32 := X"00000000";
signal y : float32 := X"00000000";
signal t1 : float32 := X"00000000";
signal t2 : float32 := X"00000000";
begin
-- I/O Connections assignments
S_AXI_AWREADY <= axi_awready;
S_AXI_WREADY <= axi_wready;
S_AXI_BRESP <= axi_bresp;
S_AXI_BVALID <= axi_bvalid;
S_AXI_ARREADY <= axi_arready;
S_AXI_RDATA <= axi_rdata;
S_AXI_RRESP <= axi_rresp;
S_AXI_RVALID <= axi_rvalid;
-- Implement axi_awready generation
-- axi_awready is asserted for one S_AXI_ACLK clock cycle when both
-- S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_awready is
-- de-asserted when reset is low.
process (S_AXI_ACLK)
begin
if rising_edge(S_AXI_ACLK) then
if S_AXI_ARESETN = '0' then
axi_awready <= '0';
aw_en <= '1';
else
if (axi_awready = '0' and S_AXI_AWVALID = '1' and S_AXI_WVALID = '1' and aw_en = '1') then
-- slave is ready to accept write address when
-- there is a valid write address and write data
-- on the write address and data bus. This design
-- expects no outstanding transactions.
axi_awready <= '1';
aw_en <= '0';
elsif (S_AXI_BREADY = '1' and axi_bvalid = '1') then
aw_en <= '1';
axi_awready <= '0';
else
axi_awready <= '0';
end if;
end if;
end if;
end process;
-- Implement axi_awaddr latching
-- This process is used to latch the address when both
-- S_AXI_AWVALID and S_AXI_WVALID are valid.
process (S_AXI_ACLK)
begin
if rising_edge(S_AXI_ACLK) then
if S_AXI_ARESETN = '0' then
axi_awaddr <= (others => '0');
else
if (axi_awready = '0' and S_AXI_AWVALID = '1' and S_AXI_WVALID = '1' and aw_en = '1') then
-- Write Address latching
axi_awaddr <= S_AXI_AWADDR;
end if;
end if;
end if;
end process;
-- Implement axi_wready generation
-- axi_wready is asserted for one S_AXI_ACLK clock cycle when both
-- S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_wready is
-- de-asserted when reset is low.
process (S_AXI_ACLK)
begin
if rising_edge(S_AXI_ACLK) then
if S_AXI_ARESETN = '0' then
axi_wready <= '0';
else
if (axi_wready = '0' and S_AXI_WVALID = '1' and S_AXI_AWVALID = '1' and aw_en = '1') then
-- slave is ready to accept write data when
-- there is a valid write address and write data
-- on the write address and data bus. This design
-- expects no outstanding transactions.
axi_wready <= '1';
else
axi_wready <= '0';
end if;
end if;
end if;
end process;
-- Implement memory mapped register select and write logic generation
-- The write data is accepted and written to memory mapped registers when
-- axi_awready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted. Write strobes are used to
-- select byte enables of slave registers while writing.
-- These registers are cleared when reset (active low) is applied.
-- Slave register write enable is asserted when valid address and data are available
-- and the slave is ready to accept the write address and write data.
slv_reg_wren <= axi_wready and S_AXI_WVALID and axi_awready and S_AXI_AWVALID ;
process (S_AXI_ACLK)
variable loc_addr :std_logic_vector(OPT_MEM_ADDR_BITS downto 0);
begin
if rising_edge(S_AXI_ACLK) then
if S_AXI_ARESETN = '0' then
slv_reg0 <= (others => '0');
slv_reg1 <= (others => '0');
slv_reg2 <= (others => '0');
slv_reg3 <= (others => '0');
else
loc_addr := axi_awaddr(ADDR_LSB + OPT_MEM_ADDR_BITS downto ADDR_LSB);
if (slv_reg_wren = '1') then
case loc_addr is
when b"00" =>
for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop
if ( S_AXI_WSTRB(byte_index) = '1' ) then
-- Respective byte enables are asserted as per write strobes
-- slave registor 0
slv_reg0(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8);
end if;
end loop;
when b"01" =>
for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop
if ( S_AXI_WSTRB(byte_index) = '1' ) then
-- Respective byte enables are asserted as per write strobes
-- slave registor 1
slv_reg1(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8);
end if;
end loop;
when b"10" =>
for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop
if ( S_AXI_WSTRB(byte_index) = '1' ) then
-- Respective byte enables are asserted as per write strobes
-- slave registor 2
slv_reg2(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8);
end if;
end loop;
when b"11" =>
for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop
if ( S_AXI_WSTRB(byte_index) = '1' ) then
-- Respective byte enables are asserted as per write strobes
-- slave registor 3
slv_reg3(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8);
end if;
end loop;
when others =>
slv_reg0 <= slv_reg0;
slv_reg1 <= slv_reg1;
slv_reg2 <= slv_reg2;
slv_reg3 <= slv_reg3;
end case;
end if;
end if;
end if;
end process;
-- Implement write response logic generation
-- The write response and response valid signals are asserted by the slave
-- when axi_wready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted.
-- This marks the acceptance of address and indicates the status of
-- write transaction.
process (S_AXI_ACLK)
begin
if rising_edge(S_AXI_ACLK) then
if S_AXI_ARESETN = '0' then
axi_bvalid <= '0';
axi_bresp <= "00"; --need to work more on the responses
else
if (axi_awready = '1' and S_AXI_AWVALID = '1' and axi_wready = '1' and S_AXI_WVALID = '1' and axi_bvalid = '0' ) then
axi_bvalid <= '1';
axi_bresp <= "00";
elsif (S_AXI_BREADY = '1' and axi_bvalid = '1') then --check if bready is asserted while bvalid is high)
axi_bvalid <= '0'; -- (there is a possibility that bready is always asserted high)
end if;
end if;
end if;
end process;
-- Implement axi_arready generation
-- axi_arready is asserted for one S_AXI_ACLK clock cycle when
-- S_AXI_ARVALID is asserted. axi_awready is
-- de-asserted when reset (active low) is asserted.
-- The read address is also latched when S_AXI_ARVALID is
-- asserted. axi_araddr is reset to zero on reset assertion.
process (S_AXI_ACLK)
begin
if rising_edge(S_AXI_ACLK) then
if S_AXI_ARESETN = '0' then
axi_arready <= '0';
axi_araddr <= (others => '1');
else
if (axi_arready = '0' and S_AXI_ARVALID = '1') then
-- indicates that the slave has acceped the valid read address
axi_arready <= '1';
-- Read Address latching
axi_araddr <= S_AXI_ARADDR;
else
axi_arready <= '0';
end if;
end if;
end if;
end process;
-- Implement axi_arvalid generation
-- axi_rvalid is asserted for one S_AXI_ACLK clock cycle when both
-- S_AXI_ARVALID and axi_arready are asserted. The slave registers
-- data are available on the axi_rdata bus at this instance. The
-- assertion of axi_rvalid marks the validity of read data on the
-- bus and axi_rresp indicates the status of read transaction.axi_rvalid
-- is deasserted on reset (active low). axi_rresp and axi_rdata are
-- cleared to zero on reset (active low).
process (S_AXI_ACLK)
begin
if rising_edge(S_AXI_ACLK) then
if S_AXI_ARESETN = '0' then
axi_rvalid <= '0';
axi_rresp <= "00";
else
if (axi_arready = '1' and S_AXI_ARVALID = '1' and axi_rvalid = '0') then
-- Valid read data is available at the read data bus
axi_rvalid <= '1';
axi_rresp <= "00"; -- 'OKAY' response
elsif (axi_rvalid = '1' and S_AXI_RREADY = '1') then
-- Read data is accepted by the master
axi_rvalid <= '0';
end if;
end if;
end if;
end process;
-- Implement memory mapped register select and read logic generation
-- Slave register read enable is asserted when valid address is available
-- and the slave is ready to accept the read address.
slv_reg_rden <= axi_arready and S_AXI_ARVALID and (not axi_rvalid) ;
process (slv_reg0, slv_reg1, slv_reg2, slv_reg3, axi_araddr, S_AXI_ARESETN, slv_reg_rden)
variable loc_addr :std_logic_vector(OPT_MEM_ADDR_BITS downto 0);
begin
-- Address decoding for reading registers
loc_addr := axi_araddr(ADDR_LSB + OPT_MEM_ADDR_BITS downto ADDR_LSB);
case loc_addr is
when b"00" =>
reg_data_out <= slv_reg0;
when b"01" =>
reg_data_out <= "0000000000000000000000000000000" & done;
when b"10" =>
reg_data_out <= lAddr;
when b"11" =>
reg_data_out <= dataInB;
when others =>
reg_data_out <= (others => '0');
end case;
end process;
-- Output register or memory read data
process( S_AXI_ACLK ) is
begin
if (rising_edge (S_AXI_ACLK)) then
if ( S_AXI_ARESETN = '0' ) then
axi_rdata <= (others => '0');
else
if (slv_reg_rden = '1') then
-- When there is a valid read address (S_AXI_ARVALID) with
-- acceptance of read address by the slave (axi_arready),
-- output the read dada
-- Read address mux
axi_rdata <= reg_data_out; -- register read data
end if;
end if;
end if;
end process;
-- Add user logic here
start <= slv_reg0(0);
fDataIn <= to_float(dataInB);
addrB <= lAddr;
t1 <= u2 - u1;--(u1 * x) - (u2 * y);
t2 <= y - x;--(u1 * y) + (u2 * x);
statemach: process(present_state, start)
begin
case present_state is
when s_wait =>
writeB <= X"0";
done <= '0';
dataOutB <= X"00000000";
if (start = '1') then
next_state <= s_setU1Addr;
else
next_state <= s_wait;
end if;
when s_setU1Addr =>
lAddr <= X"00000000";
writeB <= X"0";
dataOutB <= X"00000000";
done <= '0';
next_state <= s_readU1Addr;
when s_readU1Addr =>
lAddr <= X"00000000";
writeB <= X"0";
dataOutB <= X"00000000";
done <= '0';
u1 <= fDataIn;
next_state <= s_setU2Addr;
when s_setU2Addr =>
lAddr <= X"00000004";
writeB <= X"0";
dataOutB <= X"00000000";
done <= '0';
next_state <= s_readU2Addr;
when s_readU2Addr =>
lAddr <= X"00000004";
writeB <= X"0";
dataOutB <= X"00000000";
done <= '0';
u2 <= fDataIn;
next_state <= s_setX_Addr;
when s_setX_Addr =>
lAddr <= X"00000008";
writeB <= X"0";
dataOutB <= X"00000000";
done <= '0';
next_state <= s_readX_Addr;
when s_readX_Addr =>
lAddr <= X"00000008";
writeB <= X"0";
dataOutB <= X"00000000";
done <= '0';
x <= fDataIn;
next_state <= s_setY_Addr;
when s_setY_Addr =>
lAddr <= X"0000000C";
writeB <= X"0";
dataOutB <= X"00000000";
done <= '0';
next_state <= s_readY_Addr;
when s_readY_Addr =>
lAddr <= X"0000000C";
y <= fDataIn;
writeB <= X"0";
dataOutB <= X"00000000";
done <= '0';
next_state <= s_calc;
when s_calc =>
-- t1 <= (u1 * x) - (u2 * y);
-- t2 <= (u1 * y) + (u2 * x);
writeB <= X"0"; -- f
dataOutB <= X"00000000";
done <= '0';
next_state <= s_setT1Addr;
when s_setT1Addr =>
-- t1 <= (u1 * x) - (u2 * y);
-- t2 <= (u1 * y) + (u2 * x);
lAddr <= X"00000010";
dataOutB <= std_logic_vector(t1);
writeB <= X"0"; -- f
done <= '0';
next_state <= s_writeT1;
when s_writeT1 =>
-- t1 <= (u1 * x) - (u2 * y);
-- t2 <= (u1 * y) + (u2 * x);
lAddr <= X"00000010";
dataOutB <= std_logic_vector(t1);
writeB <= X"F";
done <= '0';
next_state <= s_setT2Addr;
when s_setT2Addr =>
-- t1 <= (u1 * x) - (u2 * y);
-- t2 <= (u1 * y) + (u2 * x);
lAddr <= X"00000014";
dataOutB <= std_logic_vector(t2);
writeB <= X"0"; -- f
done <= '0';
next_state <= s_writeT2;
when s_writeT2 =>
-- t1 <= u2 - u1;--(u1 * x) - (u2 * y);
-- t2 <= y - x;--(u1 * y) + (u2 * x);
lAddr <= X"00000014";
dataOutB <= std_logic_vector(t2);
writeB <= X"F";
done <= '0';
next_state <= s_done;
when s_done =>
writeB <= X"0";
dataOutB <= X"00000000";
if (start = '1') then -- hold until PS acks
next_state <= s_done;
done <= '1';
else
done <= '0';
next_state <= s_wait;
end if;
when others =>
null;
end case;
end process;
updateState: process(S_AXI_ACLK, S_AXI_ARESETN)
begin
if S_AXI_ARESETN = '0' then
present_state <= s_wait;
-- miniCounter <= 0;
-- counter <= 0;
elsif S_AXI_ACLK'event and S_AXI_ACLK = '1' then
present_state <= next_state;
-- miniCounter <= miniCounter + 1;
-- counter <= counter + 1;
end if;
end process;
-- User logic ends
end arch_imp;