blob: c0860fe50134cec35f67cd3892215b220ffae825 [file] [log] [blame]
Sylvain Munaut21b03ba2020-09-14 10:01:45 +02001/*
2 * soc_picorv32_bridge.v
3 *
4 * vim: ts=4 sw=4
5 *
6 * Copyright (C) 2020 Sylvain Munaut <tnt@246tNt.com>
7 * SPDX-License-Identifier: CERN-OHL-P-2.0
8 */
9
10`default_nettype none
11
12module soc_picorv32_bridge #(
13 parameter integer WB_N = 8,
14 parameter integer WB_DW = 32,
15 parameter integer WB_AW = 16,
16 parameter integer WB_AI = 2,
17 parameter integer WB_REG = 0 // [0] = cyc / [1] = addr/wdata/wstrb / [2] = ack/rdata
18)(
19 /* PicoRV32 bus */
20 input wire [31:0] pb_addr,
21 output wire [31:0] pb_rdata,
22 input wire [31:0] pb_wdata,
23 input wire [ 3:0] pb_wstrb,
24 input wire pb_valid,
25 output wire pb_ready,
26
27 /* BRAM */
28 output wire [ 7:0] bram_addr,
29 input wire [31:0] bram_rdata,
30 output wire [31:0] bram_wdata,
31 output wire [ 3:0] bram_wmsk,
32 output wire bram_we,
33
34 /* SPRAM */
35 output wire [14:0] spram_addr,
36 input wire [31:0] spram_rdata,
37 output wire [31:0] spram_wdata,
38 output wire [ 3:0] spram_wmsk,
39 output wire spram_we,
40
41 /* Wishbone buses */
42 output wire [WB_AW-1:0] wb_addr,
43 input wire [(WB_DW*WB_N)-1:0] wb_rdata,
44 output wire [WB_DW-1:0] wb_wdata,
45 output wire [(WB_DW/8)-1:0] wb_wmsk,
46 output wire wb_we,
47 output wire [WB_N-1:0] wb_cyc,
48 input wire [WB_N-1:0] wb_ack,
49
50 /* Clock / Reset */
51 input wire clk,
52 input wire rst
53);
54
55 // Signals
56 // -------
57
58 wire ram_sel;
59 reg ram_rdy;
60 wire [31:0] ram_rdata;
61
62 (* keep *) wire [WB_N-1:0] wb_match;
63 (* keep *) wire wb_cyc_rst;
64
65 reg [31:0] wb_rdata_or;
66 wire [31:0] wb_rdata_out;
67 wire wb_rdy;
68
69
70 // RAM access
71 // ----------
72 // BRAM : 0x00000000 -> 0x000003ff
73 // SPRAM : 0x00020000 -> 0x0003ffff
74
75 assign bram_addr = pb_addr[ 9:2];
76 assign spram_addr = pb_addr[16:2];
77
78 assign bram_wdata = pb_wdata;
79 assign spram_wdata = pb_wdata;
80
81 assign bram_wmsk = ~pb_wstrb;
82 assign spram_wmsk = ~pb_wstrb;
83
84 assign bram_we = pb_valid & ~pb_addr[31] & |pb_wstrb & ~pb_addr[17];
85 assign spram_we = pb_valid & ~pb_addr[31] & |pb_wstrb & pb_addr[17];
86
87 assign ram_rdata = ~pb_addr[31] ? (pb_addr[17] ? spram_rdata : bram_rdata) : 32'h00000000;
88
89 assign ram_sel = pb_valid & ~pb_addr[31];
90
91 always @(posedge clk)
92 ram_rdy <= ram_sel && ~ram_rdy;
93
94
95 // Wishbone
96 // --------
97 // wb[x] = 0x8x000000 - 0x8xffffff
98
99 // Access Cycle
100 genvar i;
101 for (i=0; i<WB_N; i=i+1)
102 assign wb_match[i] = (pb_addr[27:24] == i);
103
104 if (WB_REG & 1) begin
105 // Register
106 reg [WB_N-1:0] wb_cyc_reg;
107 always @(posedge clk)
108 if (wb_cyc_rst)
109 wb_cyc_reg <= 0;
110 else
111 wb_cyc_reg <= wb_match & ~wb_ack;
112 assign wb_cyc = wb_cyc_reg;
113 end else begin
114 // Direct connection
115 assign wb_cyc = wb_cyc_rst ? { WB_N{1'b0} } : wb_match;
116 end
117
118 // Addr / Write-Data / Write-Mask / Write-Enable
119 if (WB_REG & 2) begin
120 // Register
121 reg [WB_AW-1:0] wb_addr_reg;
122 reg [WB_DW-1:0] wb_wdata_reg;
123 reg [(WB_DW/8)-1:0] wb_wmsk_reg;
124 reg wb_we_reg;
125
126 always @(posedge clk)
127 begin
128 wb_addr_reg <= pb_addr[WB_AW+WB_AI-1:WB_AI];
129 wb_wdata_reg <= pb_wdata[WB_DW-1:0];
130 wb_wmsk_reg <= ~pb_wstrb[(WB_DW/8)-1:0];
131 wb_we_reg <= |pb_wstrb;
132 end
133
134 assign wb_addr = wb_addr_reg;
135 assign wb_wdata = wb_wdata_reg;
136 assign wb_wmsk = wb_wmsk_reg;
137 assign wb_we = wb_we_reg;
138 end else begin
139 // Direct connection
140 assign wb_addr = pb_addr[WB_AW+WB_AI-1:WB_AI];
141 assign wb_wdata = pb_wdata[WB_DW-1:0];
142 assign wb_wmsk = pb_wstrb[(WB_DW/8)-1:0];
143 assign wb_we = |pb_wstrb;
144 end
145
146 // Ack / Read-Data
147 always @(*)
148 begin : wb_or
149 integer i;
150 wb_rdata_or = 0;
151 for (i=0; i<WB_N; i=i+1)
152 wb_rdata_or[WB_DW-1:0] = wb_rdata_or[WB_DW-1:0] | wb_rdata[WB_DW*i+:WB_DW];
153 end
154
155 if (WB_REG & 4) begin
156 // Register
157 reg wb_rdy_reg;
158 reg [31:0] wb_rdata_reg;
159
160 always @(posedge clk)
161 wb_rdy_reg <= |wb_ack;
162
163 always @(posedge clk)
164 if (wb_cyc_rst)
165 wb_rdata_reg <= 32'h00000000;
166 else
167 wb_rdata_reg <= wb_rdata_or;
168
169 assign wb_cyc_rst = ~pb_valid | ~pb_addr[31] | wb_rdy_reg;
170 assign wb_rdy = wb_rdy_reg;
171 assign wb_rdata_out = wb_rdata_reg;
172 end else begin
173 // Direct connection
174 assign wb_cyc_rst = ~pb_valid | ~pb_addr[31];
175 assign wb_rdy = |wb_ack;
176 assign wb_rdata_out = wb_rdata_or;
177 end
178
179
180 // Final data combining
181 // --------------------
182
183 assign pb_rdata = ram_rdata | wb_rdata_out;
184 assign pb_ready = ram_rdy | wb_rdy;
185
186endmodule // soc_picorv32_bridge