OpenCores
URL https://opencores.org/ocsvn/an-fpga-implementation-of-low-latency-noc-based-mpsoc/an-fpga-implementation-of-low-latency-noc-based-mpsoc/trunk

Subversion Repositories an-fpga-implementation-of-low-latency-noc-based-mpsoc

[/] [an-fpga-implementation-of-low-latency-noc-based-mpsoc/] [trunk/] [mpsoc/] [src_processor/] [mor1kx-3.1/] [rtl/] [verilog/] [mor1kx_lsu_espresso.v] - Blame information for rev 38

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 38 alirezamon
/* ****************************************************************************
2
  This Source Code Form is subject to the terms of the
3
  Open Hardware Description License, v. 1.0. If a copy
4
  of the OHDL was not distributed with this file, You
5
  can obtain one at http://juliusbaxter.net/ohdl/ohdl.txt
6
 
7
  Description:  Load, store unit for espresso pipeline
8
 
9
  All combinatorial outputs to pipeline
10
  Dbus interface request signal out synchronous
11
 
12
  32-bit specific due to sign extension of results
13
 
14
  Copyright (C) 2012 Authors
15
 
16
   Author(s): Julius Baxter <juliusbaxter@gmail.com>
17
 
18
***************************************************************************** */
19
 
20
`include "mor1kx-defines.v"
21
 
22
module mor1kx_lsu_espresso
23
  (/*AUTOARG*/
24
   // Outputs
25
   lsu_result_o, lsu_valid_o, lsu_except_dbus_o, lsu_except_align_o,
26
   dbus_adr_o, dbus_req_o, dbus_dat_o, dbus_bsel_o, dbus_we_o,
27
   dbus_burst_o,
28
   // Inputs
29
   clk, rst, padv_fetch_i, lsu_adr_i, rfb_i, op_lsu_load_i,
30
   op_lsu_store_i, lsu_length_i, lsu_zext_i, exception_taken_i,
31
   du_restart_i, stepping_i, next_fetch_done_i, dbus_err_i,
32
   dbus_ack_i, dbus_dat_i
33
   );
34
 
35
   parameter OPTION_OPERAND_WIDTH = 32;
36
   parameter OPTION_REGISTERED_IO = "NO";
37
 
38
   input clk, rst;
39
 
40
   input padv_fetch_i;
41
   // calculated address from ALU
42
   input [OPTION_OPERAND_WIDTH-1:0] lsu_adr_i;
43
 
44
   // register file B in (store operand)
45
   input [OPTION_OPERAND_WIDTH-1:0] rfb_i;
46
   // from decode stage regs, indicate if load or store
47
   input                            op_lsu_load_i;
48
   input                            op_lsu_store_i;
49
   input [1:0]                       lsu_length_i;
50
   input                            lsu_zext_i;
51
 
52
   input                            exception_taken_i;
53
   input                            du_restart_i;
54
   input                            stepping_i;
55
   input                            next_fetch_done_i;
56
 
57
 
58
   output [OPTION_OPERAND_WIDTH-1:0] lsu_result_o;
59
   output                            lsu_valid_o;
60
   // exception output
61
   output                            lsu_except_dbus_o;
62
   output                            lsu_except_align_o;
63
 
64
   // interface to data bus
65
   output [OPTION_OPERAND_WIDTH-1:0] dbus_adr_o;
66
   output                            dbus_req_o;
67
   output [OPTION_OPERAND_WIDTH-1:0] dbus_dat_o;
68
   output [3:0]               dbus_bsel_o;
69
   output                            dbus_we_o;
70
   output                            dbus_burst_o;
71
   input                             dbus_err_i;
72
   input                             dbus_ack_i;
73
   input [OPTION_OPERAND_WIDTH-1:0]  dbus_dat_i;
74
 
75
   reg [OPTION_OPERAND_WIDTH-1:0]    dbus_dat_aligned;  // comb.
76
   reg [OPTION_OPERAND_WIDTH-1:0]    dbus_dat_extended; // comb.
77
 
78
 
79
   reg [OPTION_OPERAND_WIDTH-1:0]    dbus_adr_r;
80
 
81
   reg [3:0]                          dbus_bsel;
82
 
83
   reg                               dbus_err_r;
84
 
85
   reg                               access_done;
86
 
87
   reg [OPTION_OPERAND_WIDTH-1:0]    lsu_result_r;
88
 
89
   reg                               op_lsu;
90
 
91
   wire                              align_err_word;
92
   wire                              align_err_short;
93
 
94
   wire                              align_err;
95
 
96
   wire                              except_align;
97
   reg                               except_align_r;
98
 
99
   reg                               except_dbus;
100
   reg                               execute_go;
101
 
102
   assign dbus_dat_o = (lsu_length_i == 2'b00) ? // byte access
103
                       {rfb_i[7:0],rfb_i[7:0],rfb_i[7:0],rfb_i[7:0]} :
104
                       (lsu_length_i == 2'b01) ? // halfword access
105
                       {rfb_i[15:0],rfb_i[15:0]} :
106
                       rfb_i;                    // word access
107
 
108
   assign align_err_word = |dbus_adr_o[1:0];
109
   assign align_err_short = dbus_adr_o[0];
110
 
111
 
112
   assign lsu_valid_o = dbus_ack_i | dbus_err_r| access_done;
113
   assign lsu_except_dbus_o = dbus_err_r | except_dbus;
114
 
115
   assign align_err = (lsu_length_i == 2'b10) & align_err_word |
116
                      (lsu_length_i == 2'b01) & align_err_short;
117
 
118
   assign lsu_except_align_o = except_align_r;
119
 
120
   always @(posedge clk `OR_ASYNC_RST)
