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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1200/] [rtl/] [verilog/] [or1200_lsu.v] - Blame information for rev 258

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

Line No. Rev Author Line
1 10 unneback
//////////////////////////////////////////////////////////////////////
2
////                                                              ////
3
////  OR1200's Load/Store unit                                    ////
4
////                                                              ////
5
////  This file is part of the OpenRISC 1200 project              ////
6 258 julius
////  http://opencores.org/project,or1k                           ////
7 10 unneback
////                                                              ////
8
////  Description                                                 ////
9
////  Interface between CPU and DC.                               ////
10
////                                                              ////
11
////  To Do:                                                      ////
12
////   - make it smaller and faster                               ////
13
////                                                              ////
14
////  Author(s):                                                  ////
15
////      - Damjan Lampret, lampret@opencores.org                 ////
16
////                                                              ////
17
//////////////////////////////////////////////////////////////////////
18
////                                                              ////
19
//// Copyright (C) 2000 Authors and OPENCORES.ORG                 ////
20
////                                                              ////
21
//// This source file may be used and distributed without         ////
22
//// restriction provided that this copyright statement is not    ////
23
//// removed from the file and that any derivative work contains  ////
24
//// the original copyright notice and the associated disclaimer. ////
25
////                                                              ////
26
//// This source file is free software; you can redistribute it   ////
27
//// and/or modify it under the terms of the GNU Lesser General   ////
28
//// Public License as published by the Free Software Foundation; ////
29
//// either version 2.1 of the License, or (at your option) any   ////
30
//// later version.                                               ////
31
////                                                              ////
32
//// This source is distributed in the hope that it will be       ////
33
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
34
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
35
//// PURPOSE.  See the GNU Lesser General Public License for more ////
36
//// details.                                                     ////
37
////                                                              ////
38
//// You should have received a copy of the GNU Lesser General    ////
39
//// Public License along with this source; if not, download it   ////
40
//// from http://www.opencores.org/lgpl.shtml                     ////
41
////                                                              ////
42
//////////////////////////////////////////////////////////////////////
43
//
44
//
45 141 marcus.erl
// $Log: or1200_lsu.v,v $
46
// Revision 2.0  2010/06/30 11:00:00  ORSoC
47
// Major update: 
48
// Structure reordered and bugs fixed. 
49
//
50 10 unneback
 
51
// synopsys translate_off
52
`include "timescale.v"
53
// synopsys translate_on
54
`include "or1200_defines.v"
55
 
56
module or1200_lsu(
57 141 marcus.erl
        // Clock and Reset
58
        clk, rst,
59 10 unneback
 
60
        // Internal i/f
61 141 marcus.erl
        id_addrbase, ex_addrbase, id_addrofs, ex_addrofs, id_lsu_op,
62
        lsu_datain, lsu_dataout, lsu_stall, lsu_unstall,
63
        du_stall, except_align, except_dtlbmiss, except_dmmufault, except_dbuserr,
64
        id_freeze, ex_freeze, flushpipe,
65 10 unneback
 
66
        // External i/f to DC
67
        dcpu_adr_o, dcpu_cycstb_o, dcpu_we_o, dcpu_sel_o, dcpu_tag_o, dcpu_dat_o,
68
        dcpu_dat_i, dcpu_ack_i, dcpu_rty_i, dcpu_err_i, dcpu_tag_i
69
);
70
 
71
parameter dw = `OR1200_OPERAND_WIDTH;
72
parameter aw = `OR1200_REGFILE_ADDR_WIDTH;
73
 
74
//
75
// I/O
76
//
77
 
78
//
79 141 marcus.erl
// Clock and reset
80
//
81
input                           clk;
82
input                           rst;
83
 
