Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
I'm trying to create a bitfile for a hardware design that includes HDL and Xilinx IP Cores. It includes a softcore processor (Pulpino RI5CY Core) connected to 2 separate BlockRAM Controllers. I'm trying to use XPM (Xilinx Parameterized Macros) to specify the BlockRAMs the processor is connected to so that I can specify their contents without having to constantly re-synthesise my design. I followed the steps as laid out in UG898 (page 173 onwards) however when I try to generate the MMI file I need to complete Step 18. I get the following error message:
The XPM instance: <kuuga_ila_i/inst_bram/inst/xpm_memory_spram_inst/xpm_memory_base_inst> is part of IP: <kuuga_ila_i/inst_bram>. This XPM instance will be excluded from the .mmi because updatemem is prohibited from making changes to an XPM that is part of an IP.
I've tried several methods to alleviate the problem including trying to manually write the MMI file and using the write_mmi TCL script that's included in this AR. But they have both been unsuccessful in generating me the file I need.
My intuition is that the problem is in Step 14 where UG898 talks about: "Complete the definition of the HDL file by adding the appropriate entity and/or module definition". I've tried to do this in the code included below and then added it to my exisiting Block Design by instantiating that code as an RTL Module again as per UG898. But due to the ambiguity of the instructions and my inability to find an example online of someone who has done this I can't find a correct example to study and understand. I can somewhat see what I might need to do in terms of instantiating the XPM another way but I don't know how that would be possible while still connecting everything into my existing Block Design.
Verilog Code for instantiation of XPM (Mostly a copy of the Xilinx Template with module code added around it)
module bram
READ_DATA_WIDTH_A = 32,
ADDR_WIDTH_A = 32,
WRITE_DATA_WIDTH_A = 32
output [READ_DATA_WIDTH_A-1:0] douta,
input [ADDR_WIDTH_A-1:0] addra,
input clk_a,
input [WRITE_DATA_WIDTH_A-1:0] dina,
input ena,
input regcea,
input rst_a,
input [3:0] wea
xpm_memory_spram #(
.ADDR_WIDTH_A(ADDR_WIDTH_A), // DECIMAL
.AUTO_SLEEP_TIME(0), // DECIMAL
.BYTE_WRITE_WIDTH_A(32), // DECIMAL
.ECC_MODE("no_ecc"), // String
.MEMORY_INIT_FILE("none"), // String
.MEMORY_INIT_PARAM("0"), // String
.MEMORY_OPTIMIZATION("true"), // String
.MEMORY_PRIMITIVE("auto"), // String
.MEMORY_SIZE(65536), // DECIMAL
.MESSAGE_CONTROL(0), // DECIMAL
.READ_DATA_WIDTH_A(READ_DATA_WIDTH_A), // DECIMAL
.READ_LATENCY_A(2), // DECIMAL
.READ_RESET_VALUE_A("0"), // String
.USE_MEM_INIT(1), // DECIMAL
.WAKEUP_TIME("disable_sleep"), // String
.WRITE_DATA_WIDTH_A(WRITE_DATA_WIDTH_A), // DECIMAL
.WRITE_MODE_A("read_first") // String
xpm_memory_spram_inst (
.douta(douta), // READ_DATA_WIDTH_A-bit output: Data output for port A read operations.
.addra(addra), // ADDR_WIDTH_A-bit input: Address for port A write and read operations.
.clka(clk_a), // 1-bit input: Clock signal for port A.
.dina(dina), // WRITE_DATA_WIDTH_A-bit input: Data input for port A write operations.
.ena(ena), // 1-bit input: Memory enable signal for port A. Must be high on clock
// cycles when read or write operations are initiated. Pipelined
// internally.
.regcea(regcea), // 1-bit input: Clock Enable for the last register stage on the output
// data path.
.rsta(rst_a), // 1-bit input: Reset signal for the final port A output register stage.
// Synchronously resets output port douta to the value specified by
// parameter READ_RESET_VALUE_A.
.wea(wea) // WRITE_DATA_WIDTH_A-bit input: Write enable vector for port A input
// data port dina. 1 bit wide when word-wide writes are used. In
// byte-wide write configurations, each bit controls the writing one
// byte of dina to address addra. For example, to synchronously write
// only bits [15-8] of dina when WRITE_DATA_WIDTH_A is 32, wea would be
// 4'b0010.
// End of xpm_memory_spram_inst instantiation
endmodule
Is following Step 14 my problem or is there a different way to instantiate the XPM that I haven't yet found? Am I going about this the wrong way and I should actually just try and generate the MMI file manually? Any help would be very appreciated.
TL:DR I've tried to use XPM so I can set BlockRAM contents after my bit-file is made but I can't generate the MMI file to do so and it has something to do (I think) with how I've instantiated the XPM.
So I managed to solve my immediate problem, if you instantiate the XPM instances in the top-level wrapper file for the Block Design and add external ports from the Block Design to pipe the XPM data into the AXI BRAM controller everything proceeds as would be expected and both write_mem_info and updatemem appear to work as designed.
I'll not mark the question as complete yet because I'd still like to know if there's a solution that works if you follow UG898 exactly but at least I have a workaround for now.
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.