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

Subversion Repositories zipcpu

[/] [zipcpu/] [trunk/] [rtl/] [core/] [dblfetch.v] - Blame information for rev 205

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

Line No. Rev Author Line
1 205 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    dblfetch.v
4
//
5
// Project:     Zip CPU -- a small, lightweight, RISC CPU soft core
6
//
7
// Purpose:     This is one step beyond the simplest instruction fetch,
8
//              prefetch.v.  dblfetch.v uses memory pipelining to fetch two
9
//      instruction words in one cycle, figuring that the unpipelined CPU can't
10
//      go through both at once, but yet recycles itself fast enough for the
11
//      next instruction that would follow.  It is designed to be a touch
12
//      faster than the single instruction prefetch, although not as fast as
13
//      the prefetch and cache found elsewhere.
14
//
15
//      There are some gotcha's in this logic, however.  For example, it's 
16
//      illegal to switch devices mid-transaction, since the second device
17
//      might have different timing.  I.e. the first device might take 8
18
//      clocks to create an ACK, and the second device might take 2 clocks, the
19
//      acks might therefore come on top of each other, or even out of order.
20
//      But ... in order to keep logic down, we keep track of the PC in the
21
//      o_wb_addr register.  Hence, this register gets changed on any i_new_pc.
22
//      The i_pc value associated with i_new_pc will only be valid for one
23
//      clock, hence we can't wait to change.  To keep from violating the WB
24
//      rule, therefore, we *must* immediately stop requesting any transaction,
25
//      and then terminate the bus request as soon as possible.
26
//
27
//      This has consequences in terms of logic used, leaving this routine
28
//      anything but simple--even though the number of wires affected by
29
//      this is small (o_wb_cyc, o_wb_stb, and last_ack).
30
//
31
//
32
// Creator:     Dan Gisselquist, Ph.D.
33
//              Gisselquist Technology, LLC
34
//
35
////////////////////////////////////////////////////////////////////////////////
36
//
37
// Copyright (C) 2017, Gisselquist Technology, LLC
38
//
39
// This program is free software (firmware): you can redistribute it and/or
40
// modify it under the terms of  the GNU General Public License as published
41
// by the Free Software Foundation, either version 3 of the License, or (at
42
// your option) any later version.
43
//
44
// This program is distributed in the hope that it will be useful, but WITHOUT
45
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
46
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
47
// for more details.
48
//
49
// You should have received a copy of the GNU General Public License along
50
// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no
51
// target there if the PDF file isn't present.)  If not, see
52
// <http://www.gnu.org/licenses/> for a copy.
53
//
54
// License:     GPL, v3, as defined and found on www.gnu.org,
55
//              http://www.gnu.org/licenses/gpl.html
56
//
57
//
58
////////////////////////////////////////////////////////////////////////////////
59
//
60
//
61
module  dblfetch(i_clk, i_rst, i_new_pc, i_clear_cache,
62
                        i_stall_n, i_pc, o_i, o_pc, o_v,
63
                o_wb_cyc, o_wb_stb, o_wb_we, o_wb_addr, o_wb_data,
64
                        i_wb_ack, i_wb_stall, i_wb_err, i_wb_data,
65
                o_illegal);
66
        parameter               ADDRESS_WIDTH=32, AUX_WIDTH = 1;
67
        localparam              AW=ADDRESS_WIDTH;
68
        input                           i_clk, i_rst, i_new_pc, i_clear_cache,
69
                                                i_stall_n;
70
        input           [(AW-1):0]       i_pc;
71
        output  reg     [31:0]           o_i;
72
        output  reg     [(AW-1):0]       o_pc;
73
        output  wire                    o_v;
74
        // Wishbone outputs
75
        output  reg                     o_wb_cyc, o_wb_stb;
76
        output  wire                    o_wb_we;
77
        output  reg     [(AW-1):0]       o_wb_addr;
78
        output  wire    [31:0]           o_wb_data;
79
        // And return inputs
80
        input                   i_wb_ack, i_wb_stall, i_wb_err;
81
        input           [31:0]   i_wb_data;
82
        // And ... the result if we got an error
83
        output  reg             o_illegal;
84
 
85
        assign  o_wb_we = 1'b0;
86
        assign  o_wb_data = 32'h0000;
87
 
88
        reg     last_ack, last_stb, invalid_bus_cycle;
89
 
90
        reg     [31:0]           cache   [0:1];
91
        reg     cache_read_addr, cache_write_addr;
92
        reg     [1:0]            cache_valid;
93
 
94
        initial o_wb_cyc = 1'b0;
95
        initial o_wb_stb = 1'b0;
96
        always @(posedge i_clk)
97
                if ((i_rst)||(i_wb_err))
98
                begin
99
                        o_wb_cyc <= 1'b0;
100
                        o_wb_stb <= 1'b0;
101
                        // last_stb <= 1'b0;
102
                        // last_ack <= 1'b0;
103
                end else if (o_wb_cyc)
104
                begin
105
                        if ((o_wb_stb)&&(!i_wb_stall))
106
                        begin
107
                                // last_stb <= 1'b1;
108
                                o_wb_stb <= !last_stb;
109
                        end
110
                        // if (i_wb_ack)
111
                        //      last_ack <= 1'b1;
112
                        if ((i_new_pc)||(invalid_bus_cycle))
113
                                o_wb_stb <= 1'b0;
114
 
115
                        if ((i_wb_ack)&&(
116
                                // Relase the bus on the second ack
117
                                (last_ack)
118
                                // Or on the first ACK, if we've been told
119
                                // we have an invalid bus cycle
120
                                ||((o_wb_stb)&&(i_wb_stall)&&(last_stb)&&(
121
                                        (i_new_pc)||(invalid_bus_cycle)))
122
                                ))
123
                        begin
124
                                o_wb_cyc <= 1'b0;
125
                                o_wb_stb <= 1'b0;
126
                        end
127
 
128
                        if ((!last_stb)&&(i_wb_stall)&&((i_new_pc)||(invalid_bus_cycle)))
129
                                // Also release the bus with no acks, if we
130
                                // haven't made any requests
131
                        begin
132
                                o_wb_cyc <= 1'b0;
133
                                o_wb_stb <= 1'b0;
134
                        end
135
                end else if ((invalid_bus_cycle)
136
                        ||((o_v)&&(i_stall_n)&&(cache_read_addr))) // Initiate a bus cycle
137
                begin
138
                        o_wb_cyc <= 1'b1;
139
                        o_wb_stb <= 1'b1;
140
                        // last_stb <= 1'b0;
141
                        // last_ack <= 1'b0;
142
                end
143
 
144
        initial last_stb = 1'b0;
145
        always @(posedge i_clk)
146
                if ((o_wb_cyc)&&(o_wb_stb)&&(!i_wb_stall))
147
                        last_stb <= 1'b1;
148
                else if (!o_wb_cyc)
149
                        last_stb <= 1'b0;
150
 
151
        initial last_ack = 1'b0;
152
        always @(posedge i_clk)
153
                if ((o_wb_cyc)&&(i_wb_ack))
154
                        last_ack <= 1'b1;
155
                else if ((o_wb_cyc)&&(o_wb_stb)&&(i_wb_stall)&&(
156
                                (i_new_pc)||(invalid_bus_cycle)))
157
                        last_ack <= 1'b1;
158
                else if ((o_wb_cyc)&&(o_wb_stb)&&(!i_wb_stall)&&(!last_stb)&&(
159
                                (i_new_pc)||(invalid_bus_cycle)))
160
                        last_ack <= 1'b1;
161
                else if (!o_wb_cyc)
162
                        last_ack <= 1'b0;
163
 
164
        initial invalid_bus_cycle = 1'b0;
165
        always @(posedge i_clk)
166
                if (i_rst)
167
                        invalid_bus_cycle <= 1'b0;
168
                else if ((i_new_pc)||(i_clear_cache))
169
                        invalid_bus_cycle <= 1'b1;
170
                else if (!o_wb_cyc)
171
                        invalid_bus_cycle <= 1'b0;
172
 
173
        initial o_wb_addr = {(AW){1'b1}};
174
        always @(posedge i_clk)
175
                if (i_new_pc)
176
                        o_wb_addr <= i_pc;
177
                else if ((o_wb_stb)&&(!i_wb_stall)&&(!invalid_bus_cycle))
178
                        o_wb_addr <= o_wb_addr + 1'b1;
179
 
180
        initial cache_write_addr = 1'b0;
181
        always @(posedge i_clk)
182
                if (!o_wb_cyc)
183
                        cache_write_addr <= 1'b0;
184
                else if ((o_wb_cyc)&&(i_wb_ack))
185
                        cache_write_addr <= cache_write_addr + 1'b1;
186
 
187
        always @(posedge i_clk)
188
                if ((o_wb_cyc)&&(i_wb_ack))
189
                        cache[cache_write_addr] <= i_wb_data;
190
 
191
        initial cache_read_addr = 1'b0;
192
        always @(posedge i_clk)
193
                if ((i_new_pc)||(invalid_bus_cycle)
194
                                ||((o_v)&&(cache_read_addr)&&(i_stall_n)))
195
                        cache_read_addr <= 1'b0;
196
                else if ((o_v)&&(i_stall_n))
197
                        cache_read_addr <= 1'b1;
198
 
199
        always @(posedge i_clk)
200
                if ((i_new_pc)||(invalid_bus_cycle))
201
                        cache_valid <= 2'b00;
202
                else begin
203
                        if ((o_v)&&(i_stall_n))
204
                                cache_valid[cache_read_addr] <= 1'b0;
205
                        if ((o_wb_cyc)&&(i_wb_ack))
206
                                cache_valid[cache_write_addr] <= 1'b1;
207
                end
208
 
209
        initial o_i = {(32){1'b1}};
210
        always @(posedge i_clk)
211
                if ((i_stall_n)&&(o_wb_cyc)&&(i_wb_ack))
212
                        o_i <= i_wb_data;
213
                else
214
                        o_i <= cache[cache_read_addr];
215
 
216
        initial o_pc = 0;
217
        always @(posedge i_clk)
218
                if (i_new_pc)
219
                        o_pc <= i_pc;
220
                else if ((o_v)&&(i_stall_n))
221
                        o_pc <= o_pc + 1'b1;
222
 
223
        assign  o_v = cache_valid[cache_read_addr];
224
 
225
        initial o_illegal = 1'b0;
226
        always @(posedge i_clk)
227
                if ((o_wb_cyc)&&(i_wb_err))
228
                        o_illegal <= 1'b1;
229
                else if ((!o_wb_cyc)&&((i_new_pc)||(invalid_bus_cycle)))
230
                        o_illegal <= 1'b0;
231
 
232
endmodule

powered by: WebSVN 2.1.0

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