hw/vendor/pulp_riscv_dbg/src/dm_sba.sv Cov: 97%
1: /* Copyright 2018 ETH Zurich and University of Bologna.
2: * Copyright and related rights are licensed under the Solderpad Hardware
3: * License, Version 0.51 (the “License”); you may not use this file except in
4: * compliance with the License. You may obtain a copy of the License at
5: * http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
6: * or agreed to in writing, software, hardware and materials distributed under
7: * this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR
8: * CONDITIONS OF ANY KIND, either express or implied. See the License for the
9: * specific language governing permissions and limitations under the License.
10: *
11: * File: dm_sba.sv
12: * Author: Florian Zaruba
13: * Date: 1.8.2018
14: *
15: * Description: System Bus Access Module
16: *
17: */
18: module dm_sba #(
19: parameter int unsigned BusWidth = 32
20: ) (
21: input logic clk_i, // Clock
22: input logic rst_ni,
23: input logic dmactive_i, // synchronous reset active low
24:
25: output logic master_req_o,
26: output logic [BusWidth-1:0] master_add_o,
27: output logic master_we_o,
28: output logic [BusWidth-1:0] master_wdata_o,
29: output logic [BusWidth/8-1:0] master_be_o,
30: input logic master_gnt_i,
31: input logic master_r_valid_i,
32: input logic [BusWidth-1:0] master_r_rdata_i,
33:
34: input logic [BusWidth-1:0] sbaddress_i,
35: input logic sbaddress_write_valid_i,
36: // control signals in
37: input logic sbreadonaddr_i,
38: output logic [BusWidth-1:0] sbaddress_o,
39: input logic sbautoincrement_i,
40: input logic [2:0] sbaccess_i,
41: // data in
42: input logic sbreadondata_i,
43: input logic [BusWidth-1:0] sbdata_i,
44: input logic sbdata_read_valid_i,
45: input logic sbdata_write_valid_i,
46: // read data out
47: output logic [BusWidth-1:0] sbdata_o,
48: output logic sbdata_valid_o,
49: // control signals
50: output logic sbbusy_o,
51: output logic sberror_valid_o, // bus error occurred
52: output logic [2:0] sberror_o // bus error occurred
53: );
54:
55: typedef enum logic [2:0] { Idle, Read, Write, WaitRead, WaitWrite } state_e;
56: state_e state_d, state_q;
57:
58: logic [BusWidth-1:0] address;
59: logic req;
60: logic gnt;
61: logic we;
62: logic [BusWidth/8-1:0] be;
63: logic [$clog2(BusWidth/8)-1:0] be_idx;
64:
65: assign sbbusy_o = logic'(state_q != Idle);
66:
67: always_comb begin : p_fsm
68: req = 1'b0;
69: address = sbaddress_i;
70: we = 1'b0;
71: be = '0;
72: be_idx = sbaddress_i[$clog2(BusWidth/8)-1:0];
73:
74: sberror_o = '0;
75: sberror_valid_o = 1'b0;
76: sbaddress_o = sbaddress_i;
77:
78: state_d = state_q;
79:
80: unique case (state_q)
81: Idle: begin
82: // debugger requested a read
83: if (sbaddress_write_valid_i && sbreadonaddr_i) state_d = Read;
84: // debugger requested a write
85: if (sbdata_write_valid_i) state_d = Write;
86: // perform another read
87: if (sbdata_read_valid_i && sbreadondata_i) state_d = Read;
88: end
89:
90: Read: begin
91: req = 1'b1;
92: if (gnt) state_d = WaitRead;
93: end
94:
95: Write: begin
96: req = 1'b1;
97: we = 1'b1;
98: // generate byte enable mask
99: unique case (sbaccess_i)
100: 3'b000: begin
101: be[be_idx] = '1;
102: end
103: 3'b001: begin
104: be[int'({be_idx[$high(be_idx):1], 1'b0}) +: 2] = '1;
105: end
106: 3'b010: begin
107: if (BusWidth == 32'd64) be[int'({be_idx[$high(be_idx)], 2'b0}) +: 4] = '1;
108: else be = '1;
109: end
110: 3'b011: be = '1;
111: default: ;
112: endcase
113: if (gnt) state_d = WaitWrite;
114: end
115:
116: WaitRead: begin
117: if (sbdata_valid_o) begin
118: state_d = Idle;
119: // auto-increment address
120: if (sbautoincrement_i) sbaddress_o = sbaddress_i + (32'b1 << sbaccess_i);
121: end
122: end
123:
124: WaitWrite: begin
125: if (sbdata_valid_o) begin
126: state_d = Idle;
127: // auto-increment address
128: if (sbautoincrement_i) sbaddress_o = sbaddress_i + (32'b1 << sbaccess_i);
129: end
130: end
131:
132: default: state_d = Idle; // catch parasitic state
133: endcase
134:
135: // handle error case
136: if (sbaccess_i > 3 && state_q != Idle) begin
137: req = 1'b0;
138: state_d = Idle;
139: sberror_valid_o = 1'b1;
140: sberror_o = 3'd3;
141: end
142: // further error handling should go here ...
143: end
144:
145: always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
146: if (!rst_ni) begin
147: state_q <= Idle;
148: end else begin
149: state_q <= state_d;
150: end
151: end
152:
153: assign master_req_o = req;
154: assign master_add_o = address[BusWidth-1:0];
155: assign master_we_o = we;
156: assign master_wdata_o = sbdata_i[BusWidth-1:0];
157: assign master_be_o = be[BusWidth/8-1:0];
158: assign gnt = master_gnt_i;
159: assign sbdata_valid_o = master_r_valid_i;
160: assign sbdata_o = master_r_rdata_i[BusWidth-1:0];
161:
162:
163: //pragma translate_off
164: `ifndef VERILATOR
165: // maybe bump severity to $error if not handled at runtime
166: dm_sba_access_size: assert property(@(posedge clk_i) disable iff (dmactive_i !== 1'b0)
167: (state_d != Idle) |-> (sbaccess_i < 4))
168: else $warning ("accesses > 8 byte not supported at the moment");
169: `endif
170: //pragma translate_on
171:
172: endmodule : dm_sba
173: