Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: ModelSim-Altera ругается на одинаковые имена в разных struct
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Среды разработки - обсуждаем САПРы
flammmable
Сделал в одном модуле несколько структур (struct) с разными именами. Внутри каждой структуры есть перечислимый тип (состояния конечного автомата). Ну и у каждой структуры есть состояние автомата IDLE. Сам Quartus собирает проект без ошибок. Но ModelSim-Altera говорит Enum literal name 'IDLE' already exists..

"Очищенный" пример:

Code.sv
Код
`timescale 1 ns/ 1 ns
module test013_LITERAL (
    input  A,
    input  B,
    output C
);
    struct{enum{IDLE,
                SOME_STAGE_1} FSM;
             logic some_register;
            } first_machine;
    struct{enum{IDLE,
                SOME_STAGE_2} FSM;
             logic some_register;
            } second_machine;            
    assign C = A ^ B;    
endmodule

testbench.vt
Код
`timescale 1 ns/ 1 ns
module testbench();
    reg test_A;
    reg test_B;
    wire test_C;
    test013_LITERAL DUT (.A(test_A),
                         .B(test_B),
                         .C(test_C));
    initial begin    
        #100
            test_A = 0;
            test_B = 0;
        #100
            test_A = 1;
            test_B = 0;    
        #100
            test_A = 0;
            test_B = 1;        
        #100
            test_A = 1;
            test_B = 1;    
    end    
endmodule

Что я делаю не так?
RobFPGA
Приветствую!
Цитата(flammmable @ Jul 11 2018, 13:42) *
Сделал в одном модуле несколько структур (struct) с разными именами. Внутри каждой структуры есть перечислимый тип (состояния конечного автомата). Ну и у каждой структуры есть состояние автомата IDLE. Сам Quartus собирает проект без ошибок. Но ModelSim-Altera говорит Enum literal name 'IDLE' already exists..
...
Что я делаю не так?
Enum в пределах одного compilation unit имеет глобальный scope то есть внутри одного модуля/package не может быть определено несколько елементов разных enum с оним и тем же именем. В разных модулях/package - на здоровье.
Quartus судя по всему на это болт кладет что чревато последствиями.
Код
...
    struct{enum{IDLE=1,
                SOME_STAGE_1} FSM;
             logic some_register;
            } first_machine;
    struct{enum{IDLE=2,
                SOME_STAGE_2} FSM;
             logic some_register;
            } second_machine;            
wire [1:0] w_idle=IDLE; ??? // что присвоит Quartus?


Удачи! Rob.
flammmable
Цитата(RobFPGA @ Jul 11 2018, 14:16) *
Приветствую!
Enum в пределах одного compilation unit имеет глобальный scope тоесть внутри одного модуля/package не может быть определено несколько елементов разных enum с оним и тем же именем. В разных модулях/package - на здоровъе.

Удачи! Rob.

Эмм. Внутри самого Quartus удается вполне успешно обращаться к одинаковым именам enum-ов в различных struct.
Типа того...
Код
first_machine.FSM <= first_machine.IDLE;
first_machine.FSM <= first_machine.SOME_STAGE_1;
second_machine.FSM <= second_machine.IDLE;
second_machine.FSM <= second_machine.SOME_STAGE_2;

И Quartus на такой синтаксис не ругается.
Т.е. не понятно:
1) если struct организует ограничение видимости, то чего хочет ModelSim?
2) если struct НЕ организует ограничение видимости, то начерта такой struct нужен?
3) если struct организует ограничение видимости, но только для переменных регистров, а для enum - нет и при этом сам Quartus ошибок не выдает, то... Я даже не знаю, то - что?

P.S. На меня Quartus ругнулся, когда я разным переменным регистрам из одного struct сделал блокирующее и неблокирующее присвоение. Он сказал "Нет уж! Или всем регистрам так, или всем регистрам эдак!". Но обсуждаемом случае никаких ошибок от Quartus не было.
RobFPGA
Приветствую!

