I want to write an IP to store/read data using BRAM.
What I have so far is using the (C)DMA to read memory mapped data out of the RAM and get an AXIS.
Then I created a new source file in VHDL to accept the AXIS on one side which worked like a charm.
On the other side I want to create a BRAM interface but vivado does not combine ports for the BRAM interface.
Located in the "vivado/data/ip/interfaces/bram_v1_0" folder a file "bram_rtl.xml" is present.
I tried to use the ports used in the xml file.
Especially the ports with the "required" tag.
The AXI BRAM Controller is combining them right so I am pretty sure I made a mistake. Using the same naming like the AXI BRAM Controller didn't work either.
My VHDL looks like this:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity AXIS_TO_BRAM is
generic (
addr_size : integer range 1 to 12 := 10
);
Port (
--axistream
tdata : in std_logic_vector(31 downto 0);
tkeep : in std_logic_vector(3 downto 0);
tlast : in std_logic;
tready : out std_logic;
tvalid : in std_logic;
aclk : in std_logic;
--BRAM
en : out std_logic;
dout : in std_logic_vector(31 downto 0);
din : out std_logic_vector(31 downto 0);
we : out std_logic;
addr : out std_logic_vector(addr_size-1 downto 0);
clk : out std_logic;
rst : out std_logic);
end AXIS_TO_BRAM;
architecture Behavioral of AXIS_TO_BRAM is
begin
end Behavioral;
I am using vivado 2016.4 for Zynq 7020 on Linux.
Is there something missing in the VHDL code to get vivado recognize my ports as BRAM interface or is this a bug in this version?
Thank your for any ideas
Here is the complete working and synthesizable VHDL code.
The correct solution (or at least the important part) is given in the comments by Vinay Madapura.
The predefined interfaces can be found in the folder $vivado/$version/data/ip/interfaces.
I hope this code will help other people struggling with similar problems.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity AXIS_TO_BRAM is
generic(
addr_size : integer range 1 to 12 := 10
);
Port(
tdata : in std_logic_vector(31 downto 0);
tkeep : in std_logic_vector(3 downto 0);
tlast : in std_logic;
tready : out std_logic;
tvalid : in std_logic;
aclk : in std_logic;
addra : out std_logic_vector(addr_size-1 downto 0);
clka : out std_logic;
dina : out std_logic_vector(31 downto 0);
douta : in std_logic_vector(31 downto 0);
ena : out std_logic;
rsta : out std_logic;
wea : out std_logic_vector(0 downto 0)
);
end AXIS_TO_BRAM;
architecture Behavioral of AXIS_TO_BRAM is
ATTRIBUTE X_INTERFACE_INFO : string;
ATTRIBUTE X_INTERFACE_INFO OF addra: SIGNAL IS "xilinx.com:interface:bram:1.0 BRAM_PORTA ADDR";
ATTRIBUTE X_INTERFACE_INFO OF clka: SIGNAL IS "xilinx.com:interface:bram:1.0 BRAM_PORTA CLK";
ATTRIBUTE X_INTERFACE_INFO OF dina: SIGNAL IS "xilinx.com:interface:bram:1.0 BRAM_PORTA DIN";
ATTRIBUTE X_INTERFACE_INFO OF douta: SIGNAL IS "xilinx.com:interface:bram:1.0 BRAM_PORTA DOUT";
ATTRIBUTE X_INTERFACE_INFO OF ena: SIGNAL IS "xilinx.com:interface:bram:1.0 BRAM_PORTA EN";
ATTRIBUTE X_INTERFACE_INFO OF rsta: SIGNAL IS "xilinx.com:interface:bram:1.0 BRAM_PORTA RST";
ATTRIBUTE X_INTERFACE_INFO OF wea: SIGNAL IS "xilinx.com:interface:bram:1.0 BRAM_PORTA WE";
begin
end Behavioral;
Related
I've got multiple (same) input/output to declare :
B1_data_to_send : in std_logic_vector(15 downto 0);
B1_start_transmission : out std_logic;
B1_transmission_busy : in std_logic;
B2_data_to_send : in std_logic_vector(15 downto 0);
B2_start_transmission : out std_logic;
B2_transmission_busy : in std_logic;
B3_data_to_send : in std_logic_vector(15 downto 0);
B3_start_transmission : out std_logic;
B3_transmission_busy : in std_logic;
B4_data_to_send : in std_logic_vector(15 downto 0);
B4_start_transmission : out std_logic;
B4_transmission_busy : in std_logic;
B5_data_to_send : in std_logic_vector(15 downto 0);
B5_start_transmission : out std_logic;
B5_transmission_busy : in std_logic;
B6_data_to_send : in std_logic_vector(15 downto 0);
B6_start_transmission : out std_logic;
B6_transmission_busy : in std_logic;
I've got 30 block like this to create, is there a way to avoid this repetition and to create a generic block that I can instantiate with different names ?
Arrays are what you need here. First, you will need to create an array type of std_logic_vector in a package. If you're using VHDL 2008, it can simply be an unconstrained type:
package types_pkg is
type slv_array_t is array(natural range <>) of std_logic_vector;
end package;
and then use this type in your entity:
use work.types_pkg.all;
entity your_entity is
port (
B_data_to_send : in slv_array_t (1 to 30)(15 downto 0);
B_start_transmission : out std_logic_vector(1 to 30);
B_transmission_busy : in std_logic_vector(1 to 30)
);
end entity;
Of course, any of the dimensions can come from a generic.
use work.types_pkg.all;
entity your_entity is
generic (
G_N_PORTS : natural;
G_D_WIDTH : natural
);
port (
B_data_to_send : in slv_array_t (0 to G_N_PORTS-1)(G_D_WIDTH-1 downto 0);
B_start_transmission : out std_logic_vector(0 to G_N_PORTS-1);
B_transmission_busy : in std_logic_vector(0 to G_N_PORTS-1)
);
end entity;
I want to use records as I have multiple ports which at the same time are composed by multiple signals. The issue is that some signals are in and some are out (AXI stream, specifically).
I want to avoid doing this:
port (
s0_axis_tvalid : in STD_LOGIC;
s0_axis_tdata : in STD_LOGIC_VECTOR (Data_Width-1 downto 0);
s0_axis_tlast : in STD_LOGIC;
s0_axis_tready : out STD_LOGIC;
s1_axis_tvalid : in STD_LOGIC;
s1_axis_tdata : in STD_LOGIC_VECTOR (Data_Width-1 downto 0);
s1_axis_tlast : in STD_LOGIC;
s1_axis_tready : out STD_LOGIC;
m0_axis_tvalid : out STD_LOGIC;
m0_axis_tdata : out STD_LOGIC_VECTOR (Data_Width-1 downto 0);
m0_axis_tlast : out STD_LOGIC;
m0_axis_tready : in STD_LOGIC);
So, I want to have some records looking like this:
type AXIS_Slave is record
s_axis_tvalid : STD_LOGIC;
s_axis_tdata : STD_LOGIC_VECTOR (Data_Width-1 downto 0);
s_axis_tlast : STD_LOGIC;
s_axis_tready : STD_LOGIC;
end record AXIS_Slave;
type AXIS_Master is record
s_axis_tvalid : STD_LOGIC;
s_axis_tdata : STD_LOGIC_VECTOR (Data_Width-1 downto 0);
s_axis_tlast : STD_LOGIC;
s_axis_tready : STD_LOGIC;
end record AXIS_Master;
Now, the port in my TOP's entity design should be:
Port (
s0: AXIS_Slave;
s1: AXIS_Slave;
m0: AXIS_Master);
The problem is that I need to declare in the Port whether it is in or out but the direction of each signal should be defined in the record, which I believe is not allowed as I get a warning "Syntax error near in" or "Syntax error near out".
So, how can I declare a type which has in and out signals?
I am implementing the MIPS processor in VHDL using Quartus II, and one of my components is causing an error that has me completely baffled.
I have the following component:
library ieee;
use ieee.std_logic_1164.all;
entity HazardDetectionUnit is
port(
--Datapath inputs
IFIDrt : in std_logic_vector(4 downto 0);
IDEXrt : in std_logic_vector(4 downto 0);
IFIDrs : in std_logic_vector(4 downto 0);
--Controlpath inputs
IDEXMemRead : in std_logic;
PCWrite : out std_logic;
IFIDWrite : out std_logic;
IDEXFlush : out std_logic);
end HazardDetectionUnit;
architecture structural of HazardDetectionUnit is
signal same1 : std_logic;
signal same2 : std_logic;
signal NZ1 : std_logic;
signal stall : std_logic;
component comp5
port( a : in std_logic_vector(4 downto 0);
b : in std_logic_vector(4 downto 0);
comp_output : out std_logic);
end component;
component zerocomp5
port ( a : in std_logic_vector(4 downto 0);
zero : out std_logic);
end component;
begin
--Port Map
comparator1 : comp5 port map(IFIDrt, IDEXrt, same1);
comparator2 : comp5 port map(IDEXrt, IFIDrs, same2);
nonzero1 : zerocomp5 port map(IDEXrt, NZ1);
--Concurrent Signal Assignment
stall <= NZ1 and IDEXMemRead and (same1 or same2);
--Output Driver
PCWrite <= not(stall);
IFIDWrite <= not(stall);
IDEXFlush <= stall;
end structural;
I'm having an issue with the comp5 component. The error I'm getting is Error (12012): Port direction mismatch for entity "MIPS_PROCESSOR:inst|HazardDetectionUnit:inst22|comp5:comparator1" at port "comp_output". Upper entity is expecting "Input" pin while lower entity is using "Output" pin.
The sub-component comp5, which is a 5-bit equality comparator, is as follows:
library ieee;
use ieee.std_logic_1164.all;
entity comp5 is
port( a : in std_logic_vector(4 downto 0);
b : in std_logic_vector(4 downto 0);
comp_output : out std_logic
);
end comp5;
architecture structural of comp5 is
signal xor_out : std_logic_vector(4 downto 0);
component nxor2_5bit
port( a : in std_logic_vector(4 downto 0);
b : in std_logic_vector(4 downto 0);
o : out std_logic_vector(4 downto 0));
end component;
begin
--Port Map
xor_gate : nxor2_5bit port map(a, b, xor_out);
--Output Driver
comp_output <= xor_out(4) and xor_out(3) and xor_out(2) and xor_out(1) and xor_out(0);
end structural;
How is this possible? The comp5 component is clearly defined as having two 5-bit inputs, a and b, and a single one-bit output, comp_output. So why does the compiler insist that comp_output is actually an input?
I tried to debug the issue by implementing HazardDetectionUnit as a block diagram, but I got the same error.
I don't get it. comp5 is just a simple two-input, one-output logic unit. I've never had an error like this before, and I can't find any posts about a similar error. Would anyone be able to offer advice?
Edit: for completeness, here is the nxor2_5bit component:
--5-bit NXOR gate.
library ieee;
use ieee.std_logic_1164.all;
entity nxor2_5bit is
port( a : in std_logic_vector(4 downto 0);
b : in std_logic_vector(4 downto 0);
o : out std_logic_vector(4 downto 0));
end nxor2_5bit;
architecture structural of nxor2_5bit is
begin
--Output Driver
o <= not(a(4) xor b(4)) & not(a(3) xor b(3)) & not(a(2) xor b(2)) & not(a(1) xor b(1)) & not(a(0) xor b(0));
end structural;
So I have the following VHDL code to implement an Nbit adder/subtractor using only a 2:1 mux, an inverter (flips bit), and a full adder. I am having issues connecting the carry out of an adder to the next ones carry in while having the first adder have a carry in of i_Control. Any help would be greatly appreciated :).
library IEEE;
use IEEE.std_logic_1164.all;
use work.all;
entity add_subtract is
generic(N : integer := 16);
port(i_M : in std_logic_vector(N-1 downto 0);
i_N : in std_logic_vector(N-1 downto 0);
i_Control : in std_logic_vector(N-1 downto 0);
o_S : out std_logic_vector(N-1 downto 0));
end add_subtract;
architecture structure of add_subtract is
component bit_adder
port(i_X : in std_logic;
i_Y : in std_logic;
i_Cin : in std_logic;
o_Ss : out std_logic;
o_Couts : out std_logic);
end component;
component inverter
port(i_A : in std_logic;
o_F : out std_logic);
end component;
component bit_mux
port(i_X : in std_logic;
i_Y : in std_logic;
i_S : in std_logic;
o_N : out std_logic);
end component;
signal compvalue, muxvalue, addervalue : std_logic_vector(N-1 downto 0);
signal sel, carry : std_logic_vector(N-1 downto 0);
signal k : integer := 0;
begin
carry(0) <= i_Control(0);
G1: for i in 0 to N-1 generate
one_comp: inverter
port map(i_A => i_N(i),
o_F => compvalue(i));
mux: bit_mux
port map(i_X => i_N(i),
i_Y => compvalue(i),
i_S => i_Control(i),
o_N => muxvalue(i));
struct_adder: bit_adder
port map(i_X => i_M(i),
i_Y => muxvalue(i),
i_Cin => carry(i),
o_Ss => o_S(i),
o_Couts => carry(i));
end generate;
end structure;
Make the carry array one longer:
signal carry : std_logic_vector(N downto 0); -- was N-1
and change this:
o_Couts => carry(i));
to this:
o_Couts => carry(i+1));
in your generate statement while leaving the i_Cin carry input association as is.
If the last carry out isn't conveyed through an output port the net will get eaten during synthesis.
I am a fresh student and the assignment is to build 3 components with testbench and then to arrange them into one structure. All 3 components I have built work great but when I put them together one of the the outputs stays undefined. I tried to trace the signal called dat and it is fine, but probably I am not using correct syntax to assign the dat signal to data_out . The id_led_ind is the second output and it works fine but the data_out is undefined.
Here is the code (i think the problem is in lane 21 - "data_out <= dat")
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
entity peak_detect is
port(
input : in std_logic_vector (7 downto 0);
data_out : out std_logic_vector (7 downto 0);
reset : in std_logic;
clock : in std_logic;
enable : in std_logic;
id_led_ind : out std_logic);
end peak_detect;
architecture dataflow of peak_detect is
signal a_big_b : std_logic;
signal en : std_logic;
signal dat : std_logic_vector (7 downto 0);
begin
en <= (enable or a_big_b);
data_out <= dat;
end dataflow;
architecture structure of peak_detect is
signal a_big_b : std_logic;
signal en : std_logic;
signal dat : std_logic_vector (7 downto 0);
component comp_8bit is
port(
A : in std_logic_vector (7 downto 0);
B : in std_logic_vector (7 downto 0);
res : out std_logic);
end component;
component dff is
port (
data : in std_logic_vector (7 downto 0);
q : out std_logic_vector (7 downto 0);
clk : in std_logic;
reset : in std_logic;
en : in std_logic);
end component;
component id_sens is
port(
data_in : in std_logic_vector (7 downto 0);
led : out std_logic);
end component;
begin
reg : dff port map (data => input, q => dat, clk => clock, reset => reset, en => enable);
comp : comp_8bit port map (A => input, B => dat, res => a_big_b);
sens : id_sens port map (data_in => dat, led => id_led_ind);
end structure;
There appears to be confusion over having two architectures (dataflow and structure) for the entity peak_detect. The two architectures are mutually exclusive, and the last one analyzed is the default in absence of other configuration specifying one of the architectures directly.
For purposes of evaluating how the components are interconnected and their port mapped connections relate to the port declarations of peak_detect, the first architecture could be commented out (dataflow).
When you disregard the architecture dataflow we find there is no driver for data_out in architecture structure.
You're missing an assignment to data_out using dat as a source in architecture structure, as found in architecture dataflow. Copy or replicate the concurrent signal assignment statement data_out <= dat; into architecture structure.
You can't simply connect data_out to q in the port map of dff because the output of dff is also used as an input to id_sense.
dat is driven by q of dff. That is not how you connect components. port map should be used to connect ports of different components/entities, not signals of any entity to the port of another entity.