Сбой Icarus Verilog при компиляции модуля динамической памяти

Это мой первый пост на Stackru.

Я новичок в Verilog, хотя у меня есть значительный опыт работы с Python, C и C++. Я использую Icarus Verilog версии 10.1.1 в Windows 10 и пытаюсь написать динамический распределитель памяти. По какой-то причине, когда эта команда запускается:

iverilog dynmem.v dynmem_test.v -o dynmem_test.out

выводится следующее:

Assertion failed!

Program: c:\iverilog\lib\ivl\ivl.exe
File: ../verilog-10.1.1/pform.cc, Line 333

Expression: lexical_scope

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

В чем проблема с моим кодом, и я должен представить отчет об ошибке для этого?

dynmem.v:

`define WORD_SIZE 32

`ifndef DYNMEM_SIZE // size of dynamic memory in words
  `define DYNMEM_SIZE 16384*8/WORD_SIZE // 16 KB
`endif

`define __DYNMEM_BIT_SIZE WORD_SIZE*DYNMEM_SIZE-1 // size of dynamic memory in bits

reg [__DYNMEM_BIT_SIZE:0] dynmem; // dynamic memory
reg [DYNMEM_SIZE:0] allocated; // bitvector telling which words are allocated
reg mutex = 0;

module dynreg(address,
              ioreg,
              read_en,
              write_en,
              realloc_en);
    output reg [WORD_SIZE-1:0] address;
    output reg [WORD_SIZE-1:0] ioreg;
    output reg read_en; // rising edge: put word stored at location address into ioreg
    output reg write_en; // rising edge: put word stored in ioreg into location address
    output reg realloc_en; // rising edge: if ioreg=0, free memory, otherwise reallocate memory into buffer of size ioreg.

    task malloc; // allocate dynamic memory
        output reg [WORD_SIZE-1:0] size;
        output reg [WORD_SIZE-1:0] start;

        unsigned integer size_int = size; // convert size to integer

        reg flag1 = 1;

        while (mutex) begin end // wait on mutex
        mutex = 1; // acquire mutex

        // loop through possible starting locations
        for (index=size_int-1; (index < DYNMEM_SIZE) && flag1; index=index+1) begin
            // check if unallocated
            reg flag2 = 1;
            for (offset=0; (offset < size_int) && flag2; offset=offset+1)
                 if (allocated[index-offset])
                     flag2 = 0;
            if (flag2) begin // if memory block is free
                start = index;
                flag1 = 0; // exit loop
            end
        end

        // mark as allocated
        for (i=0; i<size; i=i+1)
            allocated[start-offset] = 1;

        mutex = 0; // release mutex
    endtask

    task freealloc;
        output reg [WORD_SIZE-1:0] size;
        output reg [WORD_SIZE-1:0] start;

        while (mutex) begin end // wait on mutex
        mutex = 1; // acquire mutex

        // deallocate locations
        for (index=start; index > 0; index=index-1)
            allocated[index] = 0;

        mutex = 0; // release mutex
    endtask

    // internal registers
    unsigned integer start; // start address
    unsigned integer size; // block size
    unsigned integer address_int; // address register converted to int

    initial begin
        // allocate memory
        size = ioreg;
        malloc(size, start);
    end

    always @(posedge(read_en)) begin
        // read memory into ioreg
        address_int = address;
        ioreg[WORD_SIZE-1:0] = dynmem[8*(start+address_int)-1 -:WORD_SIZE-1];
    end

    always @(posedge(write_en)) begin
        // write memory from ioreg
        address_int = address;
        dynmem[8*(start+address_int)-1 -:WORD_SIZE-1] = ioreg[WORD_SIZE-1:0];
    end

    always @(posedge(realloc_en)) begin
        unsigned integer ioreg_int = ioreg; // convert ioreg to integer
        reg [WORD_SIZE-1:0] new_start; // new start address

        if (ioreg_int != 0) begin // if memory is to be reallocated, not freed
            malloc(ioreg, new_start); // allocated new memory
            // copy memory
            for (i=0; i<size; i=i+1)
                dynmem[8*(new_start+i)-1 -:WORD_SIZE-1] = dynmem[8*(start+i)-1 -:WORD_SIZE-1];
        end

        freealloc(size, start); // free previous memory
        // update registers
        size = ioreg_int;
        start = new_start;
    end
endmodule

dynmem_test.v:

module testmodule();
    $monitor ("%g ioreg1=%b ioreg2=%b",
      $time, ioreg1, ioreg2);
    reg [WORD_SIZE-1:0] address1, address2;
    reg [WORD_SIZE-1:0] ioreg1=5, ioreg2=10;
    reg read_en1, read_en2;
    reg write_en1, write_en2;
    reg realloc_en1, realloc_en2;
 #1 dynreg dr1(address1, ioreg1, read_en1, write_en1, realloc_en1);
 #1 dynreg dr2(address2, ioreg2, read_en2, write_en2, realloc_en2);
    address1 = 0;
    ioreg1 = 23;
 #1 write_en1 = 1;
    write_en1 = 0;
    address1 = 2;
    ioreg1 = 53;
 #1 write_en1 = 1;
    write_en1 = 0;
    address1 = 0;
 #1 read_en1 = 1;
    read_en1 = 0;
    address1 = 2;
 #1 read_en1 = 1;
    read_en1 = 0;
 #1 $finish;    
endmodule

ОБНОВЛЕНИЕ: C:\iverilog \ lib \ verilog-10.1.1 не существует, и, фактически, я искал в C:\iverilog файл pform.cc и не нашел результатов. Странный.

1 ответ

Решение
#1 dynreg dr1(address1, ioreg1, read_en1, write_en1, realloc_en1);

Используя задержку (#1) в объявлении экземпляра, вероятно, сбивает с толку Икара так же, как и меня. (Что именно должно быть отложено? Не существует ли экземпляр для одного шага моделирования?)

Удалите эти задержки и поместите весь код в своем тестовом стенде после этих двух объявлений экземпляров в initial блок.

Для чего это стоит, dynreg вероятно не синтезируется как написано. Он не имеет тактового входа и содержит несколько циклов, которые нельзя развернуть аппаратно.

ОБНОВЛЕНИЕ: C:\iverilog\lib\verilog-10.1.1 не существует, и, фактически, я искал в C: \ iverilog файл pform.cc и не нашел результатов. Странный.

Этот путь, вероятно, относится к расположению кода на компьютере разработчика, где была скомпилирована ваша копия Icarus. Если вы не планируете попытаться исправить ошибку, которая вызвала этот сбой самостоятельно, вы можете смело игнорировать это.

Другие вопросы по тегам