Цитата(flammmable @ Jul 11 2018, 14:32) *
Эмм. Внутри самого Quartus удается вполне успешно обращаться к одинаковым именам enum-ов в различных struct.
Типа того...
Код
first_machine.FSM <= first_machine.IDLE;
first_machine.FSM <= first_machine.SOME_STAGE_1;
second_machine.FSM <= second_machine.IDLE;
second_machine.FSM <= second_machine.SOME_STAGE_2;
Хм странно - в структурах first_machine/second_machine нет элемента IDLE! Есть FSM который может иметь занчение IDLE. wacko.gif И ModelSim об этом ругается.
Цитата(flammmable @ Jul 11 2018, 14:32) *
И Quartus на такой синтаксис не ругается.
?! cranky.gif Печалька какая.

Цитата(flammmable @ Jul 11 2018, 14:32) *
Т.е. не понятно:
1) если struct организует ограничение видимости, то чего хочет ModelSim?
2) если struct НЕ организует ограничение видимости, то начерта такой struct нужен?
3) если struct организует ограничение видимости, но только для переменных регистров, а для enum - нет и при этом сам Quartus ошибок не выдает, то... Я даже не знаю, то - что?
Нужно учитывать что это все же не С/С++ Надо немного по другому структуировать дизайн. Вынесите объявление типов enum и структур в отдельные package. Потом в модуле их импортируйте и пользуйте на здоровье не забывая ссылаться на соотвествующий package при использовании одинаковых имен элементов enum.

Удачи! Rob
flammmable
Цитата(RobFPGA @ Jul 11 2018, 14:49) *
Надо немного по другому
- Как?
- Иначе!

©Badcomedian

Хорошо, это не C/C++. Поэтому, например, исходя из каких-то соображений элементы struct могут иметь или блокирующее или не блокирующее присвоение. Хотя такое ограничение несколько странно, но допустим дело в том, что компилятор расположит отдельные биты этих элементов рядом и... (и что дальше?) и не знаю, но допустим это как-то связано со структурой ПЛИСов. Ладно, то - такое.
Но! Как вы верно отметили "IDLE" - сугубо синтаксическая абстракция. Для нее. Надо. Просто. Сделать. Ограничение. Видимости. Потому как в противном случае ситуация следующая:
1. Есть конечный автомат как некая сущность.
2. У этого автомата есть некоторые атрибуты.
3. Эти атрибуты можно сгруппировать в struct.
4. В этот же struct можно внести и список состояний автомата.
5. Причем значения этих состояний можно получать через "имя_структуры.имя_состояния".
6.1. Но! IDLE, который есть у большинства автоматов надо вынести отдельно и обращаться к нему напрямую!
6.2. Или придумать для каждой машины свое название IDLE. Имена регистров повторяются - на здоровье. Имена состояний - ни за что!
6.3. Или атрибуты сгруппировать в struct, а состояния целиком вынести в блок параметров, хотя синтаксис позволяет enum-у находится внутри struct.
6.4. Или вообще не пользоваться struct.

Мне сложно поверить, что дело в синтаксисе SystemVerilog. Он не мог быть сделан так тупо. Я уверен - дело в каких-то настройках ModelSim и/или Quartus.
Sergey_Bekrenyov
1. Несколько конечных автоматов в одном модуле держать не рекомендуется.
2. Есть два подхода к присваиваниям - или все неблокирующие, или логика с блокирующими, триггеры с блокирующими.

Следуя набору элементарных рекомендаций можно съэкономить кучу времени.
andrew_b
Цитата(Sergey_Bekrenyov @ Jul 11 2018, 15:48) *
1. Несколько конечных автоматов в одном модуле держать не рекомендуется.
Ерунда полная.
Sergey_Bekrenyov
Цитата(andrew_b @ Jul 11 2018, 17:07) *
Ерунда полная.


CummingsSNUG2003SJ_SystemVerilogFSM.pdf

"There are a few FSM coding guidelines that apply to all FSM coding styles[2]. The common guidelines are:
Guideline: Make each FSM design a separate Verilog module.
It is easier to maintain the FSM code if each FSM is a separate module, plus third-party FSM optimization tools
work best on isolated and self-contained FSM designs"