84
//
85 10 unneback
// Internal i/f
86
//
87 141 marcus.erl
input   [31:0]                   id_addrbase;
88
input   [31:0]                   ex_addrbase;
89
input   [31:0]                   id_addrofs;
90
input   [31:0]                   ex_addrofs;
91
input   [`OR1200_LSUOP_WIDTH-1:0] id_lsu_op;
92 10 unneback
input   [dw-1:0]         lsu_datain;
93
output  [dw-1:0]         lsu_dataout;
94
output                          lsu_stall;
95
output                          lsu_unstall;
96
input                           du_stall;
97
output                          except_align;
98
output                          except_dtlbmiss;
99
output                          except_dmmufault;
100
output                          except_dbuserr;
101 141 marcus.erl
input                           id_freeze;
102
input                           ex_freeze;
103
input                           flushpipe;
104 10 unneback
 
105
//
106
// External i/f to DC
107
//
108
output  [31:0]                   dcpu_adr_o;
109
output                          dcpu_cycstb_o;
110
output                          dcpu_we_o;
111
output  [3:0]                    dcpu_sel_o;
112
output  [3:0]                    dcpu_tag_o;
113
output  [31:0]                   dcpu_dat_o;
114
input   [31:0]                   dcpu_dat_i;
115
input                           dcpu_ack_i;
116
input                           dcpu_rty_i;
117
input                           dcpu_err_i;
118
input   [3:0]                    dcpu_tag_i;
119
 
120
//
121
// Internal wires/regs
122
//
123
reg     [3:0]                    dcpu_sel_o;
124
 
125 141 marcus.erl
reg     [`OR1200_LSUOP_WIDTH-1:0] ex_lsu_op;
126
wire    [`OR1200_LSUEA_PRECALC:0] id_precalc_sum;
127
reg     [`OR1200_LSUEA_PRECALC:0] dcpu_adr_r;
128
reg                             except_align;
129
 
130 10 unneback
//
131 141 marcus.erl
// ex_lsu_op
132
//
133
always @(posedge clk or posedge rst) begin
134
    if (rst)
135 258 julius
        ex_lsu_op <=  `OR1200_LSUOP_NOP;
136 141 marcus.erl
    else if (!ex_freeze & id_freeze | flushpipe)
137 258 julius
        ex_lsu_op <=  `OR1200_LSUOP_NOP;
138 141 marcus.erl
    else if (!ex_freeze)
139 258 julius
        ex_lsu_op <=  id_lsu_op;
140 141 marcus.erl
end
141
 
142
//
143
// Precalculate part of load/store EA in ID stage
144
//
145
assign id_precalc_sum = id_addrbase[`OR1200_LSUEA_PRECALC-1:0] +
146
                        id_addrofs[`OR1200_LSUEA_PRECALC-1:0];
147
 
148
always @(posedge clk or posedge rst) begin
149
    if (rst)
150 258 julius
        dcpu_adr_r <=  {`OR1200_LSUEA_PRECALC{1'b0}};
151 141 marcus.erl
    else if (!ex_freeze)
152 258 julius
        dcpu_adr_r <=  id_precalc_sum;
153 141 marcus.erl
end
154
 
155
//
156
// Generate except_align in ID stage
157
//
158
always @(posedge clk or posedge rst) begin
159
    if (rst)
160 258 julius
        except_align <=  1'b0;
161 141 marcus.erl
    else if (!ex_freeze & id_freeze | flushpipe)
162 258 julius
        except_align <=  1'b0;
163 141 marcus.erl
    else if (!ex_freeze)
164 258 julius
        except_align <=  ((id_lsu_op == `OR1200_LSUOP_SH) |
165 141 marcus.erl
                            (id_lsu_op == `OR1200_LSUOP_LHZ) |
166
                            (id_lsu_op == `OR1200_LSUOP_LHS)) & id_precalc_sum[0]
