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

Subversion Repositories zipcpu

[/] [zipcpu/] [trunk/] [rtl/] [core/] [pfcache.v] - Blame information for rev 77

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

Line No. Rev Author Line
1 69 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    pfcache2.v
4
//
5
// Project:     Zip CPU -- a small, lightweight, RISC CPU soft core
6
//
7
// Purpose:     Keeping our CPU fed with instructions, at one per clock and
8
//              with no stalls.  An unusual feature of this cache is the
9
//      requirement that the entire cache may be cleared (if necessary).
10
//
11
// Creator:     Dan Gisselquist, Ph.D.
12
//              Gisselquist Technology, LLC
13
//
14
////////////////////////////////////////////////////////////////////////////////
15
//
16
// Copyright (C) 2015, Gisselquist Technology, LLC
17
//
18
// This program is free software (firmware): you can redistribute it and/or
19
// modify it under the terms of  the GNU General Public License as published
20
// by the Free Software Foundation, either version 3 of the License, or (at
21
// your option) any later version.
22
//
23
// This program is distributed in the hope that it will be useful, but WITHOUT
24
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
25
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
26
// for more details.
27
//
28
// License:     GPL, v3, as defined and found on www.gnu.org,
29
//              http://www.gnu.org/licenses/gpl.html
30
//
31
//
32
////////////////////////////////////////////////////////////////////////////////
33
//
34
module  pfcache(i_clk, i_rst, i_new_pc, i_clear_cache,
35
                        // i_early_branch, i_from_addr,
36
                        i_stall_n, i_pc, o_i, o_pc, o_v,
37
                o_wb_cyc, o_wb_stb, o_wb_we, o_wb_addr, o_wb_data,
38
                        i_wb_ack, i_wb_stall, i_wb_err, i_wb_data,
39
                        o_illegal);
40
        parameter       LGCACHELEN = 8, ADDRESS_WIDTH=24,
41
                        CACHELEN=(1<<LGCACHELEN), BUSW=32, AW=ADDRESS_WIDTH,
42
                        CW=LGCACHELEN, PW=LGCACHELEN-5;
43
        input                           i_clk, i_rst, i_new_pc;
44
        input                           i_clear_cache;
45
        input                           i_stall_n;
46
        input           [(AW-1):0]       i_pc;
47
        output  reg     [(BUSW-1):0]     o_i;
48
        output  reg     [(AW-1):0]       o_pc;
49
        output  wire                    o_v;
50
        //
51
        output  reg             o_wb_cyc, o_wb_stb;
52
        output  wire            o_wb_we;
53
        output  reg     [(AW-1):0]       o_wb_addr;
54
        output  wire    [(BUSW-1):0]     o_wb_data;
55
        //
56
        input                           i_wb_ack, i_wb_stall, i_wb_err;
57
        input           [(BUSW-1):0]     i_wb_data;
58
        //
59
        output  reg                     o_illegal;
60
 
61
        // Fixed bus outputs: we read from the bus only, never write.
62
        // Thus the output data is ... irrelevant and don't care.  We set it
63
        // to zero just to set it to something.
64
        assign  o_wb_we = 1'b0;
65
        assign  o_wb_data = 0;
66
 
67
        reg                     r_v;
68
        (* ram_style = "distributed" *)
69
        reg     [(BUSW-1):0]     cache   [0:((1<<CW)-1)];
70
        reg     [(AW-CW-1):0]    tags    [0:((1<<(CW-PW))-1)];
71
        reg     [((1<<(CW-PW))-1):0]     vmask;
72
 
73
        reg     [(AW-1):0]       lastpc;
74
        reg     [(CW-1):0]       rdaddr;
75
        reg     [(AW-1):CW]     tagval;
76
        reg     [(AW-1):PW]     lasttag, illegal_cache;
77
 
78
        initial o_i = 32'h76_00_00_00;  // A NOOP instruction
79
        initial o_pc = 0;
80
        always @(posedge i_clk)
81
                if (~r_v)
82
                begin
83
                        o_i <= cache[lastpc[(CW-1):0]];
84
                        o_pc <= lastpc;
85
                end else if ((i_stall_n)||(i_new_pc))
86
                begin
87
                        o_i <= cache[i_pc[(CW-1):0]];
88
                        o_pc <= i_pc;
89
                end
90
 
91
        initial tagval = 0;
92
        always @(posedge i_clk)
93
                if (i_stall_n)
94
                        tagval <= tags[i_pc[(CW-1):PW]];
95
 
96
        // i_pc will only increment when everything else isn't stalled, thus
97
        // we can set it without worrying about that.   Doing this enables
98
        // us to work in spite of stalls.  For example, if the next address
99
        // isn't valid, but the decoder is stalled, get the next address
100
        // anyway.
101
        initial lastpc = 0;
102
        always @(posedge i_clk)
103 71 dgisselq
                if (((r_v)&&(i_stall_n))||(i_clear_cache)||(i_new_pc))
104 69 dgisselq
                        lastpc <= i_pc;
105
 
106
        initial lasttag = 0;
107
        always @(posedge i_clk)
108
                lasttag <= i_pc[(AW-1):PW];
109
 
110
        wire    r_v_from_pc, r_v_from_last;
111
        assign  r_v_from_pc = ((i_pc[(AW-1):PW] == lasttag)
112
                                &&(tagval == i_pc[(AW-1):CW])
113
                                &&(vmask[i_pc[(CW-1):PW]]));
