#verilog #system-verilog
#verilog #system-verilog
Вопрос:
Я пытаюсь понять, как должны быть определены контакты в SystemVerilog.
У меня есть:
- общий
dataBus
ramController
модуль, который может отправлять или получать данные на своихioData
выводах.- модуль верхнего уровня, который может записывать в
ramController
(например, подготовить буфер отображения) - a
vgaController
, который в основном получает данные изramController
, но также имеет командный режим, который позволяет настраивать его с использованием данных наdataBus
ioData
Контакты в ramController
являются двунаправленными, но также должны быть в трех состояниях, чтобы ramController
их можно было «отключить от шины», когда dataBus
используется для отправки команд на vgaController
module RAMController(
inout wire[15 : 0 ] ioData,
..
);
..
logic [15 : 0 ] ioDataCopy;
assign ioData = ( chipSelect ) ? ioDataCopy : 16'hzzzzzzzzzzzzzzzz;
Даже если vgaController никогда не выполняет запись в шину данных, должны ли его контакты быть inout для ввода или HiZ?
module VGAController(
inout wire [15 : 0 ] iData;
);
..
logic [15 : 0 ] iDataCopy = 0;
assign iData = ( chipSelect ) ? iDataCopy : 16'bzzzzzzzzzzzzzzzz;
Это dataBus
просто набор проводных значений в верхнем модуле?
module Top(
..
);
..
wire [15 : 0 ] dataBus;
Возможно, я делаю это совершенно неправильно. Может кто-нибудь, пожалуйста, помочь мне в определении системы, содержащей несколько модулей, которые используют одну и ту же шину.
Ответ №1:
Трудно сказать, правильно вы это сделали или нет, без воспроизводимого примера. Однако некоторые из ваших утверждений в основном верны. Я предполагаю, что ваш dataBus
такой же, как и ваш ioData
на уровне контроллера. В этом случае, если оба контроллера созданы в «top» и подключены правильно, у вас все должно быть готово. Вы должны убедиться, что для шины всегда есть только один драйвер, чтобы ‘ChipSelect’ предотвращал многократное управление шиной.
Итак, вот пример, демонстрирующий вышесказанное.
module Top();
wire [15 : 0 ] dataBus;
logic[1:0] select;
RAMController rc(.ioData(dataBus), .chipSelect(select == 1 ? 1 : 0));
VGAController vc(.ioData(dataBus), .chipSelect(select == 2 ? 1 : 0));
always @*
$display("%0t select: %b, data: %b", $time, select, dataBus);
initial begin
select = 0;
#1 select = 1;
#1 select = 0;
#1 select = 2;
#1 select = 0;
#1 $finish;
end
endmodule
module RAMController(
inout wire[15 : 0 ] ioData,
input logic chipSelect
//...
);
logic [15 : 0 ] ioDataCopy = 1;
assign ioData = ( chipSelect ) ? ioDataCopy : 'z;
endmodule
module VGAController(
inout wire[15 : 0 ] ioData,
input logic chipSelect
//...
);
logic [15 : 0 ] ioDataCopy = 2;
assign ioData = ( chipSelect ) ? ioDataCopy : 'z;
endmodule
и результат:
0 select: 00, data: xxxxxxxxxxxxxxxx
0 select: 00, data: zzzzzzzzzzzzzzzz
1 select: 01, data: zzzzzzzzzzzzzzzz
1 select: 01, data: 0000000000000001
2 select: 00, data: 0000000000000001
2 select: 00, data: zzzzzzzzzzzzzzzz
3 select: 10, data: zzzzzzzzzzzzzzzz
3 select: 10, data: 0000000000000010
4 select: 00, data: 0000000000000010
4 select: 00, data: zzzzzzzzzzzzzzzz
Чтобы быть более подробным, вы могли бы использовать tri
определение вместо wire
. Между ними нет разницы, но делает код более читаемым, ИМХО.
tri [15:0] dataBus;
...
tri [15:0] ioData;
Комментарии:
1. Спасибо @Serge. Я постараюсь закрыть свой проект и, возможно, обновить свой вопрос. Я получаю «Top», который должен указывать на вывод уровня, но сейчас не управляет <ничего>». Трудно найти время, чтобы сосредоточиться на этом и вне работы:-( Я определенно предпочитаю определение tri — это намного понятнее.