Создание конвейерной архитектуры Verilog LZSS с нуля

Я разрабатываю RTL в Verilog для алгоритма LZSS. У меня есть рабочий код для этого алгоритма в verilog. Этот код в значительной степени написан в стиле C++ в Verilog. Он работает и все выглядит хорошо.

Теперь я хочу увеличить скорость этого алгоритма и хочу его конвейеризировать. У меня есть подробная блок-схема этого алгоритма. Теперь, глядя на эту блок-схему, могу ли я решить, сколько этапов конвейера это закончится. Есть ли ограничение того, сколько комбинационной логики я могу использовать на этапе.

Пожалуйста, помогите мне изложить пошаговый процесс преобразования этой блок-схемы в конвейерный код Verilog.

Заранее спасибо.

ОБНОВЛЕНИЕ: копия исходного кода с http://collabedit.com/kvuu2

`timescale 1ns / 10 ps
`define EOF 32'HFFFF_FFFF
`define MEM_SIZE 200_000
`define NULL 0

//00 41 42 43 00 09 03 44 45 46 41 42 43

module UnCompBF ();

  reg [80*8:1] infilename;
  reg [80*8:1] outfilename;

  parameter EOF = -1;
  integer infile, outfile, mem_indx, file_char_rd;
  integer i, j, k, l;
  integer inc_i;
  reg[7:0] mem [4096:0]; // what size should i use??
  reg[7:0] out_mem [4096:0]; // what size should i use??
  reg[7:0]  get_char0, get_char1;
  reg[7:0] special_char;
  reg[15:0] length, offset;

  initial   
    begin :  uncompress_block
        //Load input binary file into memory
        infilename = "comp_out.bin";
        infile = $fopen(infilename,"r");
        //Check if input file is opened
    if (infile == `NULL)
        begin
        $display("Infile  -- file not opening");
        disable uncompress_block;
        end 

    i = $fread(mem[0], infile);
    $display("Loaded %0d entries \n", i); 
    $fclose(infile);

    //Open output file for writing
    outfilename = "out0.txt";
    outfile = $fopen(outfilename,"w");
    $display("input file loaded into mem and output file opened");

    //Initialize 
    mem_indx = 0;
    file_char_rd = 0; 
    special_char = 8'hxx;
    j = 0;
    k = 0;
    $display("initialize variables");

    //for (j=0;j<i;j=j+1)
  while (j<i)
    begin
            $display("In while loop -- j=%d -- i=%d", j, i);
            inc_i = 0;
            if (j == 0)
                begin
                    special_char = mem[j];
                    inc_i = inc_i + 1;
                    $display("first byte is marker j %d inc_i %d marker %h", j, inc_i, special_char);  
                    // else if not first char and current char is equal to value of special_char
                end 
            else if ((j != 0) && (mem[j] == special_char))
                begin
                    $display("byte is equal to marker");
                    //get next char
                    get_char0 = mem[j+1];
                    inc_i = inc_i + 2;
                    // if next char is equal to 00
                    if (get_char0[7:0] == 8'h00) // Marker is 0 hence unmatched literal
                        begin
                            // special character is actually unmatched char 
                            // write previous into output fie
                            $fdisplay(outfile, "%2h ", mem[j]);
                            // write previous into memory
                            out_mem[k] = mem[j];
                            k = k + 1;
                            $display("length is 00 meaning marker part of output");
                            $display("mem[j] %h -- k %d", mem[j], k);
                        end
                    else // get length and offset of match string // Otherwise move forward to get the lenght                                and offset
                        begin
                            // get length of match string
                            if(get_char0[7] == 1)
                                begin
                                    //get next char
                                    get_char1 = mem[j+2];
                                    inc_i = inc_i + 1;
                                    length = {1'b0,get_char0[6:0],get_char1[7:0]};  
                                end 
                            else
                                length = {8'h00,get_char0[7:0]};                                        

                                $display("length is %h -- inc_i %d", length, inc_i);    
                                // get offset of match string
                                get_char0 = mem[j+inc_i];
                                inc_i = inc_i + 1;
                            if(get_char0[7] == 1)
                                begin
                                    //get next char
                                    get_char1 = mem[j+inc_i];
                                    inc_i = inc_i + 1;
                                    offset = {1'b0,get_char0[6:0],get_char1[7:0]};      
                                end 
                            else
                                offset = {8'h00,get_char0[7:0]};                

                                $display("offset is %h -- inc_i %d", offset, inc_i);    
                        end
                            // write out the string match in file and memory    
                            for( l = 0; l < length; l = l + 1 )
                                begin
                                    out_mem[k] = out_mem[ k - offset ];
                                    // write previous into output fie
                                    $fdisplay(outfile, "%2h ",  out_mem[k]);
                                    $display("using the length/offset pair");
                                    $display("out_mem adds %h -- k %d", out_mem[k], k);
                                    k = k +  1;
                                end
                    // else write unmatched char into file and memory   
            end 

                else 
                    begin
                        // write previous into output fie
                        $fdisplay(outfile, "%2h ",  mem[j]);
                        // write previous into memory
                        out_mem[k] = mem[j];
                        inc_i = inc_i + 1;
                        $display("output unmatched char");
                        $display("out_mem adds %h -- k %d", out_mem[k], k);
                        k = k + 1;
                    end
          j = j + inc_i;
          $display("j is %d", j);
    end
    $fclose(outfile);
  end
endmodule

person rohit.ranjan    schedule 03.04.2014    source источник
comment
Можете ли вы добавить свой текущий код? Что является целью: ASIC или FPGA (что)? Более длинная комбинационная логика на каждом этапе приводит к более низкой целевой частоте схемы.   -  person osgx    schedule 03.04.2014
comment
Привет ОСГХ. Спасибо за ответ. Вот код.   -  person rohit.ranjan    schedule 04.04.2014
comment
Извините, а где здесь код? И его блок-схема, и ваша цель (как имя FPGA, так и целевая скорость сжатия/распаковки данных)   -  person osgx    schedule 04.04.2014
comment
Извините, это мой первый пост в stackoverflow, поэтому мне было интересно. Это быстрая ссылка collabedit.com/kvuu2.   -  person rohit.ranjan    schedule 04.04.2014
comment
Также я хочу сделать ASIC. Схему тоже могу выложить, если хотите. Первая закомментированная строка в коде // 41 41 43 .. является входной последовательностью для этой программы.   -  person rohit.ranjan    schedule 04.04.2014
comment
пользователь, извините, у меня нет доступа к collabedit.com. Попробуйте отредактировать свой пост и добавить сюда исходник, либо перезалить на другой хостинг. Опубликовать блок-схему тоже. Будете ли вы проводить тестирование FPGA?   -  person osgx    schedule 04.04.2014
comment
Ваш код нельзя использовать для синтеза, это не RTL.   -  person osgx    schedule 06.04.2014


Ответы (1)


К сожалению, похоже, что то, как вы реализовали этот код, НЕ синтезируется ни в ASIC, ни в FPGA; все это представляет собой всего лишь один большой начальный блок и использует различные несинтезируемые системные вызовы.

Одна вещь, с которой многие люди, имеющие опыт программирования, но плохо знакомые с HDL, сталкиваются с трудностями, - это понимание фундаментальных принципов проектирования HDL-кода по сравнению с программным кодом. В программном обеспечении вы даете набор инструкций, которые должны выполняться в последовательном порядке, чтобы компилятор преобразовал их в ассемблерные инструкции. В коде HDL вы предоставляете описание различных аппаратных компонентов, которые должны быть преобразованы инструментом синтеза в вентили и самые основные аппаратные компоненты. При проектировании аппаратного обеспечения лучше всего попытаться сконструировать систему так, как если бы вы рисовали схему или RTL-диаграмму (может быть полезно даже сделать это буквально на бумаге). Компоненты могут работать параллельно, принимать входы и управлять выходами. Вы не вызываете функции, вы создаете экземпляры модулей (намного ближе к ООП, но все еще без последовательного элемента).

Было бы лучше, если бы вы попрактиковались с основами, прежде чем пытаться реализовать что-то настолько сложное. В Интернете есть несколько учебных пособий, но, возможно, лучше изучить основы RTL-дизайна, прежде чем углубляться в изучение языка. Опять же, Verilog — это HDL, а не язык программирования, так что не сталкивайтесь с учебным пособием только для того, чтобы изучить синтаксис. Вам нужно подойти к этому совершенно по-новому, начиная с базовой логики и дизайна RTL на бумаге, а затем переводя этот дизайн в код HDL.

Приведенный выше код и использование вами блок-схемы указывают на то, что у вас есть хороший опыт программирования, но в HDL вместо этого вам нужно уметь мыслить в терминах RTL или принципиальной схемы. Надеюсь, это поможет, и удачи вам в мире аппаратного обеспечения!

person Unn    schedule 31.07.2014