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

Subversion Repositories yifive

[/] [yifive/] [trunk/] [caravel_yifive/] [verilog/] [rtl/] [syntacore/] [scr1/] [src/] [top/] [scr1_dmem_ahb.sv] - Blame information for rev 21

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 11 dinesha
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
2
/// @file       
3
/// @brief      Data memory AHB bridge
4
///
5
 
6
`include "scr1_ahb.svh"
7
`include "scr1_memif.svh"
8
 
9
module scr1_dmem_ahb (
10
    // Control Signals
11
    input   logic                           rst_n,
12
    input   logic                           clk,
13
 
14
    // Core Interface
15
    output  logic                           dmem_req_ack,
16
    input   logic                           dmem_req,
17 21 dinesha
    input   logic                           dmem_cmd,
18
    input   logic [1:0]                     dmem_width,
19 11 dinesha
    input   logic   [SCR1_AHB_WIDTH-1:0]    dmem_addr,
20
    input   logic   [SCR1_AHB_WIDTH-1:0]    dmem_wdata,
21
    output  logic   [SCR1_AHB_WIDTH-1:0]    dmem_rdata,
22 21 dinesha
    output  logic [1:0]                     dmem_resp,
23 11 dinesha
 
24
    // AHB Interface
25
    output  logic   [3:0]                   hprot,
26
    output  logic   [2:0]                   hburst,
27
    output  logic   [2:0]                   hsize,
28
    output  logic   [1:0]                   htrans,
29
    output  logic                           hmastlock,
30
    output  logic   [SCR1_AHB_WIDTH-1:0]    haddr,
31
    output  logic                           hwrite,
32
    output  logic   [SCR1_AHB_WIDTH-1:0]    hwdata,
33
    input   logic                           hready,
34
    input   logic   [SCR1_AHB_WIDTH-1:0]    hrdata,
35
    input   logic                           hresp
36
 
37
);
38
 
39
//-------------------------------------------------------------------------------
40
// Local Parameters
41
//-------------------------------------------------------------------------------
42
`ifndef SCR1_DMEM_AHB_OUT_BP
43
localparam  SCR1_FIFO_WIDTH = 2;
44
localparam  SCR1_FIFO_CNT_WIDTH = $clog2(SCR1_FIFO_WIDTH+1);
45
`endif // SCR1_DMEM_AHB_OUT_BP
46
 
47
//-------------------------------------------------------------------------------
48
// Local type declaration
49
//-------------------------------------------------------------------------------
50
typedef enum logic {
51
    SCR1_FSM_ADDR = 1'b0,
52
    SCR1_FSM_DATA = 1'b1,
53
    SCR1_FSM_ERR  = 1'bx
54
} type_scr1_fsm_e;
55
 
56
typedef struct packed {
57
    logic                           hwrite;
58
    logic   [2:0]                   hwidth;
59
    logic   [SCR1_AHB_WIDTH-1:0]    haddr;
60
    logic   [SCR1_AHB_WIDTH-1:0]    hwdata;
61
} type_scr1_req_fifo_s;
62
 
63
typedef struct packed {
64
    logic                           hwrite;
65
    logic   [2:0]                   hwidth;
66
    logic   [1:0]                   haddr;
67
    logic   [SCR1_AHB_WIDTH-1:0]    hwdata;
68
} type_scr1_data_fifo_s;
69
 
70
typedef struct packed {
71
    logic                           hresp;
72
    logic   [2:0]                   hwidth;
73
    logic   [1:0]                   haddr;
74
    logic   [SCR1_AHB_WIDTH-1:0]    hrdata;
75
} type_scr1_resp_fifo_s;
76
 
77
//-------------------------------------------------------------------------------
78
// Local functions
79
//-------------------------------------------------------------------------------
80
function automatic logic   [2:0] scr1_conv_mem2ahb_width (
81 21 dinesha
    input   logic [1:0]              dmem_width
82 11 dinesha
);
83
    logic   [2:0]   tmp;
84
begin
85
    case (dmem_width)
86
        SCR1_MEM_WIDTH_BYTE : begin
87
            tmp = SCR1_HSIZE_8B;
88
        end
