Редактировать: как кто-то указал, я сначала указал только, как установить входные сигналы, и привел в качестве примера два особых случая. Позвольте мне попытаться объяснить, как это работает. Хорошим началом для этого является ваш вопрос:
почему ~(double_req-base)?
Как кто-то указал вам, это основано на принципе пульсации заимствовать вычитатель. Когда вы вычитаете одно число из другого, независимо от используемой системы счисления, вы начинаете с самого низкого порядка и пытаетесь вычесть два числа из одного и того же порядка. В бинарном примере это будет выглядеть так:
1011 = 11
0010 - = 2 -
────── ────
1001 = 9
Как видите, 1 - 1
допустимо и дает 0
. Однако, если это невозможно, вы можете одолжить у более высокого порядкового номера. На этом изображении показан простой пример того, как это выглядит в десятичной системе. Примером в десятичной системе может быть:
1001 = 01(10)1 = 9
0010 - = 00 1 0 - = 2 -
────── ───────── ───
0111 = 01 1 1 = 7
Поскольку 0 - 1
невозможно во второй позиции, мы берем 1 из четвертой позиции, устанавливаем третью позицию в 1
и устанавливаем вторую позицию в 10
(таким образом, 2 в десятичной системе). Это очень похоже на пример в десятичной системе, который я публиковал ранее< /а>.
Важно для арбитра: следующая 1 из исходного числа (req
), видимая с позиции base
, будет установлена на ноль. Все числа между базовой позицией и этим 0
будут установлены на 1
. После инвертирования результата вычитания только эта позиция будет 1
, если смотреть из базы.
Однако числа с более низким порядком, чем основание, все еще могут быть 1
с помощью этой техники. Поэтому мы соединяем исходное число с вашим рассчитанным числом (double_req & ~(double_req-base)
). Это гарантирует, что возможные 1
на позициях ниже, чем base
, будут устранены.
Наконец, тот факт, что он удвоен, гарантирует, что у него не закончатся позиции для заимствования. Если ему нужно заимствовать из этих «вторых» удвоенных блоков, дизъюнкция (double_grant[WIDTH-1:0] | double_grant[2*WIDTH-1:WIDTH]
) гарантирует, что он возвращает правильный индекс. Я добавил пример для этого к примерам ниже.
Исходный пост
Вы можете интерпретировать base
как начальный индекс в req
. Это первый бит, который код будет рассматривать для арбитража. Вы должны установить это значение на last_arbitrated_position + 1
.
Взгляните на 4-битный (псевдокод) пример, который я создал ниже. Возьмем произвольные числа:
req = 4'b1101 // Your vector from which one position should be arbitrated
base = 4'b0010 // The second position is the first position to consider
Теперь из arbiter.v
следует следующее:
double_req = 1101 1101
double_grant = 1101 1101 & ~(1101 1011) = 1101 1101 & 0010 0100 = 0000 0100
На последних шагах arbiter.v
фактически назначает позицию, которая должна быть предоставлена:
grant = 0100 | 0000 = 0100
Это правильно, потому что мы установили вторую позицию в качестве базовой, а следующей допустимой позицией была третья. Другой пример, где базой является позиция, которая также допустима в req
:
req = 4'b1111
base = 4'b0010
double_req = 1111 1111
double_grant = 1111 1111 & ~(1111 1101) = 1111 1111 & 0000 0010 = 0000 0010
grant = 0010 | 0000
Что снова правильно, потому что в данном случае мы определили, что первая позиция, которая может быть рассмотрена в арбитраже, является второй позицией, и эта позиция действительно действительна.
Пример кода, который вы разместили, также заботится о переносе наиболее значимого бита. Это означает, что если вы установите базу, но нет действительной позиции, превышающей эту базу, она будет зациклена и начнет арбитраж с самого младшего бита. Примером для этого случая может быть:
req = 4'b0010
base = 4'b0100
double_req = 0010 0010
double_grant = 0010 0010 & ~(1110 0001) = 0010 0010 & 0001 1110 = 0010 0000
grant = 0000 | 0010
person
Silicon1602
schedule
06.03.2019