+ Post New Thread
Page 2 of 2 FirstFirst 1 2
Results 21 to 37 of 37
  1. #21
    Advanced Member level 4
    Points: 6,203, Level: 18

    Join Date
    Feb 2015
    Posts
    1,019
    Helped
    286 / 286
    Points
    6,203
    Level
    18

    Re: How to instantiate a submodule in Verilog

    inferring rams/roms still can be a tricky subject. you should read the synthesis coding guide and also look at the logs and implementation results. seemingly minor details can cause the tools to do unexpected things.



  2. #22
    Member level 1
    Points: 233, Level: 2
    Pastel's Avatar
    Join Date
    Jun 2019
    Posts
    38
    Helped
    1 / 1
    Points
    233
    Level
    2

    Re: How to instantiate a submodule in Verilog

    Hello!

    Thanks for your reply.

    inferring rams/roms still can be a tricky subject. you should read the synthesis coding guide and also look at the logs and implementation results. seemingly minor details can cause the tools to do unexpected things.
    I'm aware this might be a tricky subject. But although it cannot really be compared, writing
    in a CPU flash can be tricky. But it can be done, and for example TI gives examples on how to use
    the flash which is inside of the processor (unlock the flash, and if you want to alter one byte for
    instance, save the page that contains it, erase the flash page, change the byte in the saved buffer
    and save it, while being aware that you cannot set breakpoints inside of this process).

    So, RAM being internal to the FPGA, I don't think I'm expecting too much to have a piece of
    verilog or VHDL that would make a simple demonstration of what it works. So to rephrase
    my question: can anybody point me to a short piece of verilog that explains how to use
    MAX10's internal RAM?

    Thanks!

    Pastel



  3. #23
    Advanced Member level 4
    Points: 6,203, Level: 18

    Join Date
    Feb 2015
    Posts
    1,019
    Helped
    286 / 286
    Points
    6,203
    Level
    18

    Re: How to instantiate a submodule in Verilog

    So, RAM being internal to the FPGA, I don't think I'm expecting too much to have a piece of verilog or VHDL that would make a simple demonstration of what it works.
    It's tricky. best to read the docs for whatever synthesis tool you're using. More reliable than people guessing. You may also be expecting too much, sadly.



    •   AltAdvertisement

        
       

  4. #24
    Advanced Member level 5
    Points: 37,756, Level: 47
    Achievements:
    7 years registered

    Join Date
    Jun 2010
    Posts
    6,846
    Helped
    2012 / 2012
    Points
    37,756
    Level
    47

    Re: How to instantiate a submodule in Verilog

    Quote Originally Posted by Pastel View Post
    So, RAM being internal to the FPGA, I don't think I'm expecting too much to have a piece of
    verilog or VHDL that would make a simple demonstration of what it works. So to rephrase
    my question: can anybody point me to a short piece of verilog that explains how to use
    MAX10's internal RAM?
    https://www.intel.com/content/dam/ww...s_qii51007.pdf
    Page 13-13



  5. #25
    Super Moderator
    Points: 259,261, Level: 100
    Awards:
    1st Helpful Member

    Join Date
    Jan 2008
    Location
    Bochum, Germany
    Posts
    45,264
    Helped
    13770 / 13770
    Points
    259,261
    Level
    100

    Re: How to instantiate a submodule in Verilog

    You didn't yet answer which MAX10 type you are using. Probably you overlooked the comment in post #17 about "compact" flash types not supporting ROM inference.

    It makes little sense to explain RAM/ROM coding style in detail and then find out, that it's not supported by your MAX10 device.

    Initializing the RAM table at runtime through external CPU will work with any MAX10 however.



  6. #26
    Member level 1
    Points: 233, Level: 2
    Pastel's Avatar
    Join Date
    Jun 2019
    Posts
    38
    Helped
    1 / 1
    Points
    233
    Level
    2

    Re: How to instantiate a submodule in Verilog

    Hello!

    Thanks for your reply.
    The MAX10 I'm using is MAX10M50DAF484C8G.
    One of the largest.
    I'm looking for a verilog method to specify that I want to use the internal RAM.
    Currently looking at the output of the IP included in Quartus.
    I don't want to use a standard IP for the moment, I just want to use one memory block
    and more than one if it works.

    Thanks,

    Pastel



  7. #27
    Super Moderator
    Points: 259,261, Level: 100
    Awards:
    1st Helpful Member

    Join Date
    Jan 2008
    Location
    Bochum, Germany
    Posts
    45,264
    Helped
    13770 / 13770
    Points
    259,261
    Level
    100

    Re: How to instantiate a submodule in Verilog

    O.K. MAX10xxDA supports RAM initialization (ROM inference).

    As a starting point, you can use the RAM and ROM designs in Quartus Verilog templates, accessible through context menu in editor window.

    - - - Updated - - -

    There's a little trick with MAX10. You need to select a configuration scheme with memory initialization to allow ROM inference

    Click image for larger version. 

Name:	options.PNG 
Views:	12 
Size:	15.2 KB 
ID:	154869



  8. #28
    Super Moderator
    Points: 259,261, Level: 100
    Awards:
    1st Helpful Member

    Join Date
    Jan 2008
    Location
    Bochum, Germany
    Posts
    45,264
    Helped
    13770 / 13770
    Points
    259,261
    Level
    100

    Re: How to instantiate a submodule in Verilog

    Previous example supplemented with $readmemh initialization. Other initialization methods are possible, but not all are compatible with dual port ROM inference.

    Code Verilog - [expand]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    
    module test190803(DA, DB, max_clk, clk);
        output reg[15:0] DA, DB; // Data of the DAC
        output reg max_clk;  // Clock of the DAC
        input clk; // FPGA 100 MHz input clock
        // Some variables
        reg[15:0] sine[0:1023];
        reg[9:0] sinindex;
        reg[9:0] cosindex;
     
        initial begin
            sinindex = 0;
            cosindex = 256;
            $readmemh("sinetable.txt", sine);
        end
        always@(posedge clk) begin
            if(max_clk == 0) begin
                max_clk <= 1;
              sinindex <= sinindex+1;
              cosindex <= cosindex+1;
            end
            else begin
                max_clk <= 0;
            end
            // ROM must be read unconditionally to infer dual port ROM
            DA <= sine[sinindex];
            DB <= sine[cosindex];
        end
    endmodule



    •   AltAdvertisement

        
       

  9. #29
    Member level 1
    Points: 233, Level: 2
    Pastel's Avatar
    Join Date
    Jun 2019
    Posts
    38
    Helped
    1 / 1
    Points
    233
    Level
    2

    Re: How to instantiate a submodule in Verilog

    Hello!

    Thanks for your reply!
    I tried to do something... But I don't understand the compilation errors.
    Just in case, I took your code although mine was basically the same.
    See attached verilog.
    So basically, I have used the context menu to insert a dual port ROM, and a
    template was created.I changed the data and address widths (I suppose there
    is nothing wrong in the principle).
    I tried to instantiate one dual_port_rom in my code...
    But I got this error message
    Code:
    Info (276014): Found 1 instances of uninferred RAM logic
    	Info (276013): RAM logic "dual_port_rom:SineRom|rom" is uninferred because MIF is not supported for the selected family
    Error (276003): Cannot convert all sets of registers into RAM megafunctions when creating nodes. The resulting number of registers remaining in design exceeds the number of registers in the device or the number specified by the assignment max_number_of_registers_from_uninferred_rams. This can cause longer compilation time or result in insufficient memory to complete Analysis and Synthesis
    Error: Quartus Prime Analysis & Synthesis was unsuccessful. 1 error, 6 warnings
    	Error: Peak virtual memory: 652 megabytes
    	Error: Processing ended: Fri Aug 09 16:52:29 2019
    	Error: Elapsed time: 00:00:09
    	Error: Total CPU time (on all processors): 00:00:18
    Error (293001): Quartus Prime Full Compilation was unsuccessful. 3 errors, 6 warnings
    At that point, it looks like I have exactly the same message as before without inserting a template,
    so the ROM was not inferred.

    Now you were writing:
    There's a little trick with MAX10. You need to select a configuration scheme with memory initialization to allow ROM inference
    I couldn't get the setting window of your post below. Don't forget
    I'm an absolute beginner, so if you don't tell me the menu path from the root
    window, the odds of finding it are quite low.

    Another question: this is a dual port ROM, which is fine for the current design,
    but is it possible to make a 8-port ROM? For example by adding addr_a to addr_h,
    q_a to q_h?

    One more thing: I suppose the ROM will do the job as is, and therefore I don't need
    the DA <= sine[sinindex]; (and same for DB) that I used before, right?

    Thanks,

    Pastel

    Code Verilog - [expand]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    
    // Quartus Prime Verilog Template
    // Dual Port ROM
     
    module dual_port_rom
            #(parameter DATA_WIDTH=16, parameter ADDR_WIDTH=13) (
        input [(ADDR_WIDTH-1):0] addr_a, addr_b,
        input clk, 
        output reg [(DATA_WIDTH-1):0] q_a, q_b);
        // Declare the ROM variable
        reg [DATA_WIDTH-1:0] rom[2**ADDR_WIDTH-1:0];
        // Initialize the ROM with $readmemh instead of readmemb.
        initial begin
            $readmemh("sine8192.hex", rom);
        end
        always @ (posedge clk)
        begin
            q_a <= rom[addr_a];
            q_b <= rom[addr_b];
        end
    endmodule
     
    module Test190801(DA, DB, max_clk, clk);
        output reg[15:0] DA, DB; // Data of the DAC
        output reg max_clk;  // Clock of the DAC
        input clk; // FPGA 100 MHz input clock
        // Some variables
        reg[12:0] sinindex;
        reg[12:0] cosindex;
        //  Instanciation of dual port ROM
        dual_port_rom SineRom(
            .addr_a(sinindex), .addr_b(sinindex),
            .clk(clk),
            q_a(DA), q_b(DB)
        );
        //  Index calculation
        always@(posedge clk) begin
            if(max_clk == 0) begin
                max_clk <= 1;
                sinindex <= sinindex+1;
                cosindex <= cosindex+1;
            end
            else begin
                max_clk <= 0;
            end
        end
    endmodule



  10. #30
    Super Moderator
    Points: 259,261, Level: 100
    Awards:
    1st Helpful Member

    Join Date
    Jan 2008
    Location
    Bochum, Germany
    Posts
    45,264
    Helped
    13770 / 13770
    Points
    259,261
    Level
    100

    Re: How to instantiate a submodule in Verilog

    The error message shows that Quartus is trying to infer ROM, however the device type or configuration mode isn't appropriate.

    Go for "Assignments/Device/Device and Pin Options"



  11. #31
    Member level 1
    Points: 233, Level: 2
    Pastel's Avatar
    Join Date
    Jun 2019
    Posts
    38
    Helped
    1 / 1
    Points
    233
    Level
    2

    Re: How to instantiate a submodule in Verilog

    Hello!

    Thanks for your mail!
    I'm getting closer, this time it compiled. Now I would need some explanation.
    Here is the whole code. So I used the contextual menu to get a template. Now from
    my understanding, the submodule dual_port_rom, receives from the main module
    everything necessary to send the data I want to output ports.
    - It knows the outputs that were passed from the main module. (sorry, I use C / C++ vocabulary,
    I know that the variables don't move across the program, but anyway it looks like that).
    - It gets also the clock, and the 2 indexes, sinindex and cosindex. So its always@ block
    uses the internal data of this object to set data where it has to go, and therefore
    I don't need to have DA <= something in the top object.
    So I thought the simple fact that I declare a dual_port_rom SineRom in the top object
    would make it work.

    Now it doesn't work, and I would appreciate if anybody could explain me what's wrong.

    NB: When I say it doesn't work: the previous version used to work, to send data to my
    MAX5875 ADC and I could see a sine wave on the scope. Now I get absolutely nothing.
    It's the same file, nothing has changed (pin assignment is the same).

    Thanks for any hint.

    Pastel

    Code Verilog - [expand]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    
    // Quartus Prime Verilog Template
    // Dual Port ROM
     
    module dual_port_rom
            #(parameter DATA_WIDTH=16, parameter ADDR_WIDTH=13) (
        input [(ADDR_WIDTH-1):0] addr_a, addr_b,
        input clk, 
        output reg [(DATA_WIDTH-1):0] q_a, q_b);
        // Declare the ROM variable
        reg [DATA_WIDTH-1:0] rom[2**ADDR_WIDTH-1:0];
        // Initialize the ROM with $readmemh instead of readmemb.
        initial begin
            $readmemh("sine8192.hex", rom);
        end
        always @ (posedge clk)
        begin
            q_a <= rom[addr_a];
            q_b <= rom[addr_b];
        end
    endmodule
     
    module Test190801(DA, DB, max_clk, clk);
        output wire[15:0] DA, DB; // Data of the DAC
        output reg max_clk;  // Clock of the DAC
        input clk; // FPGA 100 MHz input clock
        // Some variables
        reg[12:0] sinindex;
        reg[12:0] cosindex;
        //  Instanciation of dual port ROM
        dual_port_rom SineRom(
            .addr_a(sinindex), .addr_b(sinindex),
            .clk(clk),
            .q_a(DA), .q_b(DB)
        );
        //  Index calculation
        always@(posedge clk) begin
            if(max_clk == 0) begin
                max_clk <= 1;
                sinindex <= sinindex+1;
                cosindex <= cosindex+1;
            end
            else begin
                max_clk <= 0;
            end
        end
    endmodule



  12. #32
    Super Moderator
    Points: 259,261, Level: 100
    Awards:
    1st Helpful Member

    Join Date
    Jan 2008
    Location
    Bochum, Germany
    Posts
    45,264
    Helped
    13770 / 13770
    Points
    259,261
    Level
    100

    Re: How to instantiate a submodule in Verilog

    It's not necessary to implement the ROM as separate module, it can be also embedded in the main code as in my example, but this shouldn't change anything.

    I don't find a reason for non-function of your code at first sight. Did you check data and clock signals with oscilloscope?



  13. #33
    Super Moderator
    Points: 31,315, Level: 43
    ads-ee's Avatar
    Join Date
    Sep 2013
    Location
    USA
    Posts
    7,231
    Helped
    1710 / 1710
    Points
    31,315
    Level
    43

    Re: How to instantiate a submodule in Verilog

    Ignoring the lack of any initialization of the sinindex and cosindex using a reset of some sort (don't know about max10, but some FPGAs have no guaranteed power up state for flip-flops) the code you posted in 31 simulates properly, so the problem is either in the synthesis or the p&r.

    Does the design still have the expect resource utilization counts? Did you verify the pins were assigned correctly by p&r? Did the design pass all DRC check during the compilation.

    FYI, just because a design finishes compilation doesn't mean it was compiled, placed, and routed correctly, GIGO applies.

    - - - Updated - - -

    Quote Originally Posted by Pastel View Post
    Another question: this is a dual port ROM, which is fine for the current design,
    but is it possible to make a 8-port ROM? For example by adding addr_a to addr_h,
    q_a to q_h?
    Yes, but it will require replicating the block RAM "ROM" 4 times to get to 8 as the physical block that comprises a memory in the device has only two physical memory array interface ports.



    •   AltAdvertisement

        
       

  14. #34
    Advanced Member level 4
    Points: 6,203, Level: 18

    Join Date
    Feb 2015
    Posts
    1,019
    Helped
    286 / 286
    Points
    6,203
    Level
    18

    Re: How to instantiate a submodule in Verilog

    is "sine8192.hex" something that works in simulation? I suspect readmemh failure is just a warning or silent failure.

    IIRC the last time I used readmemh with quartus I needed to add a sanity check to the build script because it wouldn't always work. maybe this was something I did wrong generating the data, but I don't trust the tools either way.



  15. #35
    Super Moderator
    Points: 31,315, Level: 43
    ads-ee's Avatar
    Join Date
    Sep 2013
    Location
    USA
    Posts
    7,231
    Helped
    1710 / 1710
    Points
    31,315
    Level
    43

    Re: How to instantiate a submodule in Verilog

    Quote Originally Posted by vGoodtimes View Post
    is "sine8192.hex" something that works in simulation? I suspect readmemh failure is just a warning or silent failure.
    Simulation wise Modelsim handles a file with hex data with $readmemh just fine. I checked that the data was read in using the 1024 size file that was posted earlier in the thread. If Quartus doesn't initialize a ROM properly with the $readmemh system task then that is a Quartus tool problem (Xilinx/Microsemi has no problem doing this).



  16. #36
    Super Moderator
    Points: 259,261, Level: 100
    Awards:
    1st Helpful Member

    Join Date
    Jan 2008
    Location
    Bochum, Germany
    Posts
    45,264
    Helped
    13770 / 13770
    Points
    259,261
    Level
    100

    Re: How to instantiate a submodule in Verilog

    You can verify that Quartus generates a respective *.mif file in the /db directory, the file name is listed in the synthesis report.

    Info (19000): Inferred 1 megafunctions from design logic
    Info (276029): Inferred altsyncram megafunction from the following design logic: "dual_port_rom:SineRom|rom_rtl_0"
    Info (286033): Parameter INIT_FILE set to db/test.ram0_dual_port_rom_e5e0e3d2.hdl.mif
    Info (12133): Instantiated megafunction "dual_port_rom:SineRom|altsyncram:rom_rtl_0" with the following parameter:
    Info (12134): Parameter "INIT_FILE" = "db/test.ram0_dual_port_rom_e5e0e3d2.hdl.mif"
    If you worry about correct ROM data, inspect the *.mif file.



  17. #37
    Member level 1
    Points: 233, Level: 2
    Pastel's Avatar
    Join Date
    Jun 2019
    Posts
    38
    Helped
    1 / 1
    Points
    233
    Level
    2

    Re: How to instantiate a submodule in Verilog

    Hello!

    Many thanks for all your support and detailed replies.
    By going to the basics (led blinker, but using a submodule to divide the clock), I found out
    what was wrong in my code. I needed wires, and (shame, the issue was solved by ads-ee very early in this
    thread). In the meantime, my code became a real mess, so I will not post it here,
    but anyway I can now load quite large files (64k coefficients sine table).

    Right now, I will divide the data by 4 by using the symmetries.

    I'm really starting to enjoy FPGA programming. It's really like a new world and I think I will spend the
    whole weekend on it...

    I will certainly have other questions, but again, many thanks fo you all!

    Pastel



--[[ ]]--