...

пятница, 9 мая 2014 г.

Аппаратный сортировщик чисел на verilog-е

Определяем модуль всей цепочки. у него есть входы, выходы и внутренние модули, всё это надо связать в единую сеть с помощью комбинационной схемы. Регистров тут в явном виде нет, они инкапсулированы внутри сортировочных ячеек.

// Заголовок
module Sorting_Stack ( clk, hold, is_input, data_in, data_out );

// Числовые параметры
parameter HBIT= 15; // size of number in bits
parameter R_SZ= 256; // capacity, max sequence size
parameter _R_SZ= (R_SZ+1)/2; // not to modify

// Перечисляем входы-выходы схемы
// Тактовый сигнал
input clk;
...
// входы-выходы данных
input [HBIT:0] data_in; // load one number per clock
output [HBIT:0] data_out; // while is_input==0, max value popping out here
// в квадратных скобках перед именем - разрядность
...
// Промежуточные точки схемы
wire [HBIT:0] in_prev[_R_SZ];
wire [HBIT:0] in_next[_R_SZ];
wire [HBIT:0] out[_R_SZ];
// в квадратных скобках после имени - размерности массивов

// Внутренние подмодули модуля
// Здесь определён целый массив подмодулей
// storage
Cell_Compare #(HBIT) ribbon[_R_SZ] ( clk, hold, is_input, in_prev, in_next, out );




Рассмотрим подробнее подстановку одного модуля в другой

Cell_Compare — тип модуля

#(HBIT) — установка числовых параметров

ribbon — имя экземпляра

[_R_SZ] — это массив, указываем количество

( clk, hold, is_input, — общие сигналы для всех

in_prev, in_next, out ); — специфические сигналы для каждого элемента массива.

Далее generate — полезная конструкция, которая позволяет

применять циклы и т.д. при описании комбинационных схем.



// Соединяем некоторые точки схемы
generate
genvar i,j;
for (i=0; i<_R_SZ-1; i=i+1)
begin : block_name01
assign in_prev[i+1]= out[i];
assign in_next[i]= out[i+1];
end
assign in_prev[0]= data_in;
assign data_out= out[0];
assign in_next[_R_SZ-1]= 0;
endgenerate

endmodule




Теперь модуль сортировочной ячейки.

module Cell_Compare ( clk, hold, is_input, in_prev, in_next, out );

parameter HBIT= 15;


input clk;
input hold;

input is_input;

input [HBIT:0] in_prev;
input [HBIT:0] in_next;




Здесь начинается собственно логика сортировки. Каждая ячейка хранит два числа, одно меньше другого. Каждый такт (если не hold) ячейка сравнивает число, пришедшее от соседа со своим «чемпионом». Чемпион — максимальное число при записи и минимальное при чтении. Проигравший покинет ячейку на следующем такте. В результате, данные движутся по цепочке сначала в одном направлении, потом в другом. Количество чисел, помещающихся в устройстве равно удвоенному количеству ячеек.

Вернёмся к исходному коду. Здесь при описании выхода применён селектор, (скомпилируется в мультиплексор). is_input определяет, читаем мы данные или пишем, от него зависит, в каком направлении движутся данные по цепочке.



output [HBIT:0] out= is_input ? lower : higher;

// Хранилище. Это все регистры, что есть в сортировщике
bit [HBIT:0] higher;
bit [HBIT:0] lower;

// Здесь определяется, что будет в хранилище на следующем такте.
// В зависимости от направления движения данных, это будет
// либо higher и in_prev (lower выталкивается к хвосту),
// либо lower и in_next (higher выталкивается к голове)
wire [HBIT:0] cand_h= is_input ? higher : lower;
wire [HBIT:0] cand_l= is_input ? in_prev : in_next;

// Далее описывается синхронная логика.
// В отличие от комбинационной схемы, от времени не зависещей,
// в регистры можно писать только в определённые моменты.
always@(posedge clk )
if (~hold)
begin
// Здесь мы наконец сравниваем два числа-кандидата.
higher <= ( cand_h >= cand_l ) ? cand_h : cand_l;
lower <= ( cand_h >= cand_l ) ? cand_l : cand_h;
end
endmodule




Всё.

This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Комментариев нет:

Отправить комментарий