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

Параметризованный мультиплексор на Verilog

Вот, скажем, мультиплексор:

 

module MBusMux4 #(parameter P_Width = 1)
(
    input      [P_Width-1:0] in0,
    input      [P_Width-1:0] in1,
    input      [P_Width-1:0] in2,
    input      [P_Width-1:0] in3,
    output reg [P_Width-1:0] out,
    
    input [1:0] sel
);
         
    always @*
    begin
        case(sel)
            0: out = in0;
            1: out = in1;
            2: out = in2;
            3: out = in3;
        endcase 
    end

endmodule

 

переключает 4 шины, размерность шины задается параметром. Но иногда надо не только ширину шины задавать, но и их количество (в данном случае их 4, но нужно сделать так, чтоб можно было задавать параметром). Вопрос: как сделать такой мультиплекор?

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


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

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

 

 

но если уж так хочется "параметризации", то написать автогенерилку модулей mux_02..mux_nn (статически находящихся в бибилиотеке проекта), а в верхнем модуле иерархии через `define custom_mux mux_N задавать нужный примитив.

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


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

Вот, скажем, мультиплексор:

 

module MBusMux4 #(parameter P_Width = 1)
(
    input      [P_Width-1:0] in0,
    input      [P_Width-1:0] in1,
    input      [P_Width-1:0] in2,
    input      [P_Width-1:0] in3,
    output reg [P_Width-1:0] out,
    
    input [1:0] sel
);
         
    always @*
    begin
        case(sel)
            0: out = in0;
            1: out = in1;
            2: out = in2;
            3: out = in3;
        endcase 
    end

endmodule

 

переключает 4 шины, размерность шины задается параметром. Но иногда надо не только ширину шины задавать, но и их количество (в данном случае их 4, но нужно сделать так, чтоб можно было задавать параметром). Вопрос: как сделать такой мультиплекор?

 

А почему бы не так:

 

module MBusMux4 #(parameter P_Width = 1, B_Count = 4, Sel_Bus_Width = 2)
(
    input      [P_Width-1:0] in[B_Count - 1: 0],
    output  [P_Width-1:0] out,
    
    input [Sel_Bus_Width - 1:0] sel
);
         
assign out = in[sel];

endmodule

 

Я примерно такое в Квартусе делал - кушало даже без предупреждений.

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


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

А почему бы не так:

 

module MBusMux4 #(parameter P_Width = 1, B_Count = 4, Sel_Bus_Width = 2)
(
    input      [P_Width-1:0] in[B_Count - 1: 0],
    output  [P_Width-1:0] out,
    
    input [Sel_Bus_Width - 1:0] sel
);
         
assign out = in[sel];

endmodule

 

Я примерно такое в Квартусе делал - кушало даже без предупреждений.

+1

и предупреждений никаких не должно быть - индексирование в массиве операция синтезируемая

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


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

Приветствую!

 

 

Была у меня такая проблема при построении дерева сумматоров на verilog.

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

 

 

...

parameter WidthIn=8;

parameter NumIn=4;

 

input [WidthIn*NumIn-1:0];

..

 

Успехов Rob!

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


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

Все так и есть Rob. А все что выше, так это или графический редактор поддерживает. Ну и наверно sverilog

 

module mux_generate
#(parameter P_Width = 4,
  parameter P_Size = 4)
(
input       [sel_width-1:0] sel,
input  [P_Width*P_Size-1:0] data,
output        [P_Width-1:0] out
);


localparam  sel_width = clog2(P_Size);


wire [P_Width-1:0] r [P_Size-1:0];
///////////////////////////////////////////////////////////////////////////////////////////
function integer clog2 (input integer num); // this function calculates ceil(log2(num))
integer j;

begin    
    num = num - 1;
    for (j = 0; num > 0; j = j + 1)        
        num = num >> 1;
clog2 = j;
end
endfunction
//////////////////////////////////////////////////////////////////////////////////
genvar j;
generate for(j=0; j<P_Size; j=j+1 ) 
begin : block_a
assign r[j] = data[(j+1)*P_Width-1:j*P_Width];
end
endgenerate

assign out = r[sel];

endmodule

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


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

module MBusMux4 #(parameter P_Width = 1, B_Count = 4, Sel_Bus_Width = 2)
(
    input      [P_Width-1:0] in[B_Count - 1: 0],
    output  [P_Width-1:0] out,
    
    input [Sel_Bus_Width - 1:0] sel
);
         
assign out = in[sel];

endmodule

 

в XST жалуется на строчку

>>> input [P_Width-1:0] in[b_Count - 1: 0],

 

ERROR:HDLCompilers:26 - "mux_param.v" line 5 expecting ')', found '['

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


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

в XST жалуется на строчку

>>> input [P_Width-1:0] in[b_Count - 1: 0],

 

ERROR:HDLCompilers:26 - "mux_param.v" line 5 expecting ')', found '['

попробуйте пакованный массив

input [b_Count - 1: 0] [P_Width-1:0] in,

хотя кажись Ксайлинковский компиллер вообще не поддерживает СВ, а вот альтера должна поддерживать один из вариантов (ток не помню какой -- пакованный или непакованный)

(раньше тоже пользовался жирной шиной даже для коммутаторов Н*М, но немного запарно распихивать всё по генерэйтам - всё-таки СВ намного удобнее)

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


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

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

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


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

Была у меня такая проблема при построении дерева сумматоров на verilog.

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

Вот и я пошел по тому же пути. Главное неудобство, имхо, в использовании - надо правильно конкатенацию входных шин делать (чаще всего порядок следования путал). По имени оно и нагляднее и безопаснее.

 

попробуйте пакованный массив

input [b_Count - 1: 0] [P_Width-1:0] in,

хотя кажись Ксайлинковский компиллер вообще не поддерживает СВ, а вот альтера должна поддерживать один из вариантов (ток не помню какой -- пакованный или непакованный)

Квартус в настоящее время поддерживает только одномерные пакованные массивы.

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


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

Разовью тему. Дело в том, что обсуждаемый параметризованный мультиплексор это только часть проблемы. Худо-бедно решаемая. Основная задача состоит в разработке параметризованного контроллера памяти. Собсно, с самим контроллером памяти проблем нет, вопросы возникают насчет того, как его сделать на произвольное количество клиентов.

 

В настоящее время приходится прописывать порты руками - например, три клиента, три порта, каждый из которых включает в себя шину адреса, шину данных на запись, шину данных на чтение, сигнал запроса (rqst) - занятия контроллера клиентом, сигнал разрешения (grant) - предоставление контроллера клиенту, занятость/готовность контроллера памяти на текущей операции (контроллер памяти SDRAM, там есть остановки на авторефреш и на смену страницы) и т.д. Прописывать руками неудобно- нужно порты добавлять/убавлять, арбитр править, в общем, это крайне неудобно и чревато ошибками. Хоцца наконец слепить модуль, для которого указал количество клиентов и цепляй эти клиенты единообразным способом. Тут и повторное использование упрощается, и коллегам гораздо проще и безошибочнее такую вещь юзать.

 

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

 

Даже не знаю, что и думать. Есть идеи? Кто как такие вещи делает?

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


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

Разовью тему.

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

 

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

 

Даже не знаю, что и думать. Есть идеи? Кто как такие вещи делает?

 

Я такого типа вещи обхожу таким образом. В вериложном файле пишу ключевой комментарий:

"коммутатор начинается отсюда"

 

и до

 

"заканчивается здесь"...

 

Далее в BCB пишу софт, который читает файл, ищет "от" и "до", стирает старое содержимое и вставляет новое. А в ВСВ я делаю все, что хочу. Ну и таким же способом добавляю номер версии, даты прошивок и прочее. Еще очень удобно по названиям пинов из верхнего проекта автоматически генерить все начала вериложного файла - от портов до буферов и проводов. И uсf к ним в придачу. Просто мне так проще...

Удачи!

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


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

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

по этому поводу у меня есть для вас хорошая и плохая новость. начну с хорошей:

interface FIFO_interface #(parameter number_of_subbuses=1, parameter addr_bus_width=30, parameter bank_selector_width=2, parameter burst_length=4, parameter data_width=128);

  logic [number_of_subbuses-1:0][addr_bus_width+bank_selector_width-1:0] ADDR_data_write_bundle; 
  logic [number_of_subbuses-1:0][(burst_length+1)-1:0] CMD_data_write_bundle;
  logic [number_of_subbuses-1:0]ADDR_write_op_req_bundle; 
  logic [number_of_subbuses-1:0]ADDR_write_op_gnt_bundle;
  
  logic [number_of_subbuses-1:0][data_width-1:0] DATA_OUT_data_write_bundle; 
  logic [number_of_subbuses-1:0]DATA_OUT_write_op_req_bundle; 
  logic [number_of_subbuses-1:0]DATA_OUT_write_op_gnt_bundle;
  logic [number_of_subbuses-1:0]DATA_OUT_write_op_forward_gnt_bundle;
  
  logic [number_of_subbuses-1:0][data_width-1:0] DATA_IN_data_read_bundle; 
  logic [number_of_subbuses-1:0]DATA_IN_read_op_req_bundle; 
  logic [number_of_subbuses-1:0]DATA_IN_read_op_gnt_bundle;
  logic [number_of_subbuses-1:0]DATA_IN_read_op_forward_gnt_bundle;

      modport switch_slave
                     (  input ADDR_data_write_bundle, input CMD_data_write_bundle, input ADDR_write_op_req_bundle, output ADDR_write_op_gnt_bundle,
                        input DATA_OUT_data_write_bundle, input DATA_OUT_write_op_req_bundle, output DATA_OUT_write_op_gnt_bundle, output DATA_OUT_write_op_forward_gnt_bundle,
                        output DATA_IN_data_read_bundle, input DATA_IN_read_op_req_bundle, output DATA_IN_read_op_gnt_bundle, output DATA_IN_read_op_forward_gnt_bundle
                     );
///////////////////////////!!!!!!!!!!!!! ATTENTION HERE !!!!!!!!!!!!!////////////////////////////////////////////////////////////////////////// 
genvar i;
  generate
  for (i=1; i<number_of_subbuses; i++)
    begin:subbus
      modport master (  output .ADDR_data_write(ADDR_data_write_bundle[i-1]), output .CMD_data_write(CMD_data_write_bundle[i-1]), 
                        output .ADDR_write_op_req(ADDR_write_op_req_bundle[i-1]), input .ADDR_write_op_gnt(ADDR_write_op_gnt_bundle[i-1]),
                        output .DATA_OUT_data_write(DATA_OUT_data_write_bundle[i-1]), output .DATA_OUT_write_op_req(DATA_OUT_write_op_req_bundle[i-1]), 
                        input .DATA_OUT_write_op_gnt(DATA_OUT_write_op_gnt_bundle[i-1]), input .DATA_OUT_write_op_forward_gnt(DATA_OUT_write_op_forward_gnt_bundle[i-1]),
                        input .DATA_IN_data_read(DATA_IN_data_read_bundle[i-1]), output .DATA_IN_read_op_req(DATA_IN_read_op_req_bundle[i-1]), 
                        input .DATA_IN_read_op_gnt(DATA_IN_read_op_gnt_bundle[i-1]), input .DATA_IN_read_op_forward_gnt(DATA_IN_read_op_forward_gnt_bundle[i-1])
                     );
      modport slave  (  input .ADDR_data_write(ADDR_data_write_bundle[i-1]), input .CMD_data_write(CMD_data_write_bundle[i-1]), 
                        input .ADDR_write_op_req(ADDR_write_op_req_bundle[i-1]), output .ADDR_write_op_gnt(ADDR_write_op_gnt_bundle[i-1]),
                        input .DATA_OUT_data_write(DATA_OUT_data_write_bundle[i-1]), input .DATA_OUT_write_op_req(DATA_OUT_write_op_req_bundle[i-1]), 
                        output .DATA_OUT_write_op_gnt(DATA_OUT_write_op_gnt_bundle[i-1]), output .DATA_OUT_write_op_forward_gnt(DATA_OUT_write_op_forward_gnt_bundle[i-1]),
                        output .DATA_IN_data_read(DATA_IN_data_read_bundle[i-1]), input .DATA_IN_read_op_req(DATA_IN_read_op_req_bundle[i-1]), 
                        output .DATA_IN_read_op_gnt(DATA_IN_read_op_gnt_bundle[i-1]), output .DATA_IN_read_op_forward_gnt(DATA_IN_read_op_forward_gnt_bundle[i-1])
                     );
    end
  endgenerate
endinterface

если не разберётесь что тут происходит то матчасть: IEEE Std 1800-2005 стр. 359-360 20.4.4 Modeport expressions

 

плохая новость: для того чтобы делать такое вам нужен компилятор действительно поддерживающий СистемВерилог - Альтера с таким не справиться

 

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

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


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

Я такого типа вещи обхожу таким образом. В вериложном файле пишу ключевой комментарий:

"коммутатор начинается отсюда"

 

и до

 

"заканчивается здесь"...

 

Далее в BCB пишу софт, который читает файл, ищет "от" и "до", стирает старое содержимое и вставляет новое. А в ВСВ я делаю все, что хочу. Ну и таким же способом добавляю номер версии, даты прошивок и прочее. Еще очень удобно по названиям пинов из верхнего проекта автоматически генерить все начала вериложного файла - от портов до буферов и проводов. И uсf к ним в придачу. Просто мне так проще...

Т.е. типа мегавизарда своего написать. Что ж, может и вариант. :a14:

 

по этому поводу у меня есть для вас хорошая и плохая новость. начну с хорошей:

[...]

если не разберётесь что тут происходит то матчасть: IEEE Std 1800-2005 стр. 359-360 20.4.4 Modeport expressions

 

плохая новость: для того чтобы делать такое вам нужен компилятор действительно поддерживающий СистемВерилог - Альтера с таким не справиться

Что можно сделать на СВ, не сомневался ни секунды. То, что Квартус не поддерживает генерацию в модпортах, в курсе. Из доступних синтезеров, умеющих СВ в полной мере, насколько понимаю, есть только Прецижн. К сожалению, тут есть сомнения насчет того, что он выдает адекватную по скорости генерацию (по сравнению с Квартусом) - как-то пробовал простой дизайн, что-то Прецижн там подотстал от Квартсуса и Синплифая. Может, конечно, я там что-то в настройках не прочухал, но это вряд ли - не особенно там опций много.

 

Вторая плохая новость для меня тут в том, что и используемый мною симулятор (Актив-ХДЛ) тоже не далеко не до конца поддерживает СВ (те же структуры, например, не держит), поэтому с таким инструментарием лезть в дебри СВ, имхо, глупо. А менять весь тулчейн с ходу тоже не улыбается - времени на это просто нет. Придецца лепить костыли.

 

Хм, простая, в общем-то, вещь - задать по параметру количество портов у модуля, а до сих пор в широкораспространенном языке (Верилог) не решена. Как же они с такими вещами-то до сих пор жили? Неужто руками все разруливали?

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


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

Хм, простая, в общем-то, вещь - задать по параметру количество портов у модуля, а до сих пор в широкораспространенном языке (Верилог) не решена. Как же они с такими вещами-то до сих пор жили? Неужто руками все разруливали?

да нет -- посмотрите концовку моего поста - запихивайте хоть все сигналы в одну плоскую мега-шину, а дальше генерэйтиком - регулярность то есть -- значит генерэйтовский цикл отлично подойдёт - в принципе могу даж какой-нить исходничек для примера заслать в личку (если нужно конечно)

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


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

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...