andrew_b
Цитата(Sergey_Bekrenyov @ Jul 11 2018, 16:17) *
CummingsSNUG2003SJ_SystemVerilogFSM.pdf
Ну и что? Мало ли кто что напишет.
flammmable
Цитата(Sergey_Bekrenyov @ Jul 11 2018, 16:17) *
CummingsSNUG2003SJ_SystemVerilogFSM.pdf

Хороший документ. Хороший вариант - делать группировку при помощи модулей. Однако странно, что в этом документе нет ни одного упоминания конструкции "struct". Применяете ли вы структуры? Если да, то в каких случаях? Если нет, то как полагаете, для чего данная конструкция языка может быть нужна и нужна ли?
RobFPGA
Приветствую
Цитата(flammmable @ Jul 11 2018, 15:24) *
Хорошо, это не C/C++. Поэтому, например, исходя из каких-то соображений элементы struct могут иметь или блокирующее или не блокирующее присвоение. Хотя такое ограничение несколько странно, но допустим дело в том, что компилятор расположит отдельные биты этих элементов рядом и... (и что дальше?) и не знаю, но допустим это как-то связано со структурой ПЛИСов. Ладно, то - такое.
Это можно обсуждать видя контекст применения этой struct

Цитата(flammmable @ Jul 11 2018, 15:24) *
Но! Как вы верно отметили "IDLE" - сугубо синтаксическая абстракция. Для нее. Надо. Просто. Сделать. Ограничение. Видимости. Потому как в противном случае ситуация следующая:
Видимость enum ограниченна compilation unit - почему это так - надо спраштвать в комитете по SV.
Давайте немного поваляем коня для придания ему сферичности...
Цитата(flammmable @ Jul 11 2018, 15:24) *
1. Есть конечный автомат как некая сущность. // не спорю
2. У этого автомата есть некоторые атрибуты. // усы хвост регистр и список состояния?
3. Эти атрибуты можно сгруппировать в struct. // зачем, какой профит? в SV есть другие способы структуирования
4. В этот же struct можно внести и список состояний автомата. // но в SV пока это особо смысла не иемеет
5. Причем значения этих состояний можно получать через "имя_структуры.имя_состояния". // как Карл???
С точки зрения синтаксиса в структуре НЕТ поля с именем IDLE! Как к нему обратится? Ну и по Вашему ведь можно так написать:
Код
    struct {
        enum {IDLE=1, SOME_STAGE_1} FSM1;
        enum {IDLE=2, SOME_STAGE_2} FSM2;
        ...
        logic some_register;
    } first_machine;
И какое значение IDLE по Вашему мне выдаст some_var=first_machine.IDLE? smile3046.gif

Цитата(flammmable @ Jul 11 2018, 15:24) *
6.1. Но! IDLE, который есть у большинства автоматов надо вынести отдельно и обращаться к нему напрямую! // это кому как нравится
6.2. Или придумать для каждой машины свое название IDLE. // у меня так и есть typedef enum {ST_A_IDLE, ..} e_ST_A_t;
Имена регистров повторяются - на здоровье. Имена состояний - ни за что! // ???
6.3. Или атрибуты сгруппировать в struct, а состояния целиком вынести в блок параметров, хотя синтаксис позволяет enum-у находится внутри struct. //???
6.4. Или вообще не пользоваться struct. // ???
Или не пытать слепо тянуть шаблоны проектирования.

Цитата(flammmable @ Jul 11 2018, 15:24) *
Мне сложно поверить, что дело в синтаксисе SystemVerilog. Он не мог быть сделан так тупо. Я уверен - дело в каких-то настройках ModelSim и/или Quartus.
Вопросы веры и религии мы тут не обсуждаем sm.gif

Удачи! Rob.
Sergey_Bekrenyov
Цитата(flammmable @ Jul 11 2018, 17:38) *
Хороший документ. Хороший вариант - делать группировку при помощи модулей. Однако странно, что в этом документе нет ни одного упоминания конструкции "struct". Применяете ли вы структуры? Если да, то в каких случаях? Если нет, то как полагаете, для чего данная конструкция языка может быть нужна и нужна ли?



"2.6.2 Structures"
http://sutherland-hdl.com/papers/2013-SNUG...rilog_paper.pdf
Sergey_Bekrenyov
Цитата(andrew_b @ Jul 11 2018, 17:23) *
Ну и что? Мало ли кто что напишет.

"Ну и что? Мало ли кто что напишет."
dxp
Цитата(RobFPGA @ Jul 11 2018, 18:16) *
Enum в пределах одного compilation unit имеет глобальный scope то есть внутри одного модуля/package не может быть определено несколько елементов разных enum с оним и тем же именем. В разных модулях/package - на здоровье.

Да, вот это любопытный момент. Вроде бы struct вводит свою собственную scope, и казалось бы проблем быть не должно - все имена разделены своими областями видимости. Но в случае структур есть исключение: внутри структуры нельзя определить тип. Поэтому когда внутри структуры объявляется перечисление:

Код
struct
{
    enum int { SLON, MAMONT, ... } slon;
}
s1;


то тут возникает анонимный тип перечисления, который не может быть определён внутри структуры, поэтому этот тип неявно "мапится" на объемлющую область видимости. Теперь если в этой области видимости объявить другую структуру:

Код
struct
{
    enum int { SLON, MAMONT, ... } slon;
}
s2;


то тут история повторяется - опять возникает анонимный тип, который выносится в объемлющую область видимости, а там уже есть точно такой же тип, тоже анонимный, но это означает, что просто у этих типов нет явных имён, но сами типы существуют и имеют одинаковые сигнатуры. И вот тут-то и возникает коллизия.

Проблема, в общем, имхо, в недоделанности структур в SystemVerilog. Непонятно, почему было просто не расширить scope структур и на определения типов тоже. Это было бы логично и ничему не мешает.
flammmable
Спасибо за комментарии. Кое-что удалось выяснить.

1. Зачем вся эта тема нужна?
Вот пара примеров группировки атрибутов (при помощи модуля и при помощи структуры):

Модуль:
Код
module test013_LITERAL (
    output some_output
);
    logic reg_C;

    logic reg_A_for_submodul;//первое упоминание reg_A
    logic reg_B_for_submodul;
    logic reg_C_for_submodul;//придумать уникальное название во избежание пересечения имен
    
    submodul(.reg_A(reg_A_for_submodul),//второе и третье упоминание reg_A
             .reg_B(reg_B_for_submodul),
             .reg_C(reg_C_for_submodul));
    
    assign some_output = reg_C_for_submodul;    
endmodule


module submodul(
    input reg_A,//четвертое упоминание reg_A
    input reg_B,
    output reg_C
);
endmodule

Структура:
Код
module test013_LITERAL (
    output some_output
);
    logic reg_C;

    struct{logic reg_A;    //только одно упоминание reg_A
            logic reg_B;
            logic reg_C;//можно не опасаться пересечения имен
            } struct_example;

    assign some_output = struct_example.reg_C;    
endmodule


Вам как было бы удобней производить группировку?

2. Вопрос веры sm.gif
Некоторые полагают, что элементы enum не вызвать через точку. Другие полагают, что можно, но синтаксис SystemVerilog таков, что вынесет элементы enum во внешнюю область видимости.

Рабочий пример:
Код
module test013_LITERAL (
    output [3:0]first_literal,
    output [3:0]second_literal
);

struct{enum{SOME_LITERAL_0_FIRST,
            SOME_LITERAL_1_FIRST,
            IDLE,
            SOME_LITERAL_3_FIRST,
            SOME_LITERAL_4_FIRST} enum_reg;
        } first_struct;

struct{enum{SOME_LITERAL_0_SECOND,
            SOME_LITERAL_1_SECOND,
            SOME_LITERAL_2_SECOND,
            IDLE,
            SOME_LITERAL_4_SECOND} enum_reg;
        } second_struct;

assign first_literal     = first_struct.IDLE;
assign second_literal    = second_struct.IDLE;

endmodule

Результаты компиляции на Quartus Prime 17.1.0 для MAX-10 10M02SCE144C8G:
Info (293000): Quartus Prime Full Compilation was successful. 0 errors, 32 warnings
Результат работы прошивки на лампочках демоплаты (линейка из восьми светодиодов): 0010 0011

