Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Problem using Max 10's memory blocs

Status
Not open for further replies.

Pastel

Member level 3
Joined
Jun 30, 2019
Messages
55
Helped
2
Reputation
4
Reaction score
1
Trophy points
8
Activity points
969
Hi guys!

It's been a while...
I'm digging into an earlier project in which I started using arrays in order
to generate a sinewave from an external DAC. That was my very first project,
and now I'm trying to make it better.
Before I forget: I'm working on a MAX10M50DAF484C8G, quite an impressive beast.
I'm working on Linux Ubuntu 20.04, and the quartus prime version is also 20.
The latest, I guess.

What I was doing previously was, after generating a 24-bit data file (sine24_4k.hex),
declaring an array reg signed[23:0] signalrom[4095:0];

Basically it worked, but I understood recently that this doesn't use memory blocks
but instead makes everything from logic elements, so I thought it would be better
to shift to existing IP. There is apparenlty what I need in Library -> On Chip Memory
-> ROM: 2port. What I'm thinking is using an array as I did earlier, and interpolate
2 consecutive values to get the accuracy I need.

Ok, after this long preamble, I wrote this.I used only a top module and tried to
instantiate a memory called sig_rom.

There are 3 modes of calculation. (CALC_SWITCH on the first line).

When 0, I simply output the 16-bit upper value of a 24 bit counter. This one works
exactly as intended, I can observe a sawtooth on the scope, and the frequency is
50 MHZ / 65536 = 732Hz.

Then I wanted to verify the addresses for the memory. They should be 12 bit, so I
extract exactly 12 bits from the same 24 bit counter, to get lindex and rindex, the
indices of the 2 values I would like to extract. In order to see the difference of the
2 waves, I shift the rindex value by 1/4 of the array, therefore I expect to get the
exact same frequency as above (732Hz), but one of the 2 sawtooths will be shifted.
Experiment, that's exactly what I observe, therefore I guess lindex and rindex are
right.

Last, I have instantiated the memory, using 2 registers da and db (DA and DB are the
outputs, da and db are the outputs of the memory). So I guess the memory should spit
values addressed by lindex and rindex, but nothing happens. The output stays 0.

Does anybody have an explanation?

Thanks for any hint.

Code:
`define    CALC_SWITCH 2

module MemIPTest(
    DA,
    DB,
    error,
    max_clk,
    clk
);
    //    Interface variables
    output reg [15:0] DA;
    output reg [15:0] DB;
    output reg error;
    output max_clk;
    input clk;
    //    Internal variables
    reg[23:0] counter = 0;
    reg[11:0] lindex = 0;
    reg[11:0] rindex;
    reg signed[17:0] da;
    reg signed[17:0] db;
    reg pll_lock;
    reg spi_clk;
    //    Realtime
    //    Generate clocks
    SysClkPLL system_pll(
        .inclk0(clk),
        .c0(sys_clk),                    //    Changed sysclock out sys clock
        .c1(max_clk),
        .c2(spi_clk),
        .locked(pll_lock)
    );
    //    Get data from memory
    sig_rom signal(
        .address_a(lindex),
        .address_b(rindex),
        .clock(sys_clk),
        .q_a(da),
        .q_b(db)
    );
    always@(posedge clk) begin
        if(max_clk == 1) begin
            counter <= counter+23'h000100;        //    Add 2^8, therefore counter[23:8] will count 1 by 1 from 0 to 2^16 - 1
            if(counter < 23'h001000) begin        //    Generato output sync pulse for oscilloscope
                error <= 1;
            end
            else begin
                error <= 0;
            end
            //    Calculate lindex and rindex for addressig the dual ROM
            lindex <= counter[23:12];                //    Get a 12 bit addressing value from array
            rindex <= lindex + 1024;                //    Calculate cosine value from 1/4 phase
        end
        else begin
            case(`CALC_SWITCH)
            0:
            begin
                //    Check the counter value (works fine on the oscilloscope, observed exactly as it should be).
                DA <= counter[23:8];                    //    Get a 16 bit value for output from counter
                DB <= counter[23:8];                    //    Same on channel B
            end
            1:
            begin
                //    Check the index values on the oscilloscope. Works fine, values are as expected.
                DA <= lindex << 4;                    //    Restore a 16 bit value for observation on the scope
                DB <= rindex << 4;
            end
            2:
            begin
                //    Check the values of the ROM. Does not work. The da and db values are apparently not generated from sig_rom
                //    I get only 0s.
                DA <= da[17:2];                        //    Make a 16 bit value from 18 bit.
                DB <= db[17:2];
            end
            endcase
        end
    end

endmodule
 

The ROM usage looks correct, but the sig_ram module declaration isn't shown. We don't know if an initialisation file is referenced in the code.

If a ROM can't be inferred as intended, the compiler warnings will show you why. With MAX10, you need to select a configuration scheme with memory initilization, otherwise no ROM and initialized RAM is possible.
 

