|
|
|
объявление и передача в другой модуль полей регистра на Verilog |
|
|
|
Nov 13 2017, 08:33
|
Группа: Участник
Сообщений: 5
Регистрация: 10-11-17
Из: Москва
Пользователь №: 100 139
|
Уважаемые плисоводы! Не могу найти информацию и/или доступные примеры, помогите, пожалуйста со следующей задачей. Имеется модуль, в котором объявлены 32-разрядные регистры некоторого устройства, например, 2 регистра: reg_control и reg_status. Кроме модуля, в котором эти регистры объявлены, имеется второй модуль, в котором они используются. И вот чего я не могу понять: как объявить конкретные поля под конкретные значения в одном модуле и потом передать эти поля как часть регистра в другой модуль?
|
|
|
|
|
Nov 13 2017, 08:52
|
Местный
Группа: Свой
Сообщений: 377
Регистрация: 23-12-06
Из: Зеленоград
Пользователь №: 23 811
|
Цитата(Jul'etta @ Nov 13 2017, 11:33) Уважаемые плисоводы! Не могу найти информацию и/или доступные примеры, помогите, пожалуйста со следующей задачей. Имеется модуль, в котором объявлены 32-разрядные регистры некоторого устройства, например, 2 регистра: reg_control и reg_status. Кроме модуля, в котором эти регистры объявлены, имеется второй модуль, в котором они используются. И вот чего я не могу понять: как объявить конкретные поля под конкретные значения в одном модуле и потом передать эти поля как часть регистра в другой модуль? На SV можно было бы объявить регистры как структуры с нужными полями, далее структуры передавать через порты модулей. Или даже структуру поместить в интерфейс, тогда и поля регистров и другие сигналы можно было бы передавать через порты модулей одной строкой (удобно и красиво). На проcто V можно подразумевать такой же подход, но реализовывать через reg и в явном виде передавать через порты модулей.
|
|
|
|
|
Nov 13 2017, 09:07
|
Группа: Участник
Сообщений: 5
Регистрация: 10-11-17
Из: Москва
Пользователь №: 100 139
|
Цитата(Mad_max @ Nov 13 2017, 08:52) На SV можно было бы объявить регистры как структуры с нужными полями, далее структуры передавать через порты модулей. Или даже структуру поместить в интерфейс, тогда и поля регистров и другие сигналы можно было бы передавать через порты модулей одной строкой (удобно и красиво).
На проcто V можно подразумевать такой же подход, но реализовывать через reg и в явном виде передавать через порты модулей. у меня просто Verilog. Вот как я объявила поля регистров в первом модуле (на примере регистра status): // Reg Status assign stts_overflow_fifo = Reg_Status_r[31:25]; assign stts_op_code = Reg_Status_r[24:17]; assign stts_status = Reg_Status_r[16:9]; assign stts_add_inf = Reg_Status_r[8:0]; Я не поняла Ваше объяснение про передачу в другой модуль. Синтаксис как ".port_name(signal)" ?
|
|
|
|
|
Nov 13 2017, 09:13
|
Местный
Группа: Свой
Сообщений: 377
Регистрация: 23-12-06
Из: Зеленоград
Пользователь №: 23 811
|
Цитата(Jul'etta @ Nov 13 2017, 12:07) у меня просто Verilog. Вот как я объявила поля регистров в первом модуле (на примере регистра status):
// Reg Status assign stts_overflow_fifo = Reg_Status_r[31:25]; assign stts_op_code = Reg_Status_r[24:17]; assign stts_status = Reg_Status_r[16:9]; assign stts_add_inf = Reg_Status_r[8:0];
Я не поняла Ваше объяснение про передачу в другой модуль. Синтаксис как ".port_name(signal)" ? Ну вот ваши stts_overflow_fifo, stts_op_code и т.д. делаете выходными портами первого модуля и подаете на входные порты второго модуля. Продумайте только имена портов, где вход где выход, что бы не запутаться. По другому никак.
|
|
|
|
|
Nov 13 2017, 09:29
|
Знающий
Группа: Свой
Сообщений: 680
Регистрация: 11-02-08
Из: Msk
Пользователь №: 34 950
|
Цитата(Mad_max @ Nov 13 2017, 11:52) На SV можно было бы объявить регистры как структуры с нужными полями, далее структуры передавать через порты модулей. Или даже структуру поместить в интерфейс, тогда и поля регистров и другие сигналы можно было бы передавать через порты модулей одной строкой (удобно и красиво). Очень интересный вопрос кстати, по использованию SV и интерфейсов - исключительно удобно для дизайна! Если бы не одно НО. Когда проектируется эсик, то уже после закачки RTL в тул синтеза (DC/Genus), на дженерик уровне все эти интерфейсы флатуются, преобразовывая имена во что то неудобоваримое. Результирующий нетлист (verilog де-факто) так же содержит только расфлатованные интерфейсы, в которых тяжело найти исходные сигналы. Получается, кодить то на SV - красивее и проще, а вот писать констрейнты и, главное, дебажить потом - боль жуткая. Агитирую коллег поменьше увлекаться SV, особенно на верхнем уровне иерархии. Ситуация изменится только когда пост-синтез/пост-лейаут нетлист можно будет сохранять в формате SV. Подозреваю, будет это не скоро.
|
|
|
|
|
Nov 13 2017, 09:40
|
Группа: Участник
Сообщений: 5
Регистрация: 10-11-17
Из: Москва
Пользователь №: 100 139
|
Цитата(Mad_max @ Nov 13 2017, 09:13) Ну вот ваши stts_overflow_fifo, stts_op_code и т.д. делаете выходными портами первого модуля и подаете на входные порты второго модуля. Продумайте только имена портов, где вход где выход, что бы не запутаться. По другому никак. Ааа, вот кажется теперь поняла. Посмотрите, пожалуйста, верно ли // first module`include "Corr_Header.v" module sm_registers (clk, rst, stts_overflow_fifo_o, stts_op_code_o, stts_status_o, stts_add_inf_o ); input clk, rst; output stts_overflow_fifo_o; output stts_op_code_o; output stts_status_o; output stts_add_inf_o; assign stts_overflow_fifo = Reg_Status_r[31:25]; assign stts_op_code = Reg_Status_r[24:17]; assign stts_status = Reg_Status_r[16:9]; assign stts_add_inf = Reg_Status_r[8:0]; // second module`include "Corr_Header.v" module SM_Read (clk, rst, stts_overflow_fifo_i, stts_op_code_i, stts_status_i, stts_add_inf_i ); input clk, rst; input stts_overflow_fifo_i; input stts_op_code_i; input stts_status_i; input stts_add_inf_i; Цитата(Shivers @ Nov 13 2017, 09:29) Очень интересный вопрос кстати, по использованию SV и интерфейсов - исключительно удобно для дизайна! Если бы не одно НО. Когда проектируется эсик, то уже после закачки RTL в тул синтеза (DC/Genus), на дженерик уровне все эти интерфейсы флатуются, преобразовывая имена во что то неудобоваримое. Результирующий нетлист (verilog де-факто) так же содержит только расфлатованные интерфейсы, в которых тяжело найти исходные сигналы. Получается, кодить то на SV - красивее и проще, а вот писать констрейнты и, главное, дебажить потом - боль жуткая. Агитирую коллег поменьше увлекаться SV, особенно на верхнем уровне иерархии. Ситуация изменится только когда пост-синтез/пост-лейаут нетлист можно будет сохранять в формате SV. Подозреваю, будет это не скоро. с ума сойти. Не использую пока ни SV, ни интерфейсов - не доросла. А кстати, обязательно ли имена полей должны совпадать с именами портов?
|
|
|
|
|
Nov 13 2017, 09:57
|
Знающий
Группа: Участник
Сообщений: 916
Регистрация: 3-10-08
Из: Москва
Пользователь №: 40 664
|
Цитата Кроме модуля, в котором эти регистры объявлены, имеется второй модуль, в котором они используются. И вот чего я не могу понять: как объявить конкретные поля под конкретные значения в одном модуле и потом передать эти поля как часть регистра в другой модуль? Я обычно сохраняю регистры, но не пользуюсь численными значениями в объявлении полей. Вместо хард литералов я использую макро. С помощью макро разбиваю регистры на рабочие вектора. Код assign stts_overflow_fifo = Reg_Status_r[31:25]; assign stts_op_code = Reg_Status_r[24:17]; assign stts_status = Reg_Status_r[16:9]; assign stts_add_inf = Reg_Status_r[8:0] Превращается в: Код assign stts_overflow_fifo = Reg_Status_r[`OVERFLOW_FIFO_HI:`OVERFLOW_FIFO_LO]; assign stts_op_code = Reg_Status_r[`OPCODE_HI:`OPCODE_LO]; assign stts_status = Reg_Status_r[`STATUS_HI:`STATUS_LO]; assign stts_add_inf = Reg_Status_r[`ADD_INTF_HI:`ADD_INTF_LO] Естественно, данная операция осуществляется во всех модулях, где регистр (Reg_Status_r) используется данным образом. Как вариант можно использовать "опорный" бит и ширину поля. Ну или второй вариант, уже предложенный здесь - в модуле, куда нужно передать сигналы, в качестве входов/выходов задать сразу нужные наименования и ширины векторов. Цитата Агитирую коллег поменьше увлекаться SV Поддерживаю. По этой же причине я предпочитаю писать Gate-Level везде, где это возможно, поскольку так Netlist остаётся похожим на RTL-код, в отличие от бихевиорального описания. Цитата Посмотрите, пожалуйста, верно ли Ширину векторов забыли указать при определении. Цитата А кстати, обязательно ли имена полей должны совпадать с именами портов? Нет. Компилятору нужно лишь точно заданное соответствие подключений. Имена переменных - это для вас и для тех, кто будет с вашим кодом работать.
Сообщение отредактировал one_eight_seven - Nov 13 2017, 09:50
|
|
|
|
|
Nov 13 2017, 10:31
|
Местный
Группа: Свой
Сообщений: 377
Регистрация: 23-12-06
Из: Зеленоград
Пользователь №: 23 811
|
Цитата(Shivers @ Nov 13 2017, 12:29) Очень интересный вопрос кстати, по использованию SV и интерфейсов - исключительно удобно для дизайна! Если бы не одно НО. Когда проектируется эсик, то уже после закачки RTL в тул синтеза (DC/Genus), на дженерик уровне все эти интерфейсы флатуются, преобразовывая имена во что то неудобоваримое. Результирующий нетлист (verilog де-факто) так же содержит только расфлатованные интерфейсы, в которых тяжело найти исходные сигналы. Получается, кодить то на SV - красивее и проще, а вот писать констрейнты и, главное, дебажить потом - боль жуткая. Агитирую коллег поменьше увлекаться SV, особенно на верхнем уровне иерархии. Ситуация изменится только когда пост-синтез/пост-лейаут нетлист можно будет сохранять в формате SV. Подозреваю, будет это не скоро. Для FPGA маршрута (синтезаторов) тоже самое. В целом ни чего сложного, простое правило - в файле верхнего уровня использовать "плоский" список портов.
|
|
|
|
|
Nov 13 2017, 10:32
|
Группа: Участник
Сообщений: 5
Регистрация: 10-11-17
Из: Москва
Пользователь №: 100 139
|
Цитата(one_eight_seven @ Nov 13 2017, 09:57) Я обычно сохраняю регистры, но не пользуюсь численными значениями в объявлении полей. Вместо хард литералов я использую макро. С помощью макро разбиваю регистры на рабочие вектора. Код assign stts_overflow_fifo = Reg_Status_r[31:25]; assign stts_op_code = Reg_Status_r[24:17]; assign stts_status = Reg_Status_r[16:9]; assign stts_add_inf = Reg_Status_r[8:0] Превращается в: Код assign stts_overflow_fifo = Reg_Status_r[`OVERFLOW_FIFO_HI:`OVERFLOW_FIFO_LO]; assign stts_op_code = Reg_Status_r[`OPCODE_HI:`OPCODE_LO]; assign stts_status = Reg_Status_r[`STATUS_HI:`STATUS_LO]; assign stts_add_inf = Reg_Status_r[`ADD_INTF_HI:`ADD_INTF_LO] Естественно, данная операция осуществляется во всех модулях, где регистр (Reg_Status_r) используется данным образом. Как вариант можно использовать "опорный" бит и ширину поля. Ну или второй вариант, уже предложенный здесь - в модуле, куда нужно передать сигналы, в качестве входов/выходов задать сразу нужные наименования и ширины векторов. Поддерживаю. По этой же причине я предпочитаю писать Gate-Level везде, где это возможно, поскольку так Netlist остаётся похожим на RTL-код, в отличие от бихевиорального описания. Ширину векторов забыли указать при определении. Нет. Компилятору нужно лишь точно заданное соответствие подключений. Имена переменных - это для вас и для тех, кто будет с вашим кодом работать. Ага, а уже в заголовке объявляете через 'define ? просто я так сделала с самими названиями регистров: 'define reg_control 14'h000 'define reg_status 14'h004 .... а оказывается, можно в заголовке и поля так задавать, здорово, только я пока не уверена, за что какие поля у меня будут отвечать.
|
|
|
|
|
Nov 13 2017, 10:36
|
Местный
Группа: Свой
Сообщений: 278
Регистрация: 18-01-05
Из: Санкт-Петербург
Пользователь №: 2 031
|
Цитата reg_control и reg_status Код wire control; wire status;
module first_module( output wire control, output wire status ); assign control = 1'b1; assign status = 1'b0; endmodule
module second_module( input wire control, input wire status );
endmodule
first_module FIRST(.control, .status); second_module SECOND(.control, .status); Цитата `include "Corr_Header.v"
module sm_registers (clk, rst, stts_overflow_fifo_o, stts_op_code_o, stts_status_o, stts_add_inf_o );
input clk, rst;
output stts_overflow_fifo_o; output stts_op_code_o; output stts_status_o; output stts_add_inf_o; Не надо пожалуйста писать так. Пишите так: Код module sm_registers ( input wire clk, input wire rst, output wire stts_overflow_fifo_o, output wire stts_op_code_o, output wire stts_status_o, output wire stts_add_inf_o ); Цитата output stts_overflow_fifo_o; assign stts_overflow_fifo = Reg_Status_r[31:25]; Как уже писали выше надо stts_overflow_fifo_o привести к виду wire [5:0]stts_overflow_fifo и определить RegStatus_r
|
|
|
|
|
Nov 13 2017, 10:41
|
Знающий
Группа: Участник
Сообщений: 916
Регистрация: 3-10-08
Из: Москва
Пользователь №: 40 664
|
Цитата а оказывается, можно в заголовке и поля так задавать, здорово Почему нет? Макроопределение - это просто текстовая замена. т.е.: `define MACRO (EXPRESSION) приведёт к тому, что все вхождения `MACRO будут заменены на (EXPRESSION).
|
|
|
|
|
Nov 13 2017, 11:02
|
Группа: Участник
Сообщений: 5
Регистрация: 10-11-17
Из: Москва
Пользователь №: 100 139
|
Пишите так: Код module sm_registers ( input wire clk, input wire rst, output wire stts_overflow_fifo_o, output wire stts_op_code_o, output wire stts_status_o, output wire stts_add_inf_o ); Как уже писали выше надо stts_overflow_fifo_o привести к виду wire [5:0]stts_overflow_fifo и определить RegStatus_r [/quote] да, видела такой стиль (когда читала книгу В.В. Соловьева по основам проектирования на верилог). Так лаконичней, согласна, но мне милей все отдельно обозначать. Цитата(one_eight_seven @ Nov 13 2017, 11:41) Почему нет? Макроопределение - это просто текстовая замена. т.е.: `define MACRO (EXPRESSION)
приведёт к тому, что все вхождения `MACRO будут заменены на (EXPRESSION). Спасибо, не додумалась буду иметь ввиду.
|
|
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|