89
        SCR1_MEM_WIDTH_HWORD : begin
90
            tmp = SCR1_HSIZE_16B;
91
        end
92
        SCR1_MEM_WIDTH_WORD : begin
93
            tmp = SCR1_HSIZE_32B;
94
        end
95
        default : begin
96
            tmp = SCR1_HSIZE_ERR;
97
        end
98
    endcase
99
    scr1_conv_mem2ahb_width =  tmp; // cp.11
100
end
101
endfunction
102
 
103
function automatic logic[SCR1_AHB_WIDTH-1:0] scr1_conv_mem2ahb_wdata (
104
    input   logic   [1:0]                   dmem_addr,
105 21 dinesha
    input   logic [1:0]                     dmem_width,
106 11 dinesha
    input   logic   [SCR1_AHB_WIDTH-1:0]    dmem_wdata
107
);
108
    logic   [SCR1_AHB_WIDTH-1:0]  tmp;
109
begin
110
    tmp = 'x;
111
    case (dmem_width)
112
        SCR1_MEM_WIDTH_BYTE : begin
113
            case (dmem_addr)
114
                2'b00 : begin
115
                    tmp[7:0]   = dmem_wdata[7:0];
116
                end
117
                2'b01 : begin
118
                    tmp[15:8]  = dmem_wdata[7:0];
119
                end
120
                2'b10 : begin
121
                    tmp[23:16] = dmem_wdata[7:0];
122
                end
123
                2'b11 : begin
124
                    tmp[31:24] = dmem_wdata[7:0];
125
                end
126
                default : begin
127
                end
128
            endcase
129
        end
130
        SCR1_MEM_WIDTH_HWORD : begin
131
            case (dmem_addr[1])
132
                1'b0 : begin
133
                    tmp[15:0]  = dmem_wdata[15:0];
134
                end
135
                1'b1 : begin
136
                    tmp[31:16] = dmem_wdata[15:0];
137
                end
138
                default : begin
139
                end
140
            endcase
141
        end
142
        SCR1_MEM_WIDTH_WORD : begin
143
            tmp = dmem_wdata;
144
        end
145
        default : begin
146
        end
147
    endcase
148
    scr1_conv_mem2ahb_wdata = tmp;
149
end
150
endfunction
151
 
152
function automatic logic[SCR1_AHB_WIDTH-1:0] scr1_conv_ahb2mem_rdata (
153
    input   logic [2:0]                 hwidth,
154
    input   logic [1:0]                 haddr,
155
    input   logic [SCR1_AHB_WIDTH-1:0]  hrdata
156
);
157
    logic   [SCR1_AHB_WIDTH-1:0]  tmp;
158
begin
159
    tmp = 'x;
160
    case (hwidth)
161
        SCR1_HSIZE_8B : begin
162
            case (haddr)
163
                2'b00 : tmp[7:0] = hrdata[7:0];
164
                2'b01 : tmp[7:0] = hrdata[15:8];
165
                2'b10 : tmp[7:0] = hrdata[23:16];
166
                2'b11 : tmp[7:0] = hrdata[31:24];
167
                default : begin
168
                end
169
            endcase
170
        end
171
        SCR1_HSIZE_16B : begin
172
            case (haddr[1])
173
                1'b0 : tmp[15:0] = hrdata[15:0];
174
                1'b1 : tmp[15:0] = hrdata[31:16];
175
                default : begin
176
                end
177
            endcase
178
        end
179
        SCR1_HSIZE_32B : begin
180
            tmp = hrdata;
181
        end
182
        default : begin
183
        end
184
    endcase
185
    scr1_conv_ahb2mem_rdata = tmp;
186
end
187
endfunction
188
 