3. Кто что говорит.
Altera-forum - молчит.
Verification Academy от Mentor - молчит.
StackOverflow - говорит, что на одном из трех симуляторов мой код заработал. Так же там ссылаются на раздел 23.9 стандарта IEEE 1800-2017 и утверждают, что struct не создает scope (пффф, а зачем он тогда вообще нужен?), но проверить это утверждение пока не представляется возможным ввиду отсутствия у меня IEEE 1800-2017.
Мы продолжаем следить за событиями.
dxp
Цитата
struct не создает scope

struct создаёт scope - вы можете создавать объекты с одинаковыми именами в структурах, всё будет ок, struct не позволяет внутри своей scope определять тип. Когда вы объявляете объект внутри структуры, всё нормально, он живёт внутри этой области видимости, но определить тип внутри вы не можете - попробуйте написать там typedef - получите ошибку (а если нет, значит это баг тула). Когда вы определяете перечисление, вы неявно определяете его тип, и поскольку внутри структуры этот тип не может быть определён, он автоматом переносится в объемлющую область видимости со всеми вытекающими.

flammmable
Цитата(dxp @ Jul 12 2018, 15:53) *
struct создаёт scope - вы можете создавать объекты с одинаковыми именами в структурах, всё будет ок, struct не позволяет внутри своей scope определять тип. Когда вы объявляете объект внутри структуры, всё нормально, он живёт внутри этой области видимости, но определить тип внутри вы не можете - попробуйте написать там typedef - получите ошибку (а если нет, значит это баг тула). Когда вы определяете перечисление, вы неявно определяете его тип, и поскольку внутри структуры этот тип не может быть определён, он автоматом переносится в объемлющую область видимости со всеми вытекающими.

Звучит логично. Жаль. Не хотелось бы имена регистров копировать четыре раза вместо одного, используя module для группировки. Посмотрю что скажет Мегратек (и вообще) и покорюсь судьбе sm.gif
RobFPGA
Приветствую!
Цитата(flammmable @ Jul 12 2018, 14:28) *
Вот пара примеров группировки атрибутов (при помощи модуля и при помощи структуры):
...
Вам как было бы удобней производить группировку?
Простите не уловил что тут хотелось бы увидет? Какую задачу должна решать эта гуппировка? Я пытаюсь давать имена портам и сигналам чтобы хоть как то отображать их функционал. Ну и приведеные примеры функционально разные.
Мне ни кто не мешает делать так
Код
...
logic sig_AAA, sig_BBB;
   submodul i_sub (
      .reg_A(sig_AAA),
      .reg_B(sig_BBB),
      .reg_C(some_output)
   );


В свою очередь хотелось бы от Вас услышать как в таком случае будете выкручиватся вместе с Qu?
Код
struct{
  enum {IDLE=1, SOME_LITERAL_1_FIRST, SOME_LITERAL_2_FIRST} enum1_reg;
  enum {IDLE=2, SOME_LITERAL_1_SECOND, SOME_LITERAL_2_SECOND} enum2_reg;
} first_and_second_struct;
assign some_litera = first_and_second_struct.IDLE;
...


Удачи! Rob.

P.S.
Ну и для прикола - если уж так хочется в одном модуле иметь геморой одинаковые элементы в разных enum то есть способ sm.gif
Код
module test2 (input  int A, output int B,C);

generate begin : gg
    begin : g_fsm1
      enum {IDLE=3, SOME_STAGE_2} FSM;
    end
    begin : g_fsm2
      enum {IDLE=4, SOME_STAGE_2} FSM;
    end
    ...
end
endgenerate

assign B = gg.g_fsm1.IDLE;
assign C = gg.g_fsm2.IDLE;

endmodule
Только нафиг такая групировка нужна? этж скооко писанины лишней wacko.gif Да и проверять сложно если где ошибся.
flammmable
Цитата(RobFPGA @ Jul 12 2018, 16:27) *
Простите не уловил что тут хотелось бы увидеть?

