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

Subversion Repositories next186

[/] [next186/] [trunk/] [Next186_BIU_2T_delayread.v] - Blame information for rev 2

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

Line No. Rev Author Line
1 2 ndumitrach
//////////////////////////////////////////////////////////////////////////////////
2
//
3
// This file is part of the Next186 project
4
// http://opencores.org/project,next186
5
//
6
// Filename: Next186_BIU_2T_delayread.v
7
// Description: Part of the Next186 CPU project, bus interface unit
8
// Version 1.0
9
// Creation date: 20Jan2012 - 10Mar2012
10
//
11
// Author: Nicolae Dumitrache 
12
// e-mail: ndumitrache@opencores.org
13
//
14
/////////////////////////////////////////////////////////////////////////////////
15
// 
16
// Copyright (C) 2011 Nicolae Dumitrache
17
// 
18
// This source file may be used and distributed without 
19
// restriction provided that this copyright statement is not 
20
// removed from the file and that any derivative work contains 
21
// the original copyright notice and the associated disclaimer.
22
// 
23
// This source file is free software; you can redistribute it 
24
// and/or modify it under the terms of the GNU Lesser General 
25
// Public License as published by the Free Software Foundation;
26
// either version 2.1 of the License, or (at your option) any 
27
// later version. 
28
// 
29
// This source is distributed in the hope that it will be 
30
// useful, but WITHOUT ANY WARRANTY; without even the implied 
31
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
32
// PURPOSE. See the GNU Lesser General Public License for more 
33
// details. 
34
// 
35
// You should have received a copy of the GNU Lesser General 
36
// Public License along with this source; if not, download it 
37
// from http://www.opencores.org/lgpl.shtml 
38
// 
39
///////////////////////////////////////////////////////////////////////////////////
40
// Additional Comments: 
41
//
42
// Description: Next186 Bus Interface Unit, 32bit width SRAM, double CPU frequency (2T), delayed read (1T)
43
// 
44
//      The CPU is able to execute (up to) one instrusction/clock with sepparate data and instruction buses.
45
//      This particular bus interface links the CPU with a 32bit width memory bus and it is able to address up to 1MB. 
46
//      It have a 16byte instruction queue, and works at up to 80Mhz, allowing the CPU to execute an instruction at 2T. It is possible
47
//              to implement a BIU with sepparate data/instruction buses, which will run at the same frequency as the CPU, but it requires more resources.
48
//
49
//      The 32bit data bus width and the double BIU clock allows the instruction queue to be almost always full, avoiding the CPU starving. 
50
//      The data un-alignement penalties are required only when data words crosses the 4byte boundaries.
51
//////////////////////////////////////////////////////////////////////////////////
52
// How to compute each instruction duration, in clock cycles (please note that it is specific to this particular BIU implementation):
53
//
54
//      1 - From the Next186_features.doc see for each instruction how many T states are required (you will notice they are always
55
//              less or equal than 486 and much less than the original 80186
56
// 2 - multiply this number by 2 - the BIU works at double ALU frequency because it needs to multiplex the data and instructions,
57
//              in order to keep the ALU permanently feed with instructions. The 16bit queue acts like a flexible instruction buffer.
58
// 3 - add penalties, as follows:
59
//                      +1T for each memory read - because of the synchronous SRAM which need this extra cycle to deliver the data
60
//                      +2T for each jump - required to flush and re-fill the instruction queue
61
//                      +1T for each 16bit(word) read/write which overlaps the 4byte boundary - specific to 32bit bus width
62
//                      +1T if the jump is made at an address with the latest 2bits 11 - specific to 32bit bus width
63
//                      +1T when the instruction queue empties - this case appears very rare, when a lot of 5-6 bytes memory write 
64
//                              instructions are executed one after the other
65
//              Some examples:
66
//                      - the instruction "inc word ptr [1]" will require 5T (2x2T inc M + 1T read)
67
//                      - the instruction "inc word ptr [3]" will require 7T (2x2T inc M + 1T read + 1T unaligned read + 1T unaligned write)
68
//                      - the instruction "imul ax,bx,234" will require 4T (2x2T imul)
69
//                      - the instruction "loop <address = 1>" will require 4T (2x1T loop + 2T flush)
70
//                      - the instruction "loop <address = 3>" will require 5T (2x1T loop + 2T flush + 1T unaligned jump)
71
//                      - the instruction "call <address = 0>" will require 4T (2x1T call near + 2T flush 
72
//                      - the instruction "ret <address = 0>" will require 5T (2x2T ret + 1T read penalty)
73
//////////////////////////////////////////////////////////////////////////////////
74
 
