Skip to content

FLStepCode/test_task

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 

Repository files navigation

test_task

Репозиторий, в котором хранятся решения тестового задания для стажировки в Импульсе

Вариант 2

Описание принятых решений

  1. Необходимо "запомнить" порядок, в котором приходили значения ID от slave-устройства. С этим прекрасно справится простой FIFO, а так как нам четко известно, что приходит 16 уникальных ID, то можно сделать фиксированную длину очереди в 16 и не заботиться о переполнении очереди и пересечении указателей. Назовем эту очередь id_FIFO;

  2. При получении пакета данных от master-устройства также приходит его ID. Есть два варианта реализации получения данных:

    • Создать буфер длиной в 16 слов и для каждого пришедшего пакета "искать" позицию, которая соответствует позиции ID в очереди, а далее бездумно отдавать пакет и ID вместе обратно slave-устройству;
    • Создать буфер длиной в 16 слов и для каждого пришедшего пакета использовать "принцип" хэш-таблиц, где позиция пакета в этом буфере равна его ID (отталкиваясь от узкого диапазона ID - от 0 до 15).

    Был выбран вариант 2, поскольку он проще в реализации и возможно занимает меньше ресурсов, поскольку длина буфера одинакова, но логика, возможно, проще. Назовем этот буфер data_buffer;

  3. При записи пришедших от master-устройства данных также предусматривается бит валидности: если в n-ную позицию буфера данных пришел пакет, то его старший бит гарантированно равен 1, т. е. слово в буфере - это {1'b1, data_word}, если туда пришли данные.

  4. С таким устройством модуля данные отдаются slave-устройству в том случае, если по ID, который находится в голове очереди, пришли данные, то есть data_buffer[id_FIFO[FIFO_head]][DATA_WIDTH] == 1'b1 (бит валидности старший, то есть находится на позиции DATA_WIDTH). Этот случай говорит либо о том, что это самый первый ID и данные по нему пришли, либо о том, что пакеты по всем ID, которые были до текущего головного ID, были отданы. Таким образом гарантируется корректный порядок выдачи данных.

  5. Спустя день после всего сделанного была попытка сделать все на RAM-блоках. Адрес, по которому будут читаться данные из буфера данных, напрямую зависит от прочитанных из очереди ID данных, а для того, чтобы задержки не препятствовали одновременной отдаче данных, я попробовал отдавать индекс пакета в порт с задержкой в один такт. Но при попытке написания этой все штуки были большие проблемы с тем, чтобы придумать, как согласовать все это с сигналами готовности от slave-устройства, то есть как удерживать пакет данных, даже если данные, читаемые с очереди, поменялись. К тому же с заданными ограничениями очередь не переводилась в М9К, поскольку она слишком маленькая по объему, поэтому я решил, что оно не стоит того и вернулся к прошлой стратегии. К тому же я нашел ошибку, которую надо исправить, а именно была сломана логика отдачи данных обратно в slave-устройство.

Описание работы модуля

Был спроектирован только один модуль:

module reorder_buffer #(
    parameter DATA_WIDTH = 8
) (
    input logic clk,
    input logic rst_n,

    //AR slave interface
    input logic [3:0] s_arid_i,
    input logic s_arvalid_i,
    output logic s_arready_o,

    //R slave interface
    output logic [DATA_WIDTH-1:0] s_rdata_o,
    output logic [3:0] s_rid_o,
    output logic s_rvalid_o,
    input logic s_rready_i,

    //AR master interface
    output logic [3:0] m_arid_o,
    output logic m_arvalid_o,
    input logic m_arready_i,

    //R master interface
    input logic [DATA_WIDTH-1:0] m_rdata_i,
    input logic [3:0] m_rid_i,
    input logic m_rvalid_i,
    output logic m_rready_o
);

Сигналы, которые должны передаваться напрямую между устройствами, соединяются через простой assign:

assign m_arid_o = s_arid_i;
assign m_arvalid_o = s_arvalid_i;
assign s_arready_o = m_arready_i;
assign m_rready_o = s_rready_i;

Также объявляются буферы для ID и данных:

logic [3:0] s_arid_FIFO [0:15];
logic [3:0] FIFO_head;
logic [3:0] FIFO_tail;

logic [DATA_WIDTH:0] m_rdata_buffer [0:15];

При сигнале сброса указатели и буферы обнуляются. Во время положительного фронта тактового сигнала сначала "инициализируется" дефолтное значение s_rvalid_o в 0, а далее параллельно происходят три процесса:

  • При наличии необходимых сигналов ID от slave-устройства записывается в очередь:
    if (s_arready_o && s_arvalid_i) begin
        s_arid_FIFO[FIFO_tail] <= s_arid_i;
        FIFO_tail <= FIFO_tail + 1;
    end
    
  • При наличии необходимых сигналов пакет данных от master-устройства записывается в буфер по индексу ID:
    if (m_rvalid_i && m_rready_o) begin
        m_rdata_buffer[m_rid_i] <= {1'b1, m_rdata_i};
    end
    
  • Если пришел пакет с ID, который совпадает с ID, ожидающим в голове очереди, то на выходы к slave-устройству выводятся пакет и ID. Если сигнал готовности slave-устройства поднят, то голова очереди передвигается на следующий элемент:
    if (m_rdata_buffer[s_arid_FIFO[FIFO_head]][DATA_WIDTH]) begin
        s_rdata_o <= m_rdata_buffer[s_arid_FIFO[FIFO_head]];
        s_rid_o <= s_arid_FIFO[FIFO_head];
        if (s_rready_i) begin
            FIFO_head <= FIFO_head + 1;
        end
        s_rvalid_o <= 1'b1;
    end
    

Запуск тестбенча

В папке ./variant_2/modelsim есть файл modelsim_run.bat. Данный батч скрипт приказывает ModelSim скомпилировать тестбенч tb.sv и вывести релевантные сигналы на временную диаграмму согласно скрипту modelsim_script.tcl

Вариант 1

  1. Надо перенаправить данные от устройства к устройству, а также есть шанс, что нам надо будет подержать данные у себя некоторое время? Строим FIFO, причем интерпретация проста: сигнал валидности от vc-устройства - это сигнал push, а сигнал готовности vr-устройства - это сигнал pop.
  2. Написав очередь через простую конструкцию
    case ({s_valid_i, m_ready_i})
        2'b00: begin
            ...
        end
        2'b01: begin
            ...
        end
        2'b10: begin
            ...
        end
        2'b11: begin
            ...
        end
    endcase
    
    сохраняя положение головы, положение хвоста и количество элементов, можно повесить на этот код всю логику, связянную с выводом валидности данных для vr-устройства и количеством кредитов для vc-устройства.

К тому же было проверено, что FIFO со всей сопутствующей логикой распознается как минимум синтезатором Quartus как RAM, что очень хорошо. При слишком мелких размерах очереди RAM синтезируется на плате как логика, но при достижении определенного порога используются спецблоки, например, M9K или подобные.

Запуск тестбенча

В папке ./variant_1/modelsim есть файл modelsim_run.bat. Данный батч скрипт приказывает ModelSim скомпилировать тестбенч tb.sv и вывести релевантные сигналы на временную диаграмму согласно скрипту modelsim_script.tcl

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published