Хотелось бы увидеть нормальную группировку атрибутов сущности. Хотелось бы увидеть как атрибут сущности объявляется один раз (а не один раз во внешнем модуле, один раз во внутреннем модуле и еще два раза его имя нужно написать при подключении этого модуля).

Цитата(RobFPGA @ Jul 12 2018, 16:27) *
Какую задачу должна решать эта группировка?

А какую задачу решает конструкция struct?

Цитата(RobFPGA @ Jul 12 2018, 16:27) *
В свою очередь хотелось бы от Вас услышать как в таком случае будете выкручиватся вместе с Qu?
Код
struct{
  enum {IDLE=1, SOME_LITERAL_1_FIRST, SOME_LITERAL_2_FIRST} enum1_reg;
  enum {IDLE=2, SOME_LITERAL_1_SECOND, SOME_LITERAL_2_SECOND} enum2_reg;
} first_and_second_struct;
assign some_litera = first_and_second_struct.IDLE;
...

Никак. Данный пример не соберется ни в Квартусе, ни в МоделСиме. Заглавный же пост о том, что один и тот же код одной системой считается верным, а другой системой - ошибочным. О том, что интерпретация инженерами Ментора стандарта SystemVerilog обессмысливает одну синтаксическую конструкцию. И о том, как бы побороть это зло.
RobFPGA
Приветствую!
Цитата(flammmable @ Jul 12 2018, 17:02) *
Хотелось бы увидеть нормальную группировку атрибутов сущности. Хотелось бы увидеть как атрибут сущности объявляется один раз (а не один раз во внешнем модуле, один раз во внутреннем модуле и еще два раза его имя нужно написать при подключении этого модуля).
Тю и всего то ...
Код
package fsm1_pq;
  typedef enum {IDLE=1, SOME_STAGE_1} e_FSM_t;
  typedef struct packed {
      logic some_register;
      e_FSM_t  cur_fsm;
  } st_FSM_t;
endpackage

package fsm2_pq;
  typedef enum {IDLE=2, SOME_STAGE_1} e_FSM_t;
  typedef struct packed {
      logic some_register;
      e_FSM_t  cur_fsm;
  } st_FSM_t;
endpackage

import fsm1_pq::*;
module test (input st_FSM_t A, output int B,C);
st_FSM_t fsm1;
fsm2_pq::st_FSM_t fsm2;

  assign fsm1.cur_fsm = (A.cur_fsm==fsm1_pq::e_FSM_t'(fsm2_pq::IDLE)) ? IDLE : fsm1_pq::e_FSM_t'(int'(IDLE)+1); //;)
  assign fsm2.cur_fsm = fsm2_pq::IDLE;

endmodule


Цитата(flammmable @ Jul 12 2018, 17:02) *
Никак. Данный пример не соберется ни в Квартусе, ни в МоделСиме. Заглавный же пост о том, что один и тот же код одной системой считается верным, а другой системой - ошибочным. О том, что интерпретация инженерами Ментора стандарта SystemVerilog обессмысливает одну синтаксическую конструкцию. И о том, как бы побороть это зло.
Тогда это скорее Qu чудит - так как один и тот же синтаксис то синтезирует то нет.
Удачи! Rob.
flammmable
Цитата(RobFPGA @ Jul 12 2018, 17:34) *
Тогда это скорее Qu чудит - так как один и тот же синтаксис то синтезирует то нет.

Не, Qu не синтезирует ваш пример. И ModelSim не синтезирует ваш пример. Вообще, я не очень понимаю зачем и к чему вы его написали. Пример из первого поста Qu синтезирует стабильно, так же стабильно его не синтезирует ModelSim
RobFPGA
Приветствую!
Цитата(flammmable @ Jul 12 2018, 18:40) *
Не, Qu не синтезирует ваш пример. И ModelSim не синтезирует ваш пример. Вообще, я не очень понимаю зачем и к чему вы его написали. Пример из первого поста Qu синтезирует стабильно, так же стабильно его не синтезирует ModelSim
Затем что с точки зрения синтаксиса пример #1 поста и мой одинаков! Поэтому есть неоднозначность синтеза в Qu и стабильное поведения в ModelSim. IMHO первое хуже второго.

Удачи! Rob.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.