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

Subversion Repositories xulalx25soc

[/] [xulalx25soc/] [trunk/] [rtl/] [wbudecompress.v] - Blame information for rev 109

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    wbudecompress.v
4
//
5 109 dgisselq
// Project:     FPGA library
6 2 dgisselq
//
7
// Purpose:     Compression via this interface is simply a lookup table.
8
//              When writing, if requested, rather than writing a new 36-bit
9
//      word, we may be asked to repeat a word that's been written recently.
10
//      That's the goal of this routine: if given a word's (relative) address
11
//      in the write stream, we use that address, else we expect a full 32-bit
12
//      word to come in to be written.
13
//
14
//
15
// Creator:     Dan Gisselquist, Ph.D.
16
//              Gisselquist Technology, LLC
17
//
18
////////////////////////////////////////////////////////////////////////////////
19
//
20 109 dgisselq
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
21 2 dgisselq
//
22
// This program is free software (firmware): you can redistribute it and/or
23
// modify it under the terms of  the GNU General Public License as published
24
// by the Free Software Foundation, either version 3 of the License, or (at
25
// your option) any later version.
26
//
27
// This program is distributed in the hope that it will be useful, but WITHOUT
28
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
29
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
30
// for more details.
31
//
32
// License:     GPL, v3, as defined and found on www.gnu.org,
33
//              http://www.gnu.org/licenses/gpl.html
34
//
35
//
36
////////////////////////////////////////////////////////////////////////////////
37
//
38
//
39
module  wbudecompress(i_clk, i_stb, i_word, o_stb, o_word);
40
        input                   i_clk, i_stb;
41
        input           [35:0]   i_word;
42
        output  reg             o_stb;
43
        output  reg     [35:0]   o_word;
44
 
45 9 dgisselq
 
46
        // Clock zero
47
        //      { o_stb, r_stb } = 0
48 2 dgisselq
        wire    cmd_write_not_compressed = (i_word[35:33] == 3'h3);
49
 
50 9 dgisselq
 
51
        // Clock one: { o_stb, r_stb } = 4'h1 when done
52 2 dgisselq
        reg     [7:0]    wr_addr;
53
        initial wr_addr = 8'h0;
54
        always @(posedge i_clk)
55
                if ((i_stb)&&(cmd_write_not_compressed))
56
                        wr_addr <= wr_addr + 8'h1;
57
 
58
        reg     [31:0]   compression_tbl [0:255];
59
        always @(posedge i_clk)
60 14 dgisselq
                if (i_stb)
61 2 dgisselq
                compression_tbl[wr_addr] <= { i_word[32:31], i_word[29:0] };
62
 
63 9 dgisselq
        reg     [35:0]   r_word;
64
        always @(posedge i_clk)
65 14 dgisselq
                if (i_stb)
66
                        r_word <= i_word;
67 2 dgisselq
 
68 9 dgisselq
 
69
        // Clock two, calculate the table address ... 1 is the smallest address
70
        //      { o_stb, r_stb } = 4'h2 when done
71
        reg     [7:0]    cmd_addr;
72 2 dgisselq
        always @(posedge i_clk)
73 9 dgisselq
                cmd_addr = wr_addr - { r_word[32:31], r_word[29:24] };
74 2 dgisselq
 
75
        // Let's also calculate the address, in case this is a compressed
76
        // address word
77
        reg     [24:0]   r_addr;
78
        always @(posedge i_clk)
79 9 dgisselq
                case(r_word[32:30])
80
                3'b000: r_addr <= { 19'h0, r_word[29:24] };
81
                3'b010: r_addr <= { 13'h0, r_word[29:18] };
82
                3'b100: r_addr <= {  7'h0, r_word[29:12] };
83
                3'b110: r_addr <= {  1'h0, r_word[29: 6] };
84
                3'b001: r_addr <= { {(19){ r_word[29]}}, r_word[29:24] };
85
                3'b011: r_addr <= { {(13){ r_word[29]}}, r_word[29:18] };
86
                3'b101: r_addr <= { {( 7){ r_word[29]}}, r_word[29:12] };
87
                3'b111: r_addr <= { {( 1){ r_word[29]}}, r_word[29: 6] };
88 2 dgisselq
                endcase
89
        wire    [31:0]   w_addr;
90
        assign  w_addr = { {(7){r_addr[24]}}, r_addr };
91
 
92
        reg     [9:0]    rd_len;
93
        always @(posedge i_clk)
94 9 dgisselq
                if (~r_word[34])
95
                        rd_len <= 10'h01 + { 6'h00, r_word[33:31] };
96 2 dgisselq
                else
97 109 dgisselq
                        rd_len <= 10'h09 + { 1'b0, r_word[33:31], r_word[29:24] };
98 2 dgisselq
 
99 9 dgisselq
        // Clock three, read the table value
100
        //      { o_stb, r_stb } = 4'h4 when done
101
        // Maintaining ...
102
        //      r_word (clock 1)
103
        //      r_addr, rd_len (clock 2)
104
        reg     [31:0]   cword;
105
        always @(posedge i_clk)
106
                cword <= compression_tbl[cmd_addr];
107 2 dgisselq
 
108 9 dgisselq
 
109
        // Pipeline the strobe signal to create an output strobe, 3 clocks later
110
        reg     [2:0]    r_stb;
111
        initial r_stb = 0;
112 2 dgisselq
        always @(posedge i_clk)
113 9 dgisselq
                r_stb <= { r_stb[1:0], i_stb };
114 2 dgisselq
 
115 9 dgisselq
        // Clock four, now that the table value is valid, let's set our output
116 2 dgisselq
        // word.
117 9 dgisselq
        //      { o_stb, r_stb } = 4'h8 when done
118 2 dgisselq
        always @(posedge i_clk)
119 9 dgisselq
                o_stb <= r_stb[2];
120
        // Maintaining ...
121
        //      r_word          (clock 1)
122
        //      r_addr, rd_len  (clock 2)
123
        //      cword           (clock 3)
124
        //              Any/all of these can be pipelined for faster operation
125
        // However, speed is really limited by the speed of the I/O port.  At
126
        // it's fastest, it's 1 bit per clock, 48 clocks per codeword therefore,
127
        // thus ... things will hold still for much longer than just 5 clocks.
128 2 dgisselq
        always @(posedge i_clk)
129
                if (r_word[35:30] == 6'b101110)
130
                        o_word <= r_word;
131
                else casez(r_word[35:30])
132 14 dgisselq
                // Set address from something compressed ... unsigned
133 2 dgisselq
                6'b001??0: o_word <= { 4'h0, w_addr[31:0] };
134 14 dgisselq
                // Set a new address as a signed offset from the last (set) one
135
                //      (The last address is kept further down the chain,
136
                //      we just mark here that the address is to be set
137
                //      relative to it, and by how much.)
138
                6'b001??1: o_word <= { 3'h1, w_addr[31:30], 1'b1, w_addr[29:0]};
139
                // Write a value to the bus, with the value given from our
140
                // codeword table
141 2 dgisselq
                6'b010???: o_word <=
142
                        { 3'h3, cword[31:30], r_word[30], cword[29:0] };
143 14 dgisselq
                // Read, highly compressed length (1 word)
144
                6'b10????: o_word <= { 5'b11000, r_word[30], 20'h00, rd_len };
145
                // Read, two word (3+9 bits) length
146
                6'b11????: o_word <= { 5'b11000, r_word[30], 20'h00, rd_len };
147 2 dgisselq
                default: o_word <= r_word;
148
                endcase
149
endmodule
150
 

powered by: WebSVN 2.1.0

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