Hello! I am currently working on a matrix multiplication project. After performing the multiplication of the matrices, I am trying to build a module that can write to memory and can be read from by the UART TX module to send to host pc. What I don't understand is how does inferring a BRAM make it function as a FIFO? Do I need a separate module for a fifo buffer unit? The VHDL book I use has a sentence that I am not sure I understand completely: "Infact, the BRAM module of the Artix device can be configured as a FIFO buffer without any extrernal logic."
I have the following code for inferring a Simple(Sync) Dual Port BRAM for the Matrix Result:
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity bram_simpledual is generic( ADDR_WIDTH: integer := 4; DATA_WIDTH: integer := 16 ); Port ( clk : in std_logic; we : in std_logic ; addr_r, addr_w : in std_logic_vector (ADDR_WIDTH - 1 downto 0); din_a : in std_logic_vector (DATA_WIDTH - 1 downto 0); dout : out std_logic_vector (DATA_WIDTH - 1 downto 0) ); end bram_simpledual; architecture beh_arch of bram_simpledual is type ram_type is array (0 to 2** ADDR_WIDTH - 1) of std_logic_vector (DATA_WIDTH - 1 downto 0); signal ram: ram_type; begin process(clk) begin if(clk'event and clk = '1')then if(we = '1')then ram(to_integer(unsigned(addr_w))) <= din_a; end if; dout <= ram(to_integer(unsigned(addr_r))); end if; end process; end beh_arch;
If you are using Vivado (which you should be, for an Artix FPGA), then you can add a FIFO to your design by creating an IP block design and adding a FIFO. From there, you can edit the FIFO IP block and customize for your purposes. Make all connections external, validate design and then make an HDL wrapper, which is a VHDL module which can then be instantiated in your design and then you can access the FIFO as needed.
Now, the FIFO IP block in terms of hardware is inferred with the use of a BRAM. If you put a FIFO in your design and it is not being optimised out, you can observe this by synthesising, implement design and then open implemented design, and then use the tcl command 'report_utilization'. Scroll to the BRAM section and you will see that your FIFO does indeed use some BRAM.
You can also explicitly instantiate primitives such as a BRAM18 etc. manually, which is closer to what you have in your example code.
So in summary; instantiating a FIFO will infer a BRAM.
The above code would infer a memory (BRAM if you are targeting Xilinx) with write and read logic but NOT a FIFO. If you need a FIFO in the design, a FIFO could be created from the tool and the wrapper generated by the tool could be instantiated in your design, which is a safe approach. The tool could generate a BRAM based FIFO or Distributed RAM based FIFO depending on your customization. FIFO primitive is available for manual instantiation in some Xilinx families, please check the appropriate family HDL library. You could also manually instantiate BRAM and design remaining FIFO logic around it. I personally prefer to manually instantiate than infer any memory. To mention, if a particular component is not connected to module port or not connected to any logic that connects to port, in other words if a component is not viewed as a dependency from the perspective of module port, such component would be removed (optimised) from the netlist by the tool.
have a look to the UG768 "7 series FPGAs Libraries Guide" p60
You'll have the template to instantiate the right FIFO.