Hello!

Thanks for your reply!
> The sig_ram module declaration is not shown.
You mean sig_rom, right?
The sig_rom is a standard IP from Quartus, I didn't write it myself.
I have chosen Library -> On Chip Memory -> ROM: 2port frome Quartus IP menu (on the right).
It's a memory of 4096 words of 18 bits. Just in case, here is the .v file:

By the way, when posting code, what does svg mean? System Verilog?

Another thing I was wondering: the file sine18_4k.hex mentioned below contains 20 bit codes.
Heere are the first 2 lines:
00000 000c9 00192 0025b 00324 003ed 004b6 0057f
00648 00711 007da 008a3 0096c 00a35 00afe 00bc7
Here it's quite clear that the first bits are 0, but when going in the negative numbers:
00000 fff37 ffe6e ffda5 ffcdc ffc13 ffb4a ffa81
ff9b8 ff8ef ff826 ff75d ff694 ff5cb ff502 ff439
how will the first 2 bits treated?
NB: I haven't used the sine symmetries for simplicity, and also because the final signal
will not be a sine.

Thanks


SVG:
module sig_rom (
    address_a,
    address_b,
    clock,
    q_a,
    q_b);

    input    [11:0]  address_a;
    input    [11:0]  address_b;
    input      clock;
    output    [17:0]  q_a;
    output    [17:0]  q_b;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
    tri1      clock;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif

    wire [17:0] sub_wire0;
    wire [17:0] sub_wire1;
    wire [17:0] sub_wire2 = 18'h0;
    wire  sub_wire3 = 1'h0;
    wire [17:0] q_a = sub_wire0[17:0];
    wire [17:0] q_b = sub_wire1[17:0];

    altsyncram    altsyncram_component (
                .address_a (address_a),
                .address_b (address_b),
                .clock0 (clock),
                .data_a (sub_wire2),
                .data_b (sub_wire2),
                .wren_a (sub_wire3),
                .wren_b (sub_wire3),
                .q_a (sub_wire0),
                .q_b (sub_wire1)
                // synopsys translate_off
                ,
                .aclr0 (),
                .aclr1 (),
                .addressstall_a (),
                .addressstall_b (),
                .byteena_a (),
                .byteena_b (),
                .clock1 (),
                .clocken0 (),
                .clocken1 (),
                .clocken2 (),
                .clocken3 (),
                .eccstatus (),
                .rden_a (),
                .rden_b ()
                // synopsys translate_on
                );
    defparam
        altsyncram_component.address_reg_b = "CLOCK0",
        altsyncram_component.clock_enable_input_a = "BYPASS",
        altsyncram_component.clock_enable_input_b = "BYPASS",
        altsyncram_component.clock_enable_output_a = "BYPASS",
        altsyncram_component.clock_enable_output_b = "BYPASS",
        altsyncram_component.indata_reg_b = "CLOCK0",
`ifdef NO_PLI
        altsyncram_component.init_file = "sine18_4k.rif"
`else
        altsyncram_component.init_file = "sine18_4k.hex"