189
//-------------------------------------------------------------------------------
190
// Local signal declaration
191
//-------------------------------------------------------------------------------
192
type_scr1_fsm_e                             fsm;
193
logic                                       req_fifo_rd;
194
logic                                       req_fifo_wr;
195
logic                                       req_fifo_up;
196
`ifdef SCR1_DMEM_AHB_OUT_BP
197
type_scr1_req_fifo_s                        req_fifo_new;
198
type_scr1_req_fifo_s                        req_fifo_r;
199
type_scr1_req_fifo_s [0:0]                  req_fifo;
200
`else // SCR1_DMEM_AHB_OUT_BP
201
type_scr1_req_fifo_s [0:SCR1_FIFO_WIDTH-1]  req_fifo;
202
type_scr1_req_fifo_s [0:SCR1_FIFO_WIDTH-1]  req_fifo_new;
203
logic       [SCR1_FIFO_CNT_WIDTH-1:0]       req_fifo_cnt;
204
logic       [SCR1_FIFO_CNT_WIDTH-1:0]       req_fifo_cnt_new;
205
`endif // SCR1_DMEM_AHB_OUT_BP
206
logic                                       req_fifo_empty;
207
logic                                       req_fifo_full;
208
 
209
type_scr1_data_fifo_s                       data_fifo;
210
type_scr1_resp_fifo_s                       resp_fifo;
211
logic                                       resp_fifo_hready;
212
 
213
//-------------------------------------------------------------------------------
214
// Interface to Core
215
//-------------------------------------------------------------------------------
216
assign dmem_req_ack = ~req_fifo_full;
217
assign req_fifo_wr  = ~req_fifo_full & dmem_req;
218
 
219
assign dmem_rdata = scr1_conv_ahb2mem_rdata(resp_fifo.hwidth, resp_fifo.haddr, resp_fifo.hrdata);
220
 
221
assign dmem_resp = (resp_fifo_hready)
222
                    ? (resp_fifo.hresp == SCR1_HRESP_OKAY)
223
                        ? SCR1_MEM_RESP_RDY_OK
224
                        : SCR1_MEM_RESP_RDY_ER
225
                    : SCR1_MEM_RESP_NOTRDY ;
226
 
227
//-------------------------------------------------------------------------------
228
// REQ_FIFO
229
//-------------------------------------------------------------------------------
230
`ifdef SCR1_DMEM_AHB_OUT_BP
231
always_ff @(negedge rst_n, posedge clk) begin
232
    if (~rst_n) begin
233
        req_fifo_full <= 1'b0;
234
    end else begin
235
        if (~req_fifo_full) begin
236
            req_fifo_full <= dmem_req & ~req_fifo_rd;
237
        end else begin
238
            req_fifo_full <= ~req_fifo_rd;
239
        end
240
    end
241
end
242
assign req_fifo_empty = ~(req_fifo_full | dmem_req);
243
 
244
assign req_fifo_up = ~req_fifo_rd & req_fifo_wr;
245
always_ff @(posedge clk) begin
246
    if (req_fifo_up) begin
247
        req_fifo_r <= req_fifo_new;
248
    end
249
end
250
 
251
assign req_fifo_new.hwrite = dmem_req ? (dmem_cmd == SCR1_MEM_CMD_WR)       : 1'b0;
252
assign req_fifo_new.hwidth = dmem_req ? scr1_conv_mem2ahb_width(dmem_width) : '0;
253
assign req_fifo_new.haddr  = dmem_req ? dmem_addr                           : '0;
254
assign req_fifo_new.hwdata = (dmem_req & (dmem_cmd == SCR1_MEM_CMD_WR))
255
                                ? scr1_conv_mem2ahb_wdata(dmem_addr[1:0], dmem_width, dmem_wdata)
256
                                : '0;
257
assign req_fifo[0] = (req_fifo_full) ? req_fifo_r: req_fifo_new;
258
 