121
     if (rst)
122
       execute_go <= 0;
123
     else
124
       execute_go <= padv_fetch_i | (stepping_i & next_fetch_done_i);
125
 
126
   always @(posedge clk `OR_ASYNC_RST)
127
     if (rst)
128
       access_done <= 0;
129
     else if (padv_fetch_i | du_restart_i)
130
       access_done <= 0;
131
     else if (dbus_ack_i | dbus_err_r | lsu_except_align_o)
132
       access_done <= 1;
133
 
134
   always @(posedge clk `OR_ASYNC_RST)
135
     if (rst)
136
       except_align_r <= 0;
137
     else if (exception_taken_i)
138
       except_align_r <= 0;
139
     else
140
       except_align_r <= except_align;
141
 
142
   always @(posedge clk `OR_ASYNC_RST)
143
     if (rst)
144
       except_dbus <= 0;
145
     else if (exception_taken_i)
146
       except_dbus <= 0;
147
     else if (dbus_err_r)
148
       except_dbus <= 1;
149
 
150
   // Need to register address due to behavior of RF when source register is
151
   // same as destination register - value changes after one cycle to the
152
   // forwarding register's value, which is incorrect.
153
   // So we save it on first cycle.
154
   // TODO - perhaps detect in RF when this is case, and make it keep the
155
   // output steady to avoid an extra address registering stage here.
156
   always @(posedge clk `OR_ASYNC_RST)
157
     if (rst)
158
       dbus_adr_r <= 0;
159
     else if (execute_go & (op_lsu_load_i | op_lsu_store_i))
160
       dbus_adr_r <= lsu_adr_i;
161
 
162
   // Big endian bus mapping
163
   always @(*)
164
     case (lsu_length_i)
165
       2'b00: // byte access
166
         case(dbus_adr_o[1:0])
167
           2'b00:
168
             dbus_bsel = 4'b1000;
169
           2'b01:
170
             dbus_bsel = 4'b0100;
171
           2'b10:
172
             dbus_bsel = 4'b0010;
173
           2'b11:
174
             dbus_bsel = 4'b0001;
175
         endcase
