Перейти к содержанию

    

объявление и передача в другой модуль полей регистра на Verilog

Уважаемые плисоводы! Не могу найти информацию и/или доступные примеры, помогите, пожалуйста со следующей задачей.

Имеется модуль, в котором объявлены 32-разрядные регистры некоторого устройства, например, 2 регистра: reg_control и reg_status. Кроме модуля, в котором эти регистры объявлены, имеется второй модуль, в котором они используются. И вот чего я не могу понять: как объявить конкретные поля под конкретные значения в одном модуле и потом передать эти поля как часть регистра в другой модуль?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Уважаемые плисоводы! Не могу найти информацию и/или доступные примеры, помогите, пожалуйста со следующей задачей.

Имеется модуль, в котором объявлены 32-разрядные регистры некоторого устройства, например, 2 регистра: reg_control и reg_status. Кроме модуля, в котором эти регистры объявлены, имеется второй модуль, в котором они используются. И вот чего я не могу понять: как объявить конкретные поля под конкретные значения в одном модуле и потом передать эти поля как часть регистра в другой модуль?

 

На SV можно было бы объявить регистры как структуры с нужными полями, далее структуры передавать через порты модулей.

Или даже структуру поместить в интерфейс, тогда и поля регистров и другие сигналы можно было бы передавать через порты модулей одной строкой (удобно и красиво).

 

На проcто V можно подразумевать такой же подход, но реализовывать через reg и в явном виде передавать через порты модулей.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
На 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)" ?

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
у меня просто 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 и т.д. делаете выходными портами первого модуля и подаете на

входные порты второго модуля. Продумайте только имена портов, где вход где выход, что бы не запутаться.

По другому никак.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
На SV можно было бы объявить регистры как структуры с нужными полями, далее структуры передавать через порты модулей.

Или даже структуру поместить в интерфейс, тогда и поля регистров и другие сигналы можно было бы передавать через порты модулей одной строкой (удобно и красиво).

Очень интересный вопрос кстати, по использованию SV и интерфейсов - исключительно удобно для дизайна! Если бы не одно НО. Когда проектируется эсик, то уже после закачки RTL в тул синтеза (DC/Genus), на дженерик уровне все эти интерфейсы флатуются, преобразовывая имена во что то неудобоваримое. Результирующий нетлист (verilog де-факто) так же содержит только расфлатованные интерфейсы, в которых тяжело найти исходные сигналы. Получается, кодить то на SV - красивее и проще, а вот писать констрейнты и, главное, дебажить потом - боль жуткая. Агитирую коллег поменьше увлекаться SV, особенно на верхнем уровне иерархии. Ситуация изменится только когда пост-синтез/пост-лейаут нетлист можно будет сохранять в формате SV. Подозреваю, будет это не скоро.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Ну вот ваши 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;

 

Очень интересный вопрос кстати, по использованию SV и интерфейсов - исключительно удобно для дизайна! Если бы не одно НО. Когда проектируется эсик, то уже после закачки RTL в тул синтеза (DC/Genus), на дженерик уровне все эти интерфейсы флатуются, преобразовывая имена во что то неудобоваримое. Результирующий нетлист (verilog де-факто) так же содержит только расфлатованные интерфейсы, в которых тяжело найти исходные сигналы. Получается, кодить то на SV - красивее и проще, а вот писать констрейнты и, главное, дебажить потом - боль жуткая. Агитирую коллег поменьше увлекаться SV, особенно на верхнем уровне иерархии. Ситуация изменится только когда пост-синтез/пост-лейаут нетлист можно будет сохранять в формате SV. Подозреваю, будет это не скоро.

 

 

:wacko: с ума сойти. Не использую пока ни SV, ни интерфейсов - не доросла.

 

А кстати, обязательно ли имена полей должны совпадать с именами портов?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Кроме модуля, в котором эти регистры объявлены, имеется второй модуль, в котором они используются. И вот чего я не могу понять: как объявить конкретные поля под конкретные значения в одном модуле и потом передать эти поля как часть регистра в другой модуль?

Я обычно сохраняю регистры, но не пользуюсь численными значениями в объявлении полей. Вместо хард литералов я использую макро. С помощью макро разбиваю регистры на рабочие вектора.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Очень интересный вопрос кстати, по использованию SV и интерфейсов - исключительно удобно для дизайна! Если бы не одно НО. Когда проектируется эсик, то уже после закачки RTL в тул синтеза (DC/Genus), на дженерик уровне все эти интерфейсы флатуются, преобразовывая имена во что то неудобоваримое. Результирующий нетлист (verilog де-факто) так же содержит только расфлатованные интерфейсы, в которых тяжело найти исходные сигналы. Получается, кодить то на SV - красивее и проще, а вот писать констрейнты и, главное, дебажить потом - боль жуткая. Агитирую коллег поменьше увлекаться SV, особенно на верхнем уровне иерархии. Ситуация изменится только когда пост-синтез/пост-лейаут нетлист можно будет сохранять в формате SV. Подозреваю, будет это не скоро.

Для FPGA маршрута (синтезаторов) тоже самое.

В целом ни чего сложного, простое правило - в файле верхнего уровня использовать "плоский" список портов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Я обычно сохраняю регистры, но не пользуюсь численными значениями в объявлении полей. Вместо хард литералов я использую макро. С помощью макро разбиваю регистры на рабочие вектора.

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

....

а оказывается, можно в заголовке и поля так задавать, здорово, только я пока не уверена, за что какие поля у меня будут отвечать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
а оказывается, можно в заголовке и поля так задавать, здорово

Почему нет? Макроопределение - это просто текстовая замена. т.е.:

`define MACRO (EXPRESSION)

 

приведёт к тому, что все вхождения `MACRO будут заменены на (EXPRESSION).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

 

Пишите так:

 

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

 

да, видела такой стиль (когда читала книгу В.В. Соловьева по основам проектирования на верилог). Так лаконичней, согласна, но мне милей все отдельно обозначать.

 

Почему нет? Макроопределение - это просто текстовая замена. т.е.:

`define MACRO (EXPRESSION)

 

приведёт к тому, что все вхождения `MACRO будут заменены на (EXPRESSION).

 

Спасибо, не додумалась :) буду иметь ввиду.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Так лаконичней, согласна, но мне милей все отдельно обозначать.

Двойная работа - бессмысленная. И wire писать необязательно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти
Авторизация