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

Subversion Repositories zipcpu

[/] [zipcpu/] [trunk/] [rtl/] [core/] [pipefetch.v] - Blame information for rev 2

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

Line No. Rev Author Line
1 2 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    regset.v
4
//
5
// Project:     Zip CPU -- a small, lightweight, RISC CPU soft core
6
//
7
// Purpose:     
8
//
9
// Creator:     Dan Gisselquist, Ph.D.
10
//              Gisselquist Tecnology, LLC
11
//
12
////////////////////////////////////////////////////////////////////////////////
13
//
14
// Copyright (C) 2015, Gisselquist Technology, LLC
15
//
16
// This program is free software (firmware): you can redistribute it and/or
17
// modify it under the terms of  the GNU General Public License as published
18
// by the Free Software Foundation, either version 3 of the License, or (at
19
// your option) any later version.
20
//
21
// This program is distributed in the hope that it will be useful, but WITHOUT
22
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
23
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
24
// for more details.
25
//
26
// License:     GPL, v3, as defined and found on www.gnu.org,
27
//              http://www.gnu.org/licenses/gpl.html
28
//
29
//
30
////////////////////////////////////////////////////////////////////////////////
31
//
32
module  pipefetch(i_clk, i_rst, i_new_pc, i_stall_n, i_pc,
33
                        o_i, o_pc, o_v,
34
                o_wb_cyc, o_wb_stb, o_wb_we, o_wb_addr, o_wb_data,
35
                        i_wb_ack, i_wb_stall, i_wb_data);
36
        parameter       LGCACHELEN = 6, CACHELEN=(1<<LGCACHELEN), BUSW=32;
37
        input                           i_clk, i_rst, i_new_pc, i_stall_n;
38
        input           [(BUSW-1):0]     i_pc;
39
        output  reg     [(BUSW-1):0]     o_i;
40
        output  reg     [(BUSW-1):0]     o_pc;
41
        output  wire                    o_v;
42
        //
43
        output  reg             o_wb_cyc, o_wb_stb;
44
        output  wire            o_wb_we;
45
        output  reg     [(BUSW-1):0]     o_wb_addr;
46
        output  wire    [(BUSW-1):0]     o_wb_data;
47
        //
48
        input                   i_wb_ack, i_wb_stall;
49
        input           [(BUSW-1):0]     i_wb_data;
50
 
51
        // Fixed bus outputs: we read from the bus only, never write.
52
        // Thus the output data is ... irrelevant and don't care.  We set it
53
        // to zero just to set it to something.
54
        assign  o_wb_we = 1'b0;
55
        assign  o_wb_data = 0;
56
 
57
        reg     [(BUSW-1):0]             r_cache_base, r_cache_offset;
58
        reg     [(LGCACHELEN):0] r_nvalid, r_acks_waiting;
59
        reg     [(BUSW-1):0]             cache[0:(CACHELEN-1)];
60
 
61
        wire    [(LGCACHELEN-1):0]       c_cache_offset;
62
        assign  c_cache_offset =  r_cache_offset[(LGCACHELEN-1):0];
63
 
64
        reg                     r_addr_set;
65
        reg     [(BUSW-1):0]     r_addr;
66
 
67
        wire    [(BUSW-1):0]     bus_nvalid;
68
        assign  bus_nvalid = { {(BUSW-LGCACHELEN-1){1'b0}}, r_nvalid };
69
 
70
        initial r_nvalid = 0;
71
        initial r_cache_base = 0;
72
        always @(posedge i_clk)
73
        begin
74
                if (i_rst)
75
                        o_wb_cyc <= 1'b0;
76
                else if ((~o_wb_cyc)&&(i_new_pc)&&(r_nvalid != 0)
77
                                &&(i_pc > r_cache_base)
78
                                &&(i_pc < r_cache_base + bus_nvalid))
79
                begin
80
                        // The new instruction is in our cache, do nothing
81
                        // with the bus here.
82
                end else if ((o_wb_cyc)&&(i_new_pc)&&(r_nvalid != 0)
83
                                &&((i_pc < r_cache_base)
84
                                        ||(i_pc >= r_cache_base + CACHELEN)))
85
                begin
86
                        // We need to abandon our bus action to start over in
87
                        // a new region, setting up a new cache.  This may
88
                        // happen mid cycle while waiting for a result.  By
89
                        // dropping o_wb_cyc, we state that we are no longer
90
                        // interested in that result--whatever it might be.
91
                        o_wb_cyc <= 1'b0;
92
                        o_wb_stb <= 1'b0;
93
                end else if ((~o_wb_cyc)&&(
94
                                ((i_new_pc)&&((r_nvalid == 0)
95
                                        ||(i_pc < r_cache_base)
96
                                        ||(i_pc >= r_cache_base + CACHELEN)))
97
                                ||((r_addr_set)&&((r_addr < r_cache_base)
98
                                        ||(r_addr >= r_cache_base + CACHELEN)))
99
                                        ))
100
                begin
101
                        // Start a bus transaction
102
                        o_wb_cyc <= 1'b1;
103
                        o_wb_stb <= 1'b1;
104
                        o_wb_addr <= (i_new_pc) ? i_pc : r_addr;
105
                        r_acks_waiting <= 0;
106
                        r_nvalid <= 0;
107
                        r_cache_base <= (i_new_pc) ? i_pc : r_addr;
108
                        r_cache_offset <= 0;
109
                end else if ((~o_wb_cyc)&&(r_addr_set)
110
                                        &&(r_addr >= r_cache_base
111
                                                        + (1<<(LGCACHELEN-2))
112
                                                        + (1<<(LGCACHELEN-1))))
113
                begin
114
                        // If we're using the last quarter of the cache, then
115
                        // let's start a bus transaction to extend the cache.
116
                        o_wb_cyc <= 1'b1;
117
                        o_wb_stb <= 1'b1;
118
                        o_wb_addr <= r_cache_base + (1<<(LGCACHELEN));
119
                        r_acks_waiting <= 0;
120
                        r_nvalid <= r_nvalid - (1<<(LGCACHELEN-2));
121
                        r_cache_base <= r_cache_base + (1<<(LGCACHELEN-2));
122
                        r_cache_offset <= r_cache_offset + (1<<(LGCACHELEN-2));
123
                end else if (o_wb_cyc)
124
                begin
125
                        // This handles everything ... but the case where
126
                        // while reading we need to extend our cache.
127
                        if ((o_wb_stb)&&(~i_wb_stall))
128
                        begin
129
                                o_wb_addr <= o_wb_addr + 1;
130
                                if (o_wb_addr - r_cache_base >= CACHELEN-1)
131
                                        o_wb_stb <= 1'b0;
132
                        end
133
 
134
                        if ((o_wb_stb)&&(~i_wb_stall)&&(~i_wb_ack))
135
                                r_acks_waiting <= r_acks_waiting
136
                                                + ((i_wb_ack)? 0:1);
137
                        else if ((i_wb_ack)&&((~o_wb_stb)||(i_wb_stall)))
138
                                r_acks_waiting <= r_acks_waiting - 1;
139
 
140
                        if (i_wb_ack)
141
                        begin
142
                                cache[r_nvalid[(LGCACHELEN-1):0]+c_cache_offset] <= i_wb_data;
143
                                r_nvalid <= r_nvalid + 1;
144
                                if ((r_acks_waiting == 1)&&(~o_wb_stb))
145
                                        o_wb_cyc <= 1'b0;
146
                        end
147
                end
148
        end
149
 
150
        initial r_addr_set = 1'b0;
151
        always @(posedge i_clk)
152
                if (i_rst)
153
                        r_addr_set <= 1'b0;
154
                else if (i_new_pc)
155
                        r_addr_set <= 1'b1;
156
 
157
        // Now, read from the cache
158
        wire    w_cv;   // Cache valid, address is in the cache
159
        reg     r_cv;
160
        assign  w_cv = ((r_nvalid != 0)&&(r_addr>=r_cache_base)
161
                        &&(r_addr-r_cache_base < bus_nvalid));
162
        always @(posedge i_clk)
163
                r_cv <= (~i_new_pc)&&(w_cv);
164
        assign  o_v = (r_cv)&&(~i_new_pc);
165
 
166
        always @(posedge i_clk)
167
                if (i_new_pc)
168
                        r_addr <= i_pc;
169
                else if ((i_stall_n)&&(w_cv))
170
                        r_addr <= r_addr + 1;
171
 
172
        wire    [(LGCACHELEN-1):0]       c_rdaddr, c_cache_base;
173
        assign  c_cache_base   = r_cache_base[(LGCACHELEN-1):0];
174
        assign  c_rdaddr = r_addr[(LGCACHELEN-1):0]-c_cache_base+c_cache_offset;
175
        always @(posedge i_clk)
176
                if (i_stall_n)
177
                        o_i <= cache[c_rdaddr];
178
        always @(posedge i_clk)
179
                if (i_stall_n)
180
                        o_pc <= r_addr;
181
 
182
 
183
endmodule

powered by: WebSVN 2.1.0

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