176
       2'b01: // halfword access
177
            case(dbus_adr_o[1])
178
              1'b0:
179
                dbus_bsel = 4'b1100;
180
              1'b1:
181
                dbus_bsel = 4'b0011;
182
            endcase
183
       2'b10,
184
       2'b11:
185
         dbus_bsel = 4'b1111;
186
     endcase
187
 
188
   assign dbus_bsel_o = dbus_bsel;
189
 
190
   assign dbus_we_o =  op_lsu_store_i;
191
 
192
   // Select part of read word
193
   // Can use registered address here, as it'll take at least one cycle for
194
   // the data to come back, and by that time dbus_adr_r has the address
195
   always @*
196
     case(dbus_adr_r[1:0])
197
       2'b00:
198
         dbus_dat_aligned = dbus_dat_i;
199
       2'b01:
200
         dbus_dat_aligned = {dbus_dat_i[23:0],8'd0};
201
       2'b10:
202
         dbus_dat_aligned = {dbus_dat_i[15:0],16'd0};
203
       2'b11:
204
         dbus_dat_aligned = {dbus_dat_i[7:0],24'd0};
205
     endcase // case (dbus_adr_r[1:0])
206
 
207
   // Do appropriate extension
208
   always @(*)
209
     case({lsu_zext_i, lsu_length_i})
210
       3'b100: // lbz
211
         dbus_dat_extended = {24'd0,dbus_dat_aligned[31:24]};
212
       3'b101: // lhz
213
         dbus_dat_extended = {16'd0,dbus_dat_aligned[31:16]};
214
       3'b000: // lbs
215
         dbus_dat_extended = {{24{dbus_dat_aligned[31]}},
216
                              dbus_dat_aligned[31:24]};
217
       3'b001: // lhs
218
         dbus_dat_extended = {{16{dbus_dat_aligned[31]}},
219
                              dbus_dat_aligned[31:16]};
220
       default:
221
         dbus_dat_extended = dbus_dat_aligned;
222
     endcase
223
 
224
   // Register result incase writeback doesn't occur for a few cycles
225
   // TODO - remove this - we should write straight into the RF!
226
   always @(posedge clk)
227
     if (dbus_ack_i & op_lsu_load_i)
228
       lsu_result_r <= dbus_dat_extended;
229
 
230
   assign dbus_burst_o = 0;
231
 
232
   // Break up paths of signals which are usually pretty long
233
   generate
234
      if (OPTION_REGISTERED_IO!="NO")
235
        begin : registered_io
236
 
237
           assign dbus_adr_o = dbus_adr_r;
238
 
239
           always @(posedge clk)
240
             begin
241
                dbus_err_r <= dbus_err_i;
242
                op_lsu <=  op_lsu_load_i | op_lsu_store_i;
243
             end
244
 
245
           // Make sure padv_i isn't high because we'll be registering the
246
           // fact that this cycle is an LSU op while it is
247
           assign dbus_req_o = !execute_go & op_lsu &
248
                               !(except_align | except_align_r) &
249
                               !access_done;
250
 
251
           assign except_align = op_lsu & (op_lsu_load_i | op_lsu_store_i) &
252
                                 align_err & !execute_go;
253
 
254
        end
255
      else
256
        begin : nonregistered_io
257
 
258
           assign dbus_adr_o = execute_go ? lsu_adr_i : dbus_adr_r;
259
 
260
           always @*
261
             begin
262
                dbus_err_r = dbus_err_i;
263
                op_lsu =  op_lsu_load_i | op_lsu_store_i;
264
             end
265
 
266
           assign dbus_req_o = op_lsu & !except_align & !access_done;
267
 
268
           assign except_align = op_lsu & align_err;
269
 
270
        end
271
   endgenerate
272
 
273
   assign lsu_result_o = access_done ? lsu_result_r : dbus_dat_extended;
274
 
275
endmodule // mor1kx_lsu

powered by: WebSVN 2.1.0

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