0

我正在为 LZSS 算法设计一个 Verilog 中的 RTL。我在verilog中有这个算法的工作代码。这段代码几乎是用 Verilog 中的 C++ 风格编写的。它运行,一切看起来都很好。

现在我想提高这个算法的速度,我想把它流水线化。我有这个算法的详细流程图。现在看看这个流程图,我可以决定这最终会进入多少个管道阶段。我可以在一个阶段执行多少组合逻辑是否存在限制。

请帮助我制定一步一步的过程,以将此流程图转换为流水线的 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
4

1 回答 1

1

不幸的是,您实现此代码的方式似乎无法合成到 ASIC 或 FPGA;整个事情只是一个大的初始块,并使用各种不可合成的系统调用。

许多具有编程经验但不熟悉 HDL 的人遇到的一件事是理解设计 HDL 代码与软件代码的基本原则。在软件中,您给出了一组指令,这些指令按顺序执行,由编译器转换为汇编指令。在 HDL 代码中,您提供了各种硬件组件的描述,这些硬件组件将由综合工具转换为门和非常基本的硬件组件。在设计一个硬件时,最好尝试像绘制电路或 RTL 图一样构建系统(即使在纸上逐字进行也会有所帮助)。组件可以并行运行,接收输入并驱动输出。您不是在调用函数,而是在实例化模块(更接近 OOP,但仍然没有顺序元素)。

最好在尝试实现如此复杂的东西之前尝试更多地练习基础知识。网上有很多教程,但最好先学习 RTL 设计的基础知识,然后再深入学习该语言。同样,Verilog 是一种 HDL,而不是一种编程语言,所以不要只是通过教程来学习语法。您需要以全新的方式处理它,从纸上的基本逻辑和 RTL 设计开始,然后将该设计转换为 HDL 代码。

上面的代码和你对流程图的使用表明你有很强的编程背景,但是在 HDL 中,你需要能够用 RTL 或电路图来思考。希望这有助于进入硬件世界并祝你好运!

于 2014-07-31T19:45:47.677 回答