259
`else // SCR1_DMEM_AHB_OUT_BP
260
always_comb begin
261
    req_fifo_up      = 1'b0;
262
    req_fifo_cnt_new = req_fifo_cnt;
263
    req_fifo_new     = req_fifo;
264
    case ({req_fifo_rd, req_fifo_wr})
265
        2'b00 : begin
266
            // nothing todo
267
        end
268
        2'b01: begin
269
            // FIFO write
270
            req_fifo_up = 1'b1;
271
            req_fifo_new[req_fifo_cnt].hwrite = (dmem_cmd == SCR1_MEM_CMD_WR);
272
            req_fifo_new[req_fifo_cnt].hwidth = scr1_conv_mem2ahb_width(dmem_width);
273
            req_fifo_new[req_fifo_cnt].haddr  = dmem_addr;
274
            req_fifo_new[req_fifo_cnt].hwdata = scr1_conv_mem2ahb_wdata(dmem_addr[1:0], dmem_width, dmem_wdata);
275
            req_fifo_cnt_new = req_fifo_cnt + 1'b1;
276
        end
277
        2'b10 : begin
278
            // FIFO read
279
            req_fifo_up = 1'b1;
280
            req_fifo_new[0] = req_fifo_new[1];
281
            req_fifo_new[1].hwrite = 1'b0;
282
            req_fifo_new[1].hwidth = SCR1_HSIZE_32B;
283
            req_fifo_new[1].haddr  = 'x;
284
            req_fifo_new[1].hwdata = 'x;
285
            req_fifo_cnt_new = req_fifo_cnt - 1'b1;
286
        end
287
        2'b11 : begin
288
            // Read and Write FIFO. It is possible only when fifo_cnt = 1
289
            req_fifo_up = 1'b1;
290
            req_fifo_new[0].hwrite = (dmem_cmd == SCR1_MEM_CMD_WR);
291
            req_fifo_new[0].hwidth = scr1_conv_mem2ahb_width(dmem_width);
292
            req_fifo_new[0].haddr  = dmem_addr;
293
            req_fifo_new[0].hwdata = scr1_conv_mem2ahb_wdata(dmem_addr[1:0], dmem_width, dmem_wdata);
294
        end
295
        default : begin
296
            req_fifo_up      = 'x;
297
            req_fifo_cnt_new = 'x;
298
            req_fifo_new     = 'x;
299
        end
300
    endcase
301
end
302
 
303
always_ff @(negedge rst_n, posedge clk) begin
304
    if (~rst_n) begin
305
        req_fifo_cnt <= '0;
306
    end else begin
307
        if (req_fifo_up) begin
308
            req_fifo_cnt <= req_fifo_cnt_new;
309
        end
310
    end
311
end
312
assign req_fifo_full  = (req_fifo_cnt == SCR1_FIFO_WIDTH);
313
assign req_fifo_empty = ~(|req_fifo_cnt);
314
 
315
always_ff @(posedge clk) begin
316
    if (req_fifo_up) begin
317
        req_fifo <= req_fifo_new;
318
    end
319
end
320
`endif // SCR1_DMEM_AHB_OUT_BP
321
//-------------------------------------------------------------------------------
322
// FSM
323
//-------------------------------------------------------------------------------
324
always_ff @(negedge rst_n, posedge clk) begin
325
    if (~rst_n) begin
326
        fsm <= SCR1_FSM_ADDR;
327
    end else begin
328
        case (fsm)
329
            SCR1_FSM_ADDR : begin
330
                if (hready) begin
331
                    fsm <= (req_fifo_empty) ? SCR1_FSM_ADDR : SCR1_FSM_DATA;
332
                end
333
            end
334
            SCR1_FSM_DATA : begin
335
                if (hready) begin
336
                    if (hresp == SCR1_HRESP_OKAY) begin
337
                        fsm <= (req_fifo_empty) ? SCR1_FSM_ADDR : SCR1_FSM_DATA;
338
                    end else begin
339
                        fsm <= SCR1_FSM_ADDR;
340
                    end
341
                end
342
            end
343
            default : begin
344
                fsm <= SCR1_FSM_ERR;
345
            end
346
        endcase
347
    end
348
end
349
 
350
always_comb begin
351
    req_fifo_rd = 1'b0;
352
    case (fsm)
353
        SCR1_FSM_ADDR : begin
354
            if (hready) begin
355
                req_fifo_rd = ~req_fifo_empty;
356
            end
357
        end
358
        SCR1_FSM_DATA : begin
359
            if (hready) begin
360
                req_fifo_rd = ~req_fifo_empty & (hresp == SCR1_HRESP_OKAY);
361
            end
362
        end
363
        default : begin
364
            req_fifo_rd = 1'bx;
365
        end
366
    endcase
367
end
368
 
