hw/ip/prim/rtl/prim_sram_arbiter.sv Cov: 84.7%
1: // Copyright lowRISC contributors.
2: // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3: // SPDX-License-Identifier: Apache-2.0
4: //
5: // N:1 SRAM arbiter
6: //
7: // Parameter
8: // N: Number of requst port
9: // DW: Data width (SECDED is not included)
10: // Aw: Address width
11: // ArbiterImpl: can be either PPC or BINTREE.
12: module prim_sram_arbiter #(
13: parameter int N = 4,
14: parameter int SramDw = 32,
15: parameter int SramAw = 12,
16: parameter ArbiterImpl = "PPC"
17: ) (
18: input clk_i,
19: input rst_ni,
20:
21: input [ N-1:0] req,
22: input [SramAw-1:0] req_addr [N],
23: input req_write [N],
24: input [SramDw-1:0] req_wdata [N],
25: output logic [ N-1:0] gnt,
26:
27: output logic [ N-1:0] rsp_rvalid, // Pulse
28: output logic [SramDw-1:0] rsp_rdata [N],
29: output logic [ 1:0] rsp_error [N],
30:
31: // SRAM Interface
32: output logic sram_req,
33: output logic [SramAw-1:0] sram_addr,
34: output logic sram_write,
35: output logic [SramDw-1:0] sram_wdata,
36: input sram_rvalid,
37: input [SramDw-1:0] sram_rdata,
38: input [1:0] sram_rerror
39: );
40:
41:
42: typedef struct packed {
43: logic write;
44: logic [SramAw-1:0] addr;
45: logic [SramDw-1:0] wdata;
46: } req_t;
47:
48: localparam int ARB_DW = $bits(req_t);
49:
50: req_t req_packed [N];
51:
52: for (genvar i = 0 ; i < N ; i++) begin : gen_reqs
53: assign req_packed[i] = {req_write[i], req_addr[i], req_wdata[i]};
54: end
55:
56: req_t sram_packed;
57: assign sram_write = sram_packed.write;
58: assign sram_addr = sram_packed.addr;
59: assign sram_wdata = sram_packed.wdata;
60:
61: if (ArbiterImpl == "PPC") begin : gen_arb_ppc
62: prim_arbiter_ppc #(
63: .N (N),
64: .DW(ARB_DW)
65: ) u_reqarb (
66: .clk_i,
67: .rst_ni,
68: .req_i ( req ),
69: .data_i ( req_packed ),
70: .gnt_o ( gnt ),
71: .idx_o ( ),
72: .valid_o ( sram_req ),
73: .data_o ( sram_packed ),
74: .ready_i ( 1'b1 )
75: );
76: end else if (ArbiterImpl == "BINTREE") begin : gen_tree_arb
77: prim_arbiter_arb #(
78: .N (N),
79: .DW(ARB_DW)
80: ) u_reqarb (
81: .clk_i,
82: .rst_ni,
83: .req_i ( req ),
84: .data_i ( req_packed ),
85: .gnt_o ( gnt ),
86: .idx_o ( ),
87: .valid_o ( sram_req ),
88: .data_o ( sram_packed ),
89: .ready_i ( 1'b1 )
90: );
91: end else begin : gen_unknown
92: `ASSERT_INIT(UnknownArbImpl_A, 0)
93: end
94:
95:
96: logic [N-1:0] steer; // Steering sram_rvalid
97: logic sram_ack; // Ack for rvalid. |sram_rvalid
98:
99: assign sram_ack = sram_rvalid & (|steer);
100:
101: // Request FIFO
102: prim_fifo_sync #(
103: .Width (N),
104: .Pass (1'b0),
105: .Depth (4) // Assume at most 4 pipelined
106: ) u_req_fifo (
107: .clk_i,
108: .rst_ni,
109: .clr_i (1'b0),
110: .wvalid (sram_req && !sram_write), // Push only for read
111: .wready (), // TODO: Generate Error
112: .wdata (gnt),
113: .depth (), // Not used
114: .rvalid (), // TODO; Generate error if sram_rvalid but rvalid==0
115: .rready (sram_ack),
116: .rdata (steer)
117: );
118:
119: assign rsp_rvalid = steer & {N{sram_rvalid}};
120:
121: for (genvar i = 0 ; i < N ; i++) begin : gen_rsp
122: assign rsp_rdata[i] = sram_rdata;
123: assign rsp_error[i] = sram_rerror; // No SECDED yet
124: end
125:
126: endmodule
127: