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

Subversion Repositories zipcpu

[/] [zipcpu/] [trunk/] [rtl/] [peripherals/] [flashcache.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:    flashcache.v
4
//
5
// Project:     Zip CPU -- a small, lightweight, RISC CPU soft core
6
//
7
// Purpose:     Since my Zip CPU has primary access to a flash, which requires
8
//              nearly 24 clock cycles per read, this 'cache' module
9
//              is offered to minimize the effect.  The CPU may now request
10
//              some amount of flash to be copied into this on-chip RAM,
11
//              and then access it with nearly zero latency.
12
//
13
// Interface:
14
//      FlashCache sits on the Wishbone bus as both a slave and a master.
15
//      Slave requests for memory will get mapped to a local RAM, from which
16
//      reads and writes may take place.
17
//
18
//      This cache supports a single control register: the base wishbone address
19
//      of the device to copy memory from.  The bottom bit if this address must
20
//      be zero (or it will be silently rendered as zero).  When read, this
21
//      bottom bit will indicate 1) that the controller is still loading memory
22
//      into the cache, or 0) that the cache is ready to be used.
23
//
24
//      Writing to this register will initiate a memory copy from the (new)
25
//      address.  Once done, the loading bit will be cleared and an interrupt
26
//      generated.
27
//
28
//      Where this memory is placed on the wishbone bus is entirely up to the
29
//              wishbone bus control logic.  Setting the memory base to an
30
//              address controlled by this flashcache will produce unusable
31
//              results, and may well hang the bus.
32
//      Reads from the memory before complete will return immediately with
33
//              the value if read address is less than the current copy
34
//              address, or else they will stall until the read address is
35
//              less than the copy address.
36
//
37
// Creator:     Dan Gisselquist, Ph.D.
38
//              Gisselquist Tecnology, LLC
39
//
40
///////////////////////////////////////////////////////////////////////////
41
//
42
// Copyright (C) 2015, Gisselquist Technology, LLC
43
//
44
// This program is free software (firmware): you can redistribute it and/or
45
// modify it under the terms of  the GNU General Public License as published
46
// by the Free Software Foundation, either version 3 of the License, or (at
47
// your option) any later version.
48
//
49
// This program is distributed in the hope that it will be useful, but WITHOUT
50
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
51
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
52
// for more details.
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
module  flashcache(i_clk,
61
                // Wishbone contrl interface
62
                i_wb_cyc, i_wb_stb,i_wb_ctrl_stb, i_wb_we, i_wb_addr, i_wb_data,
63
                        o_wb_ack, o_wb_stall, o_wb_data,
64
                // Wishbone copy interface
65
                o_cp_cyc, o_cp_stb, o_cp_we, o_cp_addr, o_cp_data,
66
                        i_cp_ack, i_cp_stall, i_cp_data,
67
                o_int);
68
        parameter       LGCACHELEN=10; // 4 kB
69
        input                   i_clk;
70
        // Control interface, CPU interface to cache
71
        input                   i_wb_cyc, i_wb_stb,i_wb_ctrl_stb, i_wb_we;
72
        input           [(LGCACHELEN-1):0]       i_wb_addr;
73
        input           [31:0]   i_wb_data;
74
        output  reg             o_wb_ack;
75
        output  wire            o_wb_stall;
76
        output  wire    [31:0]   o_wb_data;
77
        // Interface to peripheral bus, including flash
78
        output  reg             o_cp_cyc, o_cp_stb;
79
        output  wire            o_cp_we;
80
        output  reg     [31:0]   o_cp_addr;
81
        output  wire    [31:0]   o_cp_data;
82
        input                   i_cp_ack, i_cp_stall;
83
        input           [31:0]   i_cp_data;
84
        // And an interrupt to send once we complete
85
        output  reg             o_int;
86
 
87
        reg             loading;
88
        reg     [31:0]   cache_base;
89
        reg     [31:0]   cache   [0:((1<<LGCACHELEN)-1)];
90
 
91
        // Decouple writing the cache base from the highly delayed bus lines
92
        reg             wr_cache_base_flag;
93
        reg     [31:0]   wr_cache_base_value;
94
        always @(posedge i_clk)
95
                wr_cache_base_flag <= ((i_wb_cyc)&&(i_wb_ctrl_stb)&&(i_wb_we));
96
        always @(posedge i_clk)
97
                wr_cache_base_value<= { i_wb_data[31:1], 1'b0 };
98
 
99
        initial cache_base = 32'hffffffff;
100
        always @(posedge i_clk)
101
                if (wr_cache_base_flag)
102
                        cache_base <= wr_cache_base_value;
103
 
104
        reg     new_cache_base;
105
        initial new_cache_base = 1'b0;
106
        always @(posedge i_clk)
107
                if ((wr_cache_base_flag)&&(cache_base != wr_cache_base_value))
108
                        new_cache_base <= 1'b1;
109
                else
110
                        new_cache_base <= 1'b0;
111
 
112
        reg     [(LGCACHELEN-1):0]       rdaddr;
113
        initial loading = 1'b0;
114
        always @(posedge i_clk)
115
                if (new_cache_base)
116
                begin
117
                        loading <= 1'b1;
118
                        o_cp_cyc <= 1'b0;
119
                end else if ((~o_cp_cyc)&&(loading))
120
                begin
121
                        o_cp_cyc <= 1'b1;
122
                end else if (o_cp_cyc)
123
                begin
124
                        // Handle the ack/read line
125
                        if (i_cp_ack)
126
                        begin
127
                                if (&rdaddr)
128
                                begin
129
                                        o_cp_cyc <= 1'b0;
130
                                        loading <= 1'b0;
131
                                end
132
                        end
133
                end
134
        always @(posedge i_clk)
135
                if (~o_cp_cyc)
136
                        o_cp_addr <= cache_base;
137
                else if ((o_cp_cyc)&&(o_cp_stb)&&(~i_cp_stall))
138
                        o_cp_addr <= o_cp_addr + 1;;
139
        always @(posedge i_clk)
140
                if ((~o_cp_cyc)&&(loading))
141
                        o_cp_stb  <= 1'b1;
142
                else if ((o_cp_cyc)&&(o_cp_stb)&&(~i_cp_stall))
143
                begin
144
                        // We've made our last request
145
                        if (o_cp_addr >= cache_base + { {(32-LGCACHELEN-1){1'b0}}, 1'b1, {(LGCACHELEN){1'b0}}})
146
                                o_cp_stb <= 1'b0;
147
                end
148
        always @(posedge i_clk)
149
                if (~loading)
150
                        rdaddr    <= 0;
151
                else if ((o_cp_cyc)&&(i_cp_ack))
152
                        rdaddr <= rdaddr + 1;
153
 
154
        initial o_int = 1'b0;
155
        always @(posedge i_clk)
156
                if ((o_cp_cyc)&&(i_cp_ack)&&(&rdaddr))
157
                        o_int <= 1'b1;
158
                else
159
                        o_int <= 1'b0;
160
 
161
        assign  o_cp_we = 1'b0;
162
        assign  o_cp_data = 32'h00;
163
 
164
 
165
        //
166
        //      Writes to our cache ... always delayed by a clock.
167
        //              Clock 0 :       Write request
168
        //              Clock 1 :       Write takes place
169
        //              Clock 2 :       Available for reading
170
        //
171
        reg                             we;
172
        reg     [(LGCACHELEN-1):0]       waddr;
173
        reg     [31:0]                   wval;
174
        always @(posedge i_clk)
175
                we <= (loading)?((o_cp_cyc)&&(i_cp_ack)):(i_wb_cyc)&&(i_wb_stb)&&(i_wb_we);
176
        always @(posedge i_clk)
177
                waddr <= (loading)?rdaddr:i_wb_addr;
178
        always @(posedge i_clk)
179
                wval <= (loading)?i_cp_data:i_wb_data;
180
 
181
        always @(posedge i_clk)
182
                if (we)
183
                        cache[waddr] <= wval;
184
 
185
        reg     [31:0]   cache_data;
186
        always @(posedge i_clk)
187
                if ((i_wb_cyc)&&(i_wb_stb))
188
                        cache_data <= cache[i_wb_addr];
189
 
190
        always @(posedge i_clk)
191
                o_wb_ack <= (i_wb_cyc)&&(
192
                                ((i_wb_stb)&&(~loading))
193
                                ||(i_wb_ctrl_stb));
194
        reg     ctrl;
195
        always @(posedge i_clk)
196
                ctrl <= i_wb_ctrl_stb;
197
        assign  o_wb_data = (ctrl)?({cache_base[31:1],loading}):cache_data;
198
        assign  o_wb_stall = (loading)&&(~o_wb_ack);
199
 
200
endmodule

powered by: WebSVN 2.1.0

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