Altifigence Academy

62 / 63 · Теория

Регистровый интерфейс и момент побочных эффектов

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

Определите действие «записать регистр»

Предварительные знания: адресный дешифраторДешифратор активирует выходную линию, соответствующую двоичному коду. При наличии enable неактивное разрешение может устанавливать все выходы в 0. Подробнее, ready/validРукопожатие (handshake) — соглашение, по которому передача подтверждается, когда valid передатчика и ready приёмника равны 1 на одном фронте. Оно также задаёт правила удержания данных во время ожидания. Подробнее, enable и приоритет обновления состояния.

Для подключения конфигурационных регистровРегистр хранит многобитное состояние. Синхронные регистры в этом курсе записывают определённый вход на фронте тактового сигнала. Подробнее к внешнему контроллеру недостаточно проверить адрес. Нужно определить приём запроса, удержание ожидающего ответа и поведение при записи по адресу только для чтения. Здесь используется простой интерфейс одного запроса и ответа в общем тактовом домене.

accept=req_valid∧req_ready\mathrm{accept}=\mathrm{req\_valid}\land\mathrm{req\_ready}

Адреса ниже байтовые, с 32-битным выравниванием. Каждый запрос создаёт ровно один ответ об успехе или ошибке.

АдресИмяПоведение
0x0CONFIGЧтение/запись с byte strobe
0x4STATUSТолько чтение, значение в момент приёма
0x8COMMANDЧтение 0, запись бита 0 байта 0 создаёт start pulse
ПрочиеНе определеныОтвет с ошибкой без изменения состояния

Приём при пустом или освобождаемом слоте ответа

SystemVerilog
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 — разрешение записи байта, а не отдельного бита.

Изменяйте только байты, выбранные byte strobe
  1. Прежний CONFIG: 11 | 22 | 33 | 44
  2. Данные записи: AA | BB | CC | DD
  3. strobe 0101: Сохранить · заменить · сохранить · заменить
  4. Новый CONFIG: 11 | BB | 33 | DD

К какому моменту относится статус

Ответ STATUS сохраняет status_value в момент приёма запроса. Если реальный status меняется во время ожидания ответа, rsp_rdata сохраняется. Прямое подключение комбинационного status при rsp_valid=1, rsp_ready=0 меняло бы содержимое ожидающего ответа и нарушало протокол.

Req_valid=req_ready=1 на последовательных фронтах означает два разных запроса. После принятия передатчик должен снять valid или перейти к следующему запросу. Нельзя постоянно удерживать один запрос, ожидая единственной обработки.

Три направления проверки

  1. Адреса и права: действительные, невыровненные и неопределённые адреса, запись STATUS; проверьте ошибки и побочные эффекты.
  2. Выбор данных: переберите четыре strobe-бита и проверьте сохранение невыбранных байтов.
  3. Управление потоком: при многократной остановке ответа данные и состояние сохраняются; при одновременном потреблении ответа и приёме нового запроса число транзакций совпадает.

Попробуйте сами

Принята запись COMMAND с req_wstrb[0]=1 и req_wdata[0]=1, затем rsp_ready=0 три цикла. Должен ли start_pulse повторяться три цикла? Может ли запись STATUS менять config_value?

Прочитать объяснение

Start_pulse равен 1 только один цикл после приёма, затем 0. Остановка ответа не означает повтор команды. Запись STATUS возвращает ошибку и не меняет другие состояния, включая config_value. Политику повторов до завершения ответа стороны тоже должны согласовать.

Выбор действует в этом браузере. Его можно изменить внизу страницы.