`endif
,
        altsyncram_component.intended_device_family = "MAX 10",
        altsyncram_component.lpm_type = "altsyncram",
        altsyncram_component.numwords_a = 4096,
        altsyncram_component.numwords_b = 4096,
        altsyncram_component.operation_mode = "BIDIR_DUAL_PORT",
        altsyncram_component.outdata_aclr_a = "NONE",
        altsyncram_component.outdata_aclr_b = "NONE",
        altsyncram_component.outdata_reg_a = "CLOCK0",
        altsyncram_component.outdata_reg_b = "CLOCK0",
        altsyncram_component.power_up_uninitialized = "FALSE",
        altsyncram_component.widthad_a = 12,
        altsyncram_component.widthad_b = 12,
        altsyncram_component.width_a = 18,
        altsyncram_component.width_b = 18,
        altsyncram_component.width_byteena_a = 1,
        altsyncram_component.width_byteena_b = 1,
        altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK0";


endmodule
--- Updated ---

Hello again!

By the way, I forgot to ask something.
If a ROM can't be inferred as intended, the compiler warnings will show you why. With MAX10, you need to select a configuration scheme with memory initilization, otherwise no ROM and initialized RAM is possible.

How do I "select a configuration scheme with memory initialization"?
I thought what I configured in the memory configuration GUI (i.e. size parameters and configuration file) would make it.
Are there other configurations? I have looked at the compiler output, but I don't see any error likely to be related to this
issue. There is one warning saying:

[/quote]
Warning (292013): Feature LogicLock is only available with a valid subscription license. You can purchase a software subscription to gain full access to this feature.
I'm not sure what it means, but I'm working with the lite version, without a license

Thanks
 
Last edited:

Assignments/Device/Device and Pin Options/Configuration/Configuration mode

1602670316296.png


It's no license problem, don't care about LogicLock.
 

Hello!
Thanks for your help. 2 news, one bad, one good.
The bad one is that my program still doesn't work, I don't get anything at the output.
The good one is that the limitations I had with my previous program (using too many
logic elements) seem to be solved by this setting.
So one question: what will the predefined IP bring to what I wrote?
Well, it's a bit late and I will not put too much effort it today but if I just make a custom
module containing reg signed[23:0] signalrom[4095:0]; then initialize it with some file
with readmh, and finally use the data as my_output <= signahrom[phase]; what would
be the merits of using quartus IP ? (other than a greater reliability because it has been tested
and retested and debugged by specialists)
I just want an array of data, nothing fancy. Can this work?

Thanks,
 


Hello!
Thanks for your reply!
And thanks for the link. It confirms that it's basically what I was more or less doing before trying to instantiate the
memory IP. Beside this what I did was working but I didn't manage to get the IP data.

That said, I found some possible explanation of why it doesn't work.
I read somewhere that the memory can be initialized with $readmh, which expects data like this:
0000 0001 0002.... etc, without 0x, only with spaces.
And apparently the memory IP expects intel .hex format, the lines starting with a dot and including checksums.
So that's a good argument to stick with the files I have already generated, with separated data.
So since I have setup that file in the configuration GUI, and since it's not the proper format, I'm not
surprised anymore that I don't get output.

Beside this, I would like to apologize for the assignments -> device setting above. I recall I already had
a similar problem in the past, but a few months ago, maybe beginning of this year or end of last year.
And I didn't touch HDL since that time. I hope I'll remember next time.
 

Hello!
I am trying to use the dual port sunchronous ROM described in the document above. I have made the proper
setting as indicated above (assignments -> device, etc..). I used the code example 13-31. Analyzis and synthesis goes fine, but I get the following
error in the fitter process.

Error (176029): Memory block signal_maker:comb_3|dual_port_rom:sine|altsyncram:rom_rtl_0|altsyncram_f071:auto_generated|ram_block1a8 uses a global signal on its clock-enable1 port. This is not allowed for this family.

I'm not sure of what it says. I have checked the following page where I found some description of the problem.


How do I "Change the signal source of the clock-enable1 port to use no control signal or a non-global control signal."?
Apparently even if I use the code above, some ROM macrofunction is used.

I found also a page that might be related,


I opened the qsf file and tried to change set_instance_assignment for
clocks to set_location_assignment, but I must admit it's a blind try, I don't know what it does and anyway quartus
detects an error and writes the file back to its former state.

Could anybody tell me what to do?

Thanks,
 

Why are you using a global signal as memory clock enable? Presumedly, you are using an inappropriate clock enable, e.g. a global clock.

Please explain what you are trying to achieve.
 

Hello!
I don't use any clock enable, so I can't understand the error message. I noticed that some memory (altsyncram) is generated, but the complexity of that file is beyond my newbie understanding. And I'm not sure of what is a global signal. Is it one that is in the parameter list of the top module?
I don't use these directly in the ROM call.

NB: I probably use the wrong words. Parameters, call, etc... I have a MCU programmer background, so I'm "calling" modules. I don't know if I should rather instantiate them or infer them, but I guess you see what I mean.

I'm making a 8 channel DAC feeding FPGA, that can be loaded with various signals.
So basically each channel just reads data from a .hex files with $readmh, and throws the data to output at a specified timing.
I'm generating all clocks from the external clock like this:
Code:
sys_clk_pll sys_clocks(
        .areset(0),
        .inclk0(clk),
        .c0(sys_clk),
        .c1(max_clk),
        .c2(spi_tempo),
        .locked()
    );
The PLL is a altpll from the IP library. I have verified on the scope that the timing is compatible with the DAC I use.
The output clocks are:
sys_clk: a copy of the input clock (clk) with a phase for timing compatibility
max_clk: half rate (50 MHz) clock for Maxim DAC data latching.
spi_tempo: a kind of clock, but not used directly because I want it to output a given number of clocks to an external spi device.

As said above, the ROM I used was copied from the links from ads-ee, example 13.31. It is set like this:
Code:
    dual_port_rom sine(
        .ldata(datal),
        .rdata(datar),
        .laddr(addl),
        .raddr(addr),
        .clk(sys_clk),
    );
In order to verify with a known signal, it takes a sine signal.
NB: as the signals will be interpolated between 2 consecutive values, I have renamed to ldata, rdata for left and right,
which is a bit more readable than q_a and q_b, but basically it's the same module as in 13.31.

So to summarize, I have the impression I don't use a clock enable, and I don't understand the message. If necessary I can make
a small subset program to show exactly what I do. But maybe you already understand what happens...

Thanks,
 

O.K., no clock enable. In this case I can only guess that the misleading error message is brought up by other conected signals, e.g. thr address input. May be the compiler is pulling an external address register into the RAM IP. We can't determine without seeing the respective design part.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top