75
`timescale 1ns / 1ps
76
 
77
 
78
module BIU186_32bSync_2T_DelayRead(
79
        input CLK,
80
        output [47:0]INSTR,
81
        input [2:0]ISIZE,
82
        input IFETCH,
83
        input FLUSH,
84
        input MREQ,
85
        input WR,
86
        input WORD,
87
        input [19:0]ADDR,
88
        input [19:0]IADDR,
89
        output reg CE186,       // CPU clock enable
90
        input [31:0]RAM_DIN,
91
        output [31:0]RAM_DOUT,
92
        output [17:0]RAM_ADDR,
93
        output RAM_MREQ,
94
        output wire[3:0]RAM_WMASK,
95
        output reg [15:0]DOUT,
96
        input [15:0]DIN,
97
        input CE                // BIU clock enable
98
);
99
 
100
        reg [31:0]queue[3:0];
101
        reg [1:0]STATE = 0;
102
        reg OLDSTATE = 1;
103
        reg [3:0]qpos = 0;
104
        reg [4:0]qsize = 0;
105
        reg [1:0]rpos = 0;
106
        reg [17:0]piaddr = 0;
107
        reg [7:0]exdata = 0;
108
        reg rdi = 0;
109
        reg data_bound;
110
 
111
        reg [1:0]NEXTSTATE;
112
        reg RAM_RD;
113
        reg RAM_WR;
114
        reg sflush;
115
        wire [4:0]newqsize = sflush ? -IADDR[1:0] : CE186 && IFETCH && ~FLUSH ? qsize - ISIZE : qsize;
116
        wire qnofull = qsize < 13;
117
        reg iread;// = (qnofull && !RAM_RD && !RAM_WR) || sflush;
118
        wire [3:0]nqpos = (FLUSH && IFETCH) ? {2'b00, IADDR[1:0]} : (qpos + ISIZE);
119
        wire [17:0]MIADDR = sflush ? IADDR[19:2] : piaddr;
120
        wire split = (&ADDR[1:0]) && WORD; // data between dwords
121
        wire [15:0]DSWAP = ADDR[0] ? {DIN[7:0], DIN[15:8]} : DIN;
122
        wire [1:0]a1 = nqpos[3:2] + 1;
123
        wire [1:0]a2 = nqpos[3:2] + 2;
124
        wire [31:0]q1 = rdi && (a1 == rpos) ? RAM_DIN : queue[a1];
125
        wire [7:0]q2 = rdi && (a2 == rpos) ? RAM_DIN[7:0] : queue[a2][7:0];
126
 
127
        assign INSTR = {q2, q1, queue[nqpos[3:2]]} >> {nqpos[1:0], 3'b000};
128
//      assign DOUT = split ? {RAM_DIN[7:0], exdata} : (RAM_DIN >> {ADDR[1:0], 3'b000}); 
129
        assign RAM_DOUT = {DSWAP, DSWAP};
130
        assign RAM_MREQ = iread || RAM_RD || RAM_WR;
131
        assign RAM_ADDR = iread ? MIADDR : ADDR[19:2] + data_bound;
132
        assign RAM_WMASK = data_bound ? {3'b000, RAM_WR} : {2'b00, WORD & RAM_WR, RAM_WR} << ADDR[1:0];
133
 
134
        always @(*) begin
135
                RAM_RD = 0;
136
                RAM_WR = 0;
137
                CE186 = 0;
138
                sflush = 0;
139
                data_bound = 0;
140
                iread = 0;
141
 
142
                case(ADDR[1:0])
143
                        2'b00: DOUT = RAM_DIN[15:0];
144
                        2'b01: DOUT = RAM_DIN[23:8];
145
                        2'b10: DOUT = RAM_DIN[31:16];
146
                        2'b11: DOUT = {RAM_DIN[7:0], WORD ? exdata : RAM_DIN[31:24]};
147
                endcase
148
 
149
                case(STATE)
150
                        0: begin // no cpu activity on first state
151
                                iread = qnofull;
152
                                NEXTSTATE = 1;
153
                        end
154
                        1: begin
155
                                NEXTSTATE = 1;
156
                                if(FLUSH && IFETCH && !OLDSTATE) begin
157
                                        sflush = 1;
158
                                        iread = 1;
159
                                end else if((FLUSH && IFETCH && (qsize > 5)) || (qsize > 11)) begin
160
                                        NEXTSTATE = 0;
161
                                        if(MREQ) begin
162
                                                if(WR) begin    // write
163
                                                        RAM_WR = 1;
164
                                                        if(split) NEXTSTATE = 3;
165
                                                        else CE186 = 1;
166
                                                end else begin
167
                                                        RAM_RD = 1;
168
                                                        NEXTSTATE = split ? 2 : 3;
169
                                                end
170
                                        end else begin
171
                                                iread = qnofull;
172
                                                CE186 = 1;
173
                                        end
174
                                end else iread = 1; // else nextstate = 1
175
                        end
176
                        2: begin
177
                                RAM_RD = 1;
178
                                data_bound = 1; // split memory access
179
                                NEXTSTATE = 3;
180
                        end
181
                        3: begin
182
                                RAM_WR = WR && MREQ;
183
                                iread = !(WR && MREQ) && qnofull;
184
                                data_bound = split;
185
                                CE186 = 1;
186
                                NEXTSTATE = 0;
187
                        end
188
                endcase
189
        end
190
 
191
        always @ (posedge CLK) if(CE) begin
192
                rdi <= iread;
193
                if(rdi) queue[rpos] <= RAM_DIN;
194
                if(iread) begin
195
                        qsize <= {newqsize[4:2] + 1, newqsize[1:0]};
196
                        piaddr <= MIADDR + 1;
197
                end else begin
198
                        qsize <= newqsize;
199
                        piaddr <= MIADDR;
200
                end
201
                if(CE186 && IFETCH) qpos <= nqpos;
202
                if(sflush) rpos <= 0;
203
                else if(rdi) rpos <= rpos + 1;
204
                OLDSTATE <= STATE[0];
205
                STATE <= NEXTSTATE;
206
                if(data_bound) exdata <= RAM_DIN[31:24];
207
        end
208
 
209
endmodule
210
 

powered by: WebSVN 2.1.0

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