114
        assign  r_v_from_last = ((lastpc[(AW-1):PW] == lasttag)
115
                                &&(tagval == lastpc[(AW-1):CW])
116
                                &&(vmask[lastpc[(CW-1):PW]]));
117
 
118
        reg     [1:0]    delay;
119
 
120
        initial delay = 2'h3;
121
        initial r_v = 1'b0;
122
        always @(posedge i_clk)
123 71 dgisselq
                if ((i_rst)||(i_clear_cache)||(i_new_pc)||((r_v)&&(i_stall_n)))
124 69 dgisselq
                begin
125
                        r_v <= r_v_from_pc;
126
                        delay <= 2'h2;
127 71 dgisselq
                end else if (~r_v) begin // Otherwise, r_v was true and we were
128
                        r_v <= r_v_from_last;   // stalled, hence only if ~r_v
129 69 dgisselq
                        if (o_wb_cyc)
130
                                delay <= 2'h2;
131
                        else if (delay != 0)
132
                                delay <= delay - 1;
133
                end
134
 
135
        assign  o_v = (r_v)&&(~i_new_pc);
136
 
137
 
138
        initial o_wb_cyc  = 1'b0;
139
        initial o_wb_stb  = 1'b0;
140
        initial o_wb_addr = {(AW){1'b0}};
141
        initial rdaddr    = 0;
142
        always @(posedge i_clk)
143
                if ((i_rst)||(i_clear_cache))
144
                begin
145
                        o_wb_cyc <= 1'b0;
146
                        o_wb_stb <= 1'b0;
147
                end else if (o_wb_cyc)
148
                begin
149
                        if ((o_wb_stb)&&(~i_wb_stall))
150
                        begin
151
                                if (o_wb_addr[(PW-1):0] == {(PW){1'b1}})
152
                                        o_wb_stb <= 1'b0;
153
                                else
154
                                        o_wb_addr[(PW-1):0] <= o_wb_addr[(PW-1):0]+1;
155
                        end
156
 
157
                        if (i_wb_ack)
158
                                rdaddr <= rdaddr + 1;
159
                        if ((rdaddr[(PW-1):0] == {(PW){1'b1}})||(i_wb_err))
160
                        begin
161
                                o_wb_cyc <= 1'b0;
162
                                tags[o_wb_addr[(CW-1):PW]] <= o_wb_addr[(AW-1):CW];
163
                        end
164
                        // else if (rdaddr[(PW-1):1] == {(PW-1){1'b1}})
165
                        //      tags[lastpc[(CW-1):PW]] <= lastpc[(AW-1):CW];
166
 
167
                end else if ((~r_v)&&(delay==0)
168
                        &&((tagval != lastpc[(AW-1):CW])
169 71 dgisselq
                                ||(~vmask[lastpc[(CW-1):PW]]))
170
                        &&(~o_illegal))
171 69 dgisselq
                begin
172
                        o_wb_cyc  <= 1'b1;
173
                        o_wb_stb  <= 1'b1;
174
                        o_wb_addr <= { lastpc[(AW-1):PW], {(PW){1'b0}} };
175
                        rdaddr <= { lastpc[(CW-1):PW], {(PW){1'b0}} };
176
                end
177
 
178
        // Can't initialize an array, so leave cache uninitialized
179
        always @(posedge i_clk)
180
                if ((o_wb_cyc)&&(i_wb_ack))
181
                        cache[rdaddr] <= i_wb_data;
182
 
183
        // VMask ... is a section loaded?
184
        initial vmask = 0;
185
        always @(posedge i_clk)
186
                if ((i_rst)||(i_clear_cache))
187
                        vmask <= 0;
188
                else if ((~r_v)&&(tagval != lastpc[(AW-1):CW])&&(delay == 0))
189
                        vmask[lastpc[(CW-1):PW]] <= 1'b0;
190
                else if ((o_wb_cyc)&&(i_wb_ack)&&(rdaddr[(PW-1):0] == {(PW){1'b1}}))
191
                        vmask[rdaddr[(CW-1):PW]] <= 1'b1;
192
 
193 71 dgisselq
        reg     illegal_valid;
194 69 dgisselq
        initial illegal_cache = 0;
195 71 dgisselq
        initial illegal_valid = 0;
196 69 dgisselq
        always @(posedge i_clk)
197
                if ((i_rst)||(i_clear_cache))
198 71 dgisselq
                begin
199 69 dgisselq
                        illegal_cache <= 0;
200 71 dgisselq
                        illegal_valid <= 0;
201
                end else if ((o_wb_cyc)&&(i_wb_err))
202
                begin
203 69 dgisselq
                        illegal_cache <= lastpc[(AW-1):PW];
204 71 dgisselq
                        illegal_valid <= 1'b1;
205
                end
206 69 dgisselq
 
207
        initial o_illegal = 1'b0;
208
        always @(posedge i_clk)
209 71 dgisselq
                if ((i_rst)||(i_clear_cache))
210
                        o_illegal <= 1'b0;
211
                else
212
                        o_illegal <= (illegal_valid)
213
                                &&(tagval == i_pc[(AW-1):CW])
214
                                &&(illegal_cache == i_pc[(AW-1):PW]);
215 69 dgisselq
 
216
endmodule

powered by: WebSVN 2.1.0

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