62 / 63 · Теория
Регистровый интерфейс и момент побочных эффектов
Задайте адреса, побайтовую запись и остановку ответа, обеспечивая ровно одно изменение состояния на принятый запрос.
Уроки доступны бесплатно. Запишитесь, чтобы сохранять прогресс.
Определите действие «записать регистр»
Предварительные знания: адресный дешифраторДешифратор активирует выходную линию, соответствующую двоичному коду. При наличии enable неактивное разрешение может устанавливать все выходы в 0. Подробнее, ready/validРукопожатие (handshake) — соглашение, по которому передача подтверждается, когда valid передатчика и ready приёмника равны 1 на одном фронте. Оно также задаёт правила удержания данных во время ожидания. Подробнее, enable и приоритет обновления состояния.
Для подключения конфигурационных регистровРегистр хранит многобитное состояние. Синхронные регистры в этом курсе записывают определённый вход на фронте тактового сигнала. Подробнее к внешнему контроллеру недостаточно проверить адрес. Нужно определить приём запроса, удержание ожидающего ответа и поведение при записи по адресу только для чтения. Здесь используется простой интерфейс одного запроса и ответа в общем тактовом домене.
Адреса ниже байтовые, с 32-битным выравниванием. Каждый запрос создаёт ровно один ответ об успехе или ошибке.
| Адрес | Имя | Поведение |
|---|---|---|
| 0x0 | CONFIG | Чтение/запись с byte strobe |
| 0x4 | STATUS | Только чтение, значение в момент приёма |
| 0x8 | COMMAND | Чтение 0, запись бита 0 байта 0 создаёт start pulse |
| Прочие | Не определены | Ответ с ошибкой без изменения состояния |
Приём при пустом или освобождаемом слоте ответа
module register_interface (
input logic clk, rst,
input logic req_valid, req_write,
output logic req_ready,
input logic [3:0] req_addr,
input logic [31:0] req_wdata,
input logic [3:0] req_wstrb,
output logic rsp_valid,
input logic rsp_ready,
output logic [31:0] rsp_rdata,
output logic rsp_error,
input logic [31:0] status_value,
output logic [31:0] config_value,
output logic start_pulse
);
assign req_ready = !rsp_valid || rsp_ready;
always_ff @(posedge clk) begin
if (rst) begin
rsp_valid <= 1'b0;
config_value <= 32'd0;
start_pulse <= 1'b0;
end else begin
start_pulse <= 1'b0;
if (req_ready) begin
rsp_valid <= req_valid;
if (req_valid) begin
rsp_rdata <= 32'd0;
rsp_error <= 1'b0;
case (req_addr)
4'h0: begin
if (req_write) begin
for (int i=0; i<4; i++)
if (req_wstrb[i])
config_value[8*i +: 8]
<= req_wdata[8*i +: 8];
end else rsp_rdata <= config_value;
end
4'h4: begin
if (req_write) rsp_error <= 1'b1;
else rsp_rdata <= status_value;
end
4'h8: begin
if (req_write)
start_pulse <= req_wstrb[0] && req_wdata[0];
end
default: rsp_error <= 1'b1;
endcase
end
end
end
end
endmoduleЕсли ответ остановлен, req_ready=0, поэтому запись config и command pulse не выполняются снова. Побочный эффект уже принятого запроса мог произойти, пока ответ ещё ждёт. Безусловная повторная отправка из-за задержки ответа может повторно исполнить команду.
Смысл byte strobe
При CONFIG=32'h11223344, req_wdata=32'hAABBCCDD, req_wstrb=4'b0101 меняются лишь байты 0 и 2: результат 32'h11BB33DD. Отдельно проверяйте выравнивание адреса, позиции битов и порядок байтов памяти. Запись с wstrb=0000 успешна, но не меняет значение.
От MSBMSB — бит с наибольшим позиционным весом. Его индекс зависит от направления объявления вектора, поэтому нельзя всегда считать его битом с наибольшим номером. Подробнее байты идут 3,2,1,0. Strobe=0101 выбирает 2 и 0, поэтому записываются только BB и DD. Strobe — разрешение записи байта, а не отдельного бита.
- Прежний CONFIG: 11 | 22 | 33 | 44
- Данные записи: AA | BB | CC | DD
- strobe 0101: Сохранить · заменить · сохранить · заменить
- Новый CONFIG: 11 | BB | 33 | DD
К какому моменту относится статус
Ответ STATUS сохраняет status_value в момент приёма запроса. Если реальный status меняется во время ожидания ответа, rsp_rdata сохраняется. Прямое подключение комбинационного status при rsp_valid=1, rsp_ready=0 меняло бы содержимое ожидающего ответа и нарушало протокол.
Req_valid=req_ready=1 на последовательных фронтах означает два разных запроса. После принятия передатчик должен снять valid или перейти к следующему запросу. Нельзя постоянно удерживать один запрос, ожидая единственной обработки.
Три направления проверки
- Адреса и права: действительные, невыровненные и неопределённые адреса, запись STATUS; проверьте ошибки и побочные эффекты.
- Выбор данных: переберите четыре strobe-бита и проверьте сохранение невыбранных байтов.
- Управление потоком: при многократной остановке ответа данные и состояние сохраняются; при одновременном потреблении ответа и приёме нового запроса число транзакций совпадает.
Попробуйте сами
Принята запись COMMAND с req_wstrb[0]=1 и req_wdata[0]=1, затем rsp_ready=0 три цикла. Должен ли start_pulse повторяться три цикла? Может ли запись STATUS менять config_value?
Прочитать объяснение
Start_pulse равен 1 только один цикл после приёма, затем 0. Остановка ответа не означает повтор команды. Запись STATUS возвращает ошибку и не меняет другие состояния, включая config_value. Политику повторов до завершения ответа стороны тоже должны согласовать.