OpenCores
URL https://opencores.org/ocsvn/xulalx25soc/xulalx25soc/trunk

Subversion Repositories xulalx25soc

[/] [xulalx25soc/] [trunk/] [rtl/] [wbudecompress.v] - Diff between revs 14 and 109

Only display areas with differences | Details | Blame | View Log

Rev 14 Rev 109
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
// Filename:    wbudecompress.v
// Filename:    wbudecompress.v
//
//
// Project:     XuLA2 board
// Project:     FPGA library
//
//
// Purpose:     Compression via this interface is simply a lookup table.
// Purpose:     Compression via this interface is simply a lookup table.
//              When writing, if requested, rather than writing a new 36-bit
//              When writing, if requested, rather than writing a new 36-bit
//      word, we may be asked to repeat a word that's been written recently.
//      word, we may be asked to repeat a word that's been written recently.
//      That's the goal of this routine: if given a word's (relative) address
//      That's the goal of this routine: if given a word's (relative) address
//      in the write stream, we use that address, else we expect a full 32-bit
//      in the write stream, we use that address, else we expect a full 32-bit
//      word to come in to be written.
//      word to come in to be written.
//
//
//
//
// Creator:     Dan Gisselquist, Ph.D.
// Creator:     Dan Gisselquist, Ph.D.
//              Gisselquist Technology, LLC
//              Gisselquist Technology, LLC
//
//
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
// Copyright (C) 2015, Gisselquist Technology, LLC
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
//
// This program is free software (firmware): you can redistribute it and/or
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of  the GNU General Public License as published
// modify it under the terms of  the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
// your option) any later version.
//
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.
// for more details.
//
//
// License:     GPL, v3, as defined and found on www.gnu.org,
// License:     GPL, v3, as defined and found on www.gnu.org,
//              http://www.gnu.org/licenses/gpl.html
//              http://www.gnu.org/licenses/gpl.html
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
module  wbudecompress(i_clk, i_stb, i_word, o_stb, o_word);
module  wbudecompress(i_clk, i_stb, i_word, o_stb, o_word);
        input                   i_clk, i_stb;
        input                   i_clk, i_stb;
        input           [35:0]   i_word;
        input           [35:0]   i_word;
        output  reg             o_stb;
        output  reg             o_stb;
        output  reg     [35:0]   o_word;
        output  reg     [35:0]   o_word;
 
 
 
 
        // Clock zero
        // Clock zero
        //      { o_stb, r_stb } = 0
        //      { o_stb, r_stb } = 0
        wire    cmd_write_not_compressed = (i_word[35:33] == 3'h3);
        wire    cmd_write_not_compressed = (i_word[35:33] == 3'h3);
 
 
 
 
        // Clock one: { o_stb, r_stb } = 4'h1 when done
        // Clock one: { o_stb, r_stb } = 4'h1 when done
        reg     [7:0]    wr_addr;
        reg     [7:0]    wr_addr;
        initial wr_addr = 8'h0;
        initial wr_addr = 8'h0;
        always @(posedge i_clk)
        always @(posedge i_clk)
                if ((i_stb)&&(cmd_write_not_compressed))
                if ((i_stb)&&(cmd_write_not_compressed))
                        wr_addr <= wr_addr + 8'h1;
                        wr_addr <= wr_addr + 8'h1;
 
 
        reg     [31:0]   compression_tbl [0:255];
        reg     [31:0]   compression_tbl [0:255];
        always @(posedge i_clk)
        always @(posedge i_clk)
                if (i_stb)
                if (i_stb)
                compression_tbl[wr_addr] <= { i_word[32:31], i_word[29:0] };
                compression_tbl[wr_addr] <= { i_word[32:31], i_word[29:0] };
 
 
        reg     [35:0]   r_word;
        reg     [35:0]   r_word;
        always @(posedge i_clk)
        always @(posedge i_clk)
                if (i_stb)
                if (i_stb)
                        r_word <= i_word;
                        r_word <= i_word;
 
 
 
 
        // Clock two, calculate the table address ... 1 is the smallest address
        // Clock two, calculate the table address ... 1 is the smallest address
        //      { o_stb, r_stb } = 4'h2 when done
        //      { o_stb, r_stb } = 4'h2 when done
        reg     [7:0]    cmd_addr;
        reg     [7:0]    cmd_addr;
        always @(posedge i_clk)
        always @(posedge i_clk)
                cmd_addr = wr_addr - { r_word[32:31], r_word[29:24] };
                cmd_addr = wr_addr - { r_word[32:31], r_word[29:24] };
 
 
        // Let's also calculate the address, in case this is a compressed
        // Let's also calculate the address, in case this is a compressed
        // address word
        // address word
        reg     [24:0]   r_addr;
        reg     [24:0]   r_addr;
        always @(posedge i_clk)
        always @(posedge i_clk)
                case(r_word[32:30])
                case(r_word[32:30])
                3'b000: r_addr <= { 19'h0, r_word[29:24] };
                3'b000: r_addr <= { 19'h0, r_word[29:24] };
                3'b010: r_addr <= { 13'h0, r_word[29:18] };
                3'b010: r_addr <= { 13'h0, r_word[29:18] };
                3'b100: r_addr <= {  7'h0, r_word[29:12] };
                3'b100: r_addr <= {  7'h0, r_word[29:12] };
                3'b110: r_addr <= {  1'h0, r_word[29: 6] };
                3'b110: r_addr <= {  1'h0, r_word[29: 6] };
                3'b001: r_addr <= { {(19){ r_word[29]}}, r_word[29:24] };
                3'b001: r_addr <= { {(19){ r_word[29]}}, r_word[29:24] };
                3'b011: r_addr <= { {(13){ r_word[29]}}, r_word[29:18] };
                3'b011: r_addr <= { {(13){ r_word[29]}}, r_word[29:18] };
                3'b101: r_addr <= { {( 7){ r_word[29]}}, r_word[29:12] };
                3'b101: r_addr <= { {( 7){ r_word[29]}}, r_word[29:12] };
                3'b111: r_addr <= { {( 1){ r_word[29]}}, r_word[29: 6] };
                3'b111: r_addr <= { {( 1){ r_word[29]}}, r_word[29: 6] };
                endcase
                endcase
        wire    [31:0]   w_addr;
        wire    [31:0]   w_addr;
        assign  w_addr = { {(7){r_addr[24]}}, r_addr };
        assign  w_addr = { {(7){r_addr[24]}}, r_addr };
 
 
        reg     [9:0]    rd_len;
        reg     [9:0]    rd_len;
        always @(posedge i_clk)
        always @(posedge i_clk)
                if (~r_word[34])
                if (~r_word[34])
                        rd_len <= 10'h01 + { 6'h00, r_word[33:31] };
                        rd_len <= 10'h01 + { 6'h00, r_word[33:31] };
                else
                else
                        rd_len <= 10'h08 + { 1'b0, r_word[33:31], r_word[29:24] };
                        rd_len <= 10'h09 + { 1'b0, r_word[33:31], r_word[29:24] };
 
 
        // Clock three, read the table value
        // Clock three, read the table value
        //      { o_stb, r_stb } = 4'h4 when done
        //      { o_stb, r_stb } = 4'h4 when done
        // Maintaining ...
        // Maintaining ...
        //      r_word (clock 1)
        //      r_word (clock 1)
        //      r_addr, rd_len (clock 2)
        //      r_addr, rd_len (clock 2)
        reg     [31:0]   cword;
        reg     [31:0]   cword;
        always @(posedge i_clk)
        always @(posedge i_clk)
                cword <= compression_tbl[cmd_addr];
                cword <= compression_tbl[cmd_addr];
 
 
 
 
        // Pipeline the strobe signal to create an output strobe, 3 clocks later
        // Pipeline the strobe signal to create an output strobe, 3 clocks later
        reg     [2:0]    r_stb;
        reg     [2:0]    r_stb;
        initial r_stb = 0;
        initial r_stb = 0;
        always @(posedge i_clk)
        always @(posedge i_clk)
                r_stb <= { r_stb[1:0], i_stb };
                r_stb <= { r_stb[1:0], i_stb };
 
 
        // Clock four, now that the table value is valid, let's set our output
        // Clock four, now that the table value is valid, let's set our output
        // word.
        // word.
        //      { o_stb, r_stb } = 4'h8 when done
        //      { o_stb, r_stb } = 4'h8 when done
        always @(posedge i_clk)
        always @(posedge i_clk)
                o_stb <= r_stb[2];
                o_stb <= r_stb[2];
        // Maintaining ...
        // Maintaining ...
        //      r_word          (clock 1)
        //      r_word          (clock 1)
        //      r_addr, rd_len  (clock 2)
        //      r_addr, rd_len  (clock 2)
        //      cword           (clock 3)
        //      cword           (clock 3)
        //              Any/all of these can be pipelined for faster operation
        //              Any/all of these can be pipelined for faster operation
        // However, speed is really limited by the speed of the I/O port.  At
        // However, speed is really limited by the speed of the I/O port.  At
        // it's fastest, it's 1 bit per clock, 48 clocks per codeword therefore,
        // it's fastest, it's 1 bit per clock, 48 clocks per codeword therefore,
        // thus ... things will hold still for much longer than just 5 clocks.
        // thus ... things will hold still for much longer than just 5 clocks.
        always @(posedge i_clk)
        always @(posedge i_clk)
                if (r_word[35:30] == 6'b101110)
                if (r_word[35:30] == 6'b101110)
                        o_word <= r_word;
                        o_word <= r_word;
                else casez(r_word[35:30])
                else casez(r_word[35:30])
                // Set address from something compressed ... unsigned
                // Set address from something compressed ... unsigned
                6'b001??0: o_word <= { 4'h0, w_addr[31:0] };
                6'b001??0: o_word <= { 4'h0, w_addr[31:0] };
                // Set a new address as a signed offset from the last (set) one
                // Set a new address as a signed offset from the last (set) one
                //      (The last address is kept further down the chain,
                //      (The last address is kept further down the chain,
                //      we just mark here that the address is to be set
                //      we just mark here that the address is to be set
                //      relative to it, and by how much.)
                //      relative to it, and by how much.)
                6'b001??1: o_word <= { 3'h1, w_addr[31:30], 1'b1, w_addr[29:0]};
                6'b001??1: o_word <= { 3'h1, w_addr[31:30], 1'b1, w_addr[29:0]};
                // Write a value to the bus, with the value given from our
                // Write a value to the bus, with the value given from our
                // codeword table
                // codeword table
                6'b010???: o_word <=
                6'b010???: o_word <=
                        { 3'h3, cword[31:30], r_word[30], cword[29:0] };
                        { 3'h3, cword[31:30], r_word[30], cword[29:0] };
                // Read, highly compressed length (1 word)
                // Read, highly compressed length (1 word)
                6'b10????: o_word <= { 5'b11000, r_word[30], 20'h00, rd_len };
                6'b10????: o_word <= { 5'b11000, r_word[30], 20'h00, rd_len };
                // Read, two word (3+9 bits) length
                // Read, two word (3+9 bits) length
                6'b11????: o_word <= { 5'b11000, r_word[30], 20'h00, rd_len };
                6'b11????: o_word <= { 5'b11000, r_word[30], 20'h00, rd_len };
                default: o_word <= r_word;
                default: o_word <= r_word;
                endcase
                endcase
endmodule
endmodule
 
 
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.