05-12-2020 04:22 PM - edited 05-13-2020 04:02 AM
Hi,
I have had great success using the Vivado design flow from start (designing IP in Verilog) to finish (deployed and running in the real world). I am now looking to investigate improvements to my signal processing system and this requires me to instantiate a variable number of BRAM Ports, depending on the number of channels I want in my own custom IP. This could be up to 12, so I want to avoid a manual copy and paste approach. I have implemented this in code using genvar and it appears to be recognising and instantiating BRAM Port instances correctly, according to value of my CHANNELS parameter (please see code below):
#(parameter integer CHANNELS = 2)(
// #################### BRAM 0 ##########################
// BRAM PORT A
output wire bram_porta_clk,
output wire bram_porta_rst,
output wire [BRAM_ADDR_WIDTH-1:0] bram_porta_addr,
output wire [BRAM_DATA_WIDTH-1:0] bram_porta_wrdata,
input wire [BRAM_DATA_WIDTH-1:0] bram_porta_rddata,
output wire bram_porta_we,
// BRAM PORT B
output wire bram_portb_clk,
output wire bram_portb_rst,
output wire [BRAM_ADDR_WIDTH-1:0] bram_portb_addr,
output wire [BRAM_DATA_WIDTH-1:0] bram_portb_wrdata,
input wire [BRAM_DATA_WIDTH-1:0] bram_portb_rddata,
output wire bram_portb_we
); // ################### END of BRAM 0 ######################
// ############ Instantiate N Channel BRAMs ############### genvar i; generate for(i=0; i<CHANNELS; i=i+1) begin : gen_UUT1 bram_ports #( .BRAM_DATA_WIDTH(BRAM_DATA_WIDTH), .BRAM_ADDR_WIDTH(BRAM_ADDR_WIDTH) ) UUT1 ( // BRAM PORT A .bram_porta_clk(bram_porta_clk), .bram_porta_rst(bram_porta_rst), .bram_porta_addr(bram_porta_addr), .bram_porta_wrdata(bram_porta_wrdata), .bram_porta_rddata(bram_porta_rddata), .bram_porta_we(bram_porta_we), // BRAM PORT B .bram_portb_clk(bram_portb_clk), .bram_portb_rst(bram_portb_rst), .bram_portb_addr(bram_portb_addr), .bram_portb_wrdata(bram_portb_wrdata), .bram_portb_rddata(bram_portb_rddata), .bram_portb_we(bram_portb_we) ); end : gen_UUT1 endgenerate
First of all, I know that the code above is not scalable to N Channels as I don't know how I would specifically address X Channel in my code. So my first question is what would be the appropriate syntax? (my logic tells me the below but that doesn't work)
UUT1[0].bram_porta_addr = {(BRAM_ADDR_WIDTH){1'b0}};
Secondly, how would this be set in the Vivado IP Packager GUI? Would I have to assign up to 12 BRAM ports manually and then set a dependency condition for each one or is there some smart way of doing this. From the Vivado blocks I know that AXI Interconnect can potentially have a large number of output ports, surely this was coded/setup programmatically?
Edit: this answer record helped me solve my 2nd question. https://www.xilinx.com/support/answers/61620.html
I am also open to alternative approaches, since it is my first time doing this.
Thank you for your time.
Best Regards, Ren
05-13-2020 06:52 AM
Update:
I have read this article which instructs how to create an interface array using System Verilog: https://stackoverflow.com/questions/42484688/systemverilog-interface-array-with-different-parameters I have since updated my top to SV and modified my code shown below:
interface itf #( parameter integer BRAM_DATA_WIDTH = 64, parameter integer BRAM_ADDR_WIDTH = 16 ) ( // PORT A output logic bram_porta_clk, output logic bram_porta_rst, output logic [BRAM_ADDR_WIDTH-1:0] bram_porta_addr, output logic [BRAM_DATA_WIDTH-1:0] bram_porta_wrdata, input logic [BRAM_DATA_WIDTH-1:0] bram_porta_rddata, output logic bram_porta_we, // PORT B output logic bram_portb_clk, output logic bram_portb_rst, output logic [BRAM_ADDR_WIDTH-1:0] bram_portb_addr, output logic [BRAM_DATA_WIDTH-1:0] bram_portb_wrdata, input logic [BRAM_DATA_WIDTH-1:0] bram_portb_rddata, output logic bram_portb_we ); assign bram_portb_we = 1'b0; assign bram_portb_wrdata = {(BRAM_DATA_WIDTH){1'b0}}; endinterface // ************** Multiple Interfaces ******************** interface itfa #( parameter integer BRAM_DATA_WIDTH = 64, parameter integer BRAM_ADDR_WIDTH = 16, parameter integer CHANNELS = 3 ) ( // PORT A output logic bram_porta_clk, output logic bram_porta_rst, output logic [BRAM_ADDR_WIDTH-1:0] bram_porta_addr, output logic [BRAM_DATA_WIDTH-1:0] bram_porta_wrdata, input logic [BRAM_DATA_WIDTH-1:0] bram_porta_rddata, output logic bram_porta_we, // PORT B output logic bram_portb_clk, output logic bram_portb_rst, output logic [BRAM_ADDR_WIDTH-1:0] bram_portb_addr, output logic [BRAM_DATA_WIDTH-1:0] bram_portb_wrdata, input logic [BRAM_DATA_WIDTH-1:0] bram_portb_rddata, output logic bram_portb_we ); generate genvar i; for (i = 0; i < CHANNELS-1; i++) begin : interfaces itf #(.BRAM_DATA_WIDTH(BRAM_DATA_WIDTH), .BRAM_ADDR_WIDTH(BRAM_ADDR_WIDTH) ) itf_inst ( // Port A .bram_porta_clk(bram_porta_clk), .bram_porta_rst(bram_porta_rst), .bram_porta_addr(bram_porta_addr), .bram_porta_wrdata(bram_porta_wrdata), .bram_porta_rddata(bram_porta_rddata), .bram_porta_we(bram_porta_we), // Port B .bram_portb_clk(bram_portb_clk), .bram_portb_rst(bram_portb_rst), .bram_portb_addr(bram_portb_addr), .bram_portb_wrdata(bram_portb_wrdata), .bram_portb_rddata(bram_portb_rddata), .bram_portb_we(bram_portb_we) ); end endgenerate endinterface module top #( parameter integer AXIS_TDATA_WIDTH = 64, parameter integer BRAM_DATA_WIDTH = 64, parameter integer BRAM_ADDR_WIDTH = 16, parameter integer CHANNELS = 3 ) ( // BRAM Cycle Interface itfa itfs ); endmodule : top
It can successfully infer one instance of 'itfs' in the Ports and Interfaces window, is there some further configuration or syntax which I need to implement in order to get this working ?
I would really like to know otherwise I will have to implement some complex variable BRAM memory logic. I also forgot to mention that I do indeed require separate instances of BRAMs since I need to implement a sliding window in each one.
It also appears that this 'array of interfaces' functionality was added to Vivado recently as of 2019 according to: https://forums.xilinx.com/t5/Simulation-and-Verification/Arrays-of-Interfaces/td-p/801616
Any help would be greatly appreciated.
Best Regards, Ren