167
                        |  ((id_lsu_op == `OR1200_LSUOP_SW) |
168
                            (id_lsu_op == `OR1200_LSUOP_LWZ) |
169
                            (id_lsu_op == `OR1200_LSUOP_LWS)) & |id_precalc_sum[1:0];
170
end
171
 
172
//
173 10 unneback
// Internal I/F assignments
174
//
175
assign lsu_stall = dcpu_rty_i & dcpu_cycstb_o;
176
assign lsu_unstall = dcpu_ack_i;
177
assign except_dtlbmiss = dcpu_err_i & (dcpu_tag_i == `OR1200_DTAG_TE);
178
assign except_dmmufault = dcpu_err_i & (dcpu_tag_i == `OR1200_DTAG_PE);
179
assign except_dbuserr = dcpu_err_i & (dcpu_tag_i == `OR1200_DTAG_BE);
180
 
181
//
182
// External I/F assignments
183
//
184 258 julius
assign dcpu_adr_o[31:`OR1200_LSUEA_PRECALC] = ex_addrbase[31:`OR1200_LSUEA_PRECALC] + ex_addrofs[31:`OR1200_LSUEA_PRECALC] +  dcpu_adr_r[`OR1200_LSUEA_PRECALC]; // carry
185 141 marcus.erl
assign dcpu_adr_o[`OR1200_LSUEA_PRECALC-1:0] = dcpu_adr_r[`OR1200_LSUEA_PRECALC-1:0];
186 258 julius
assign dcpu_cycstb_o = du_stall | lsu_unstall | except_align ?
187
                       1'b0 : |ex_lsu_op;
188 141 marcus.erl
assign dcpu_we_o = ex_lsu_op[3];
189 10 unneback
assign dcpu_tag_o = dcpu_cycstb_o ? `OR1200_DTAG_ND : `OR1200_DTAG_IDLE;
190 141 marcus.erl
always @(ex_lsu_op or dcpu_adr_o)
191
        casex({ex_lsu_op, dcpu_adr_o[1:0]})
192 10 unneback
                {`OR1200_LSUOP_SB, 2'b00} : dcpu_sel_o = 4'b1000;
193
                {`OR1200_LSUOP_SB, 2'b01} : dcpu_sel_o = 4'b0100;
194
                {`OR1200_LSUOP_SB, 2'b10} : dcpu_sel_o = 4'b0010;
195
                {`OR1200_LSUOP_SB, 2'b11} : dcpu_sel_o = 4'b0001;
196
                {`OR1200_LSUOP_SH, 2'b00} : dcpu_sel_o = 4'b1100;
197
                {`OR1200_LSUOP_SH, 2'b10} : dcpu_sel_o = 4'b0011;
198
                {`OR1200_LSUOP_SW, 2'b00} : dcpu_sel_o = 4'b1111;
199
                {`OR1200_LSUOP_LBZ, 2'b00}, {`OR1200_LSUOP_LBS, 2'b00} : dcpu_sel_o = 4'b1000;
200
                {`OR1200_LSUOP_LBZ, 2'b01}, {`OR1200_LSUOP_LBS, 2'b01} : dcpu_sel_o = 4'b0100;
201
                {`OR1200_LSUOP_LBZ, 2'b10}, {`OR1200_LSUOP_LBS, 2'b10} : dcpu_sel_o = 4'b0010;
202
                {`OR1200_LSUOP_LBZ, 2'b11}, {`OR1200_LSUOP_LBS, 2'b11} : dcpu_sel_o = 4'b0001;
203
                {`OR1200_LSUOP_LHZ, 2'b00}, {`OR1200_LSUOP_LHS, 2'b00} : dcpu_sel_o = 4'b1100;
204
                {`OR1200_LSUOP_LHZ, 2'b10}, {`OR1200_LSUOP_LHS, 2'b10} : dcpu_sel_o = 4'b0011;
205
                {`OR1200_LSUOP_LWZ, 2'b00}, {`OR1200_LSUOP_LWS, 2'b00} : dcpu_sel_o = 4'b1111;
206
                default : dcpu_sel_o = 4'b0000;
207
        endcase
208
 
209
//
210
// Instantiation of Memory-to-regfile aligner
211
//
212
or1200_mem2reg or1200_mem2reg(
213
        .addr(dcpu_adr_o[1:0]),
214 141 marcus.erl
        .lsu_op(ex_lsu_op),
215 10 unneback
        .memdata(dcpu_dat_i),
216
        .regdata(lsu_dataout)
217
);
218
 
219
//
220
// Instantiation of Regfile-to-memory aligner
221
//
222
or1200_reg2mem or1200_reg2mem(
223
        .addr(dcpu_adr_o[1:0]),
224 141 marcus.erl
        .lsu_op(ex_lsu_op),
225 10 unneback
        .regdata(lsu_datain),
226
        .memdata(dcpu_dat_o)
227
);
228
 
229
endmodule

powered by: WebSVN 2.1.0

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