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

Subversion Repositories xulalx25soc

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

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    wbudecompress.v
4
//
5
// Project:     XuLA2 board
6
//
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
// Copyright (C) 2015, Gisselquist Technology, LLC
21
//
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
                compression_tbl[wr_addr] <= { i_word[32:31], i_word[29:0] };
61
 
62 9 dgisselq
        reg     [35:0]   r_word;
63
        always @(posedge i_clk)
64
                r_word <= i_word;
65 2 dgisselq
 
66 9 dgisselq
 
67
        // Clock two, calculate the table address ... 1 is the smallest address
68
        //      { o_stb, r_stb } = 4'h2 when done
69
        reg     [7:0]    cmd_addr;
70 2 dgisselq
        always @(posedge i_clk)
71 9 dgisselq
                cmd_addr = wr_addr - { r_word[32:31], r_word[29:24] };
72 2 dgisselq
 
73
        // Let's also calculate the address, in case this is a compressed
74
        // address word
75
        reg     [24:0]   r_addr;
76
        always @(posedge i_clk)
77 9 dgisselq
                case(r_word[32:30])
78
                3'b000: r_addr <= { 19'h0, r_word[29:24] };
79
                3'b010: r_addr <= { 13'h0, r_word[29:18] };
80
                3'b100: r_addr <= {  7'h0, r_word[29:12] };
81
                3'b110: r_addr <= {  1'h0, r_word[29: 6] };
82
                3'b001: r_addr <= { {(19){ r_word[29]}}, r_word[29:24] };
83
                3'b011: r_addr <= { {(13){ r_word[29]}}, r_word[29:18] };
84
                3'b101: r_addr <= { {( 7){ r_word[29]}}, r_word[29:12] };
85
                3'b111: r_addr <= { {( 1){ r_word[29]}}, r_word[29: 6] };
86 2 dgisselq
                endcase
87
        wire    [31:0]   w_addr;
88
        assign  w_addr = { {(7){r_addr[24]}}, r_addr };
89
 
90
        reg     [9:0]    rd_len;
91
        always @(posedge i_clk)
92 9 dgisselq
                if (~r_word[34])
93
                        rd_len <= 10'h01 + { 6'h00, r_word[33:31] };
94 2 dgisselq
                else
95 9 dgisselq
                        rd_len <= 10'h08 + { 1'b0, r_word[33:31], r_word[29:24] };
96 2 dgisselq
 
97 9 dgisselq
        // Clock three, read the table value
98
        //      { o_stb, r_stb } = 4'h4 when done
99
        // Maintaining ...
100
        //      r_word (clock 1)
101
        //      r_addr, rd_len (clock 2)
102
        reg     [31:0]   cword;
103
        always @(posedge i_clk)
104
                cword <= compression_tbl[cmd_addr];
105 2 dgisselq
 
106 9 dgisselq
 
107
        // Pipeline the strobe signal to create an output strobe, 3 clocks later
108
        reg     [2:0]    r_stb;
109
        initial r_stb = 0;
110 2 dgisselq
        always @(posedge i_clk)
111 9 dgisselq
                r_stb <= { r_stb[1:0], i_stb };
112 2 dgisselq
 
113 9 dgisselq
        // Clock four, now that the table value is valid, let's set our output
114 2 dgisselq
        // word.
115 9 dgisselq
        //      { o_stb, r_stb } = 4'h8 when done
116 2 dgisselq
        always @(posedge i_clk)
117 9 dgisselq
                o_stb <= r_stb[2];
118
        // Maintaining ...
119
        //      r_word          (clock 1)
120
        //      r_addr, rd_len  (clock 2)
121
        //      cword           (clock 3)
122
        //              Any/all of these can be pipelined for faster operation
123
        // However, speed is really limited by the speed of the I/O port.  At
124
        // it's fastest, it's 1 bit per clock, 48 clocks per codeword therefore,
125
        // thus ... things will hold still for much longer than just 5 clocks.
126 2 dgisselq
        always @(posedge i_clk)
127
                if (r_word[35:30] == 6'b101110)
128
                        o_word <= r_word;
129
                else casez(r_word[35:30])
130
                6'b001??0: o_word <= { 4'h0, w_addr[31:0] };
131
                6'b001??1: o_word <= { 3'h1, w_addr[31:30], 1'b1, w_addr[29:0] };
132
                6'b010???: o_word <=
133
                        { 3'h3, cword[31:30], r_word[30], cword[29:0] };
134
                6'b10????: o_word <= { 5'b11000, r_word[30],
135
                                20'h00, rd_len };
136
                6'b11????: o_word <= { 5'b11000, r_word[30],
137
                                20'h00, rd_len };
138
                default: o_word <= r_word;
139
                endcase
140
endmodule
141
 

powered by: WebSVN 2.1.0

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