369
//-------------------------------------------------------------------------------
370
// FIFO data
371
//-------------------------------------------------------------------------------
372
always_ff @(posedge clk) begin
373
    case (fsm)
374
        SCR1_FSM_ADDR : begin
375
            if (~req_fifo_empty) begin
376
                data_fifo.hwrite <= req_fifo[0].hwrite;
377
                data_fifo.hwidth <= req_fifo[0].hwidth;
378
                data_fifo.haddr  <= req_fifo[0].haddr[1:0];
379
                data_fifo.hwdata <= req_fifo[0].hwdata;
380
            end
381
        end
382
        SCR1_FSM_DATA : begin
383
            if (hready) begin
384
                if (hresp == SCR1_HRESP_OKAY) begin
385
                    if (~req_fifo_empty) begin
386
                        data_fifo.hwrite <= req_fifo[0].hwrite;
387
                        data_fifo.hwidth <= req_fifo[0].hwidth;
388
                        data_fifo.haddr  <= req_fifo[0].haddr[1:0];
389
                        data_fifo.hwdata <= req_fifo[0].hwdata;
390
                    end
391
                end
392
            end
393
        end
394
        default : begin
395
        end
396
    endcase
397
end
398
 
399
//-------------------------------------------------------------------------------
400
// FIFO response
401
//-------------------------------------------------------------------------------
402
`ifdef SCR1_DMEM_AHB_IN_BP
403
assign resp_fifo_hready = (fsm == SCR1_FSM_DATA) ? hready : 1'b0;
404
assign resp_fifo.hresp  = hresp;
405
assign resp_fifo.hwidth = data_fifo.hwidth;
406
assign resp_fifo.haddr  = data_fifo.haddr;
407
assign resp_fifo.hrdata = hrdata;
408
`else // SCR1_DMEM_AHB_IN_BP
409
always_ff @(negedge rst_n, posedge clk) begin
410
    if (~rst_n) begin
411
        resp_fifo_hready <= 1'b0;
412
    end else begin
413
        resp_fifo_hready <= (fsm == SCR1_FSM_DATA) ? hready : 1'b0;
414
    end
415
end
416
 
417
always_ff @(posedge clk) begin
418
    if (hready & (fsm == SCR1_FSM_DATA)) begin
419
        resp_fifo.hresp  <= hresp;
420
        resp_fifo.hwidth <= data_fifo.hwidth;
421
        resp_fifo.haddr  <= data_fifo.haddr;
422
        resp_fifo.hrdata <= hrdata;
423
    end
424
end
425
`endif // SCR1_DMEM_AHB_IN_BP
426
 
427
//-------------------------------------------------------------------------------
428
// Interface to AHB
429
//-------------------------------------------------------------------------------
430
assign hprot[SCR1_HPROT_DATA]  = 1'b1;
431
assign hprot[SCR1_HPROT_PRV]   = 1'b0;
432
assign hprot[SCR1_HPROT_BUF]   = 1'b0;
433
assign hprot[SCR1_HPROT_CACHE] = 1'b0;
434
 
435
assign hburst       = SCR1_HBURST_SINGLE;
436
assign hsize        = req_fifo[0].hwidth;
437
assign hmastlock    = 1'b0;
438
 
439
always_comb begin
440
    htrans = SCR1_HTRANS_IDLE;
441
    case (fsm)
442
        SCR1_FSM_ADDR : begin
443
            if (~req_fifo_empty) begin
444
                htrans = SCR1_HTRANS_NONSEQ;
445
            end
446
        end
447
        SCR1_FSM_DATA : begin
448
            if (hready) begin
449
                if (hresp == SCR1_HRESP_OKAY) begin
450
                    if (~req_fifo_empty) begin
451
                        htrans = SCR1_HTRANS_NONSEQ;
452
                    end
453
                end
454
            end
455
        end
456
        default : begin
457
            htrans = SCR1_HTRANS_ERR;
458
        end
459
    endcase
460
end
461
 
462
assign haddr  = req_fifo[0].haddr;
463
assign hwrite = req_fifo[0].hwrite;
464
assign hwdata = data_fifo.hwdata;
465
 
466
endmodule : scr1_dmem_ahb

powered by: WebSVN 2.1.0

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