blob: 347412c99c37f5b5f2a08279cd4297be9b9cb775 [file] [log] [blame]
Sylvain Munautbd83e532020-09-15 22:11:29 +02001/*
2 * misc.v
3 *
4 * vim: ts=4 sw=4
5 *
6 * Misc peripheral functions
7 *
8 * Copyright (C) 2019-2020 Sylvain Munaut <tnt@246tNt.com>
9 * SPDX-License-Identifier: CERN-OHL-S-2.0
10 */
11
12`default_nettype none
13
Sylvain Munaut205a1312020-10-03 20:23:41 +020014// `define WITH_PDM_READBACK
15
Sylvain Munautbd83e532020-09-15 22:11:29 +020016module misc (
17 // PDM outputs
18 output wire [1:0] e1_rx_bias,
19
20 output wire clk_tune_hi,
21 output wire clk_tune_lo,
22
23 // GPS
24 output wire gps_reset_n,
25 input wire gps_pps,
26
27 // GPIO
28 inout wire [ 2:0] gpio,
29
30 // E1 led status
31 output wire [ 7:0] e1_led_state,
32 output wire e1_led_run,
33 input wire e1_led_active,
34
35 // Button
36 input wire btn_val,
37 input wire btn_stb,
38
39 // Ticks
Sylvain Munaut60f664f2024-04-29 16:14:54 +020040 input wire [ 7:0] tick_e1,
Sylvain Munautbd83e532020-09-15 22:11:29 +020041 input wire tick_usb_sof,
42
43 // Reset request
44 output wire rst_req,
45
46 // Wishbone
47 input wire [ 7:0] wb_addr,
48 output reg [31:0] wb_rdata,
49 input wire [31:0] wb_wdata,
50 input wire wb_we,
51 input wire wb_cyc,
52 output reg wb_ack,
53
54 // Clock / Reset
55 input wire clk,
56 input wire rst
57);
58
59 // Signals
60 // -------
61
62 genvar i;
63
64 // Bus
65 wire bus_clr;
66 reg bus_we_boot;
67 reg bus_we_gpio;
68 reg bus_we_led;
Sylvain Munaut60f664f2024-04-29 16:14:54 +020069 reg bus_we_tick_sel;
Sylvain Munautbd83e532020-09-15 22:11:29 +020070 reg [ 1:0] bus_we_pdm_clk;
71 reg [ 1:0] bus_we_pdm_e1;
72
73 // GPIO
74 reg [3:0] gpio_oe;
75 reg [3:0] gpio_out;
76 wire [3:0] gpio_in;
77
78 // LED
79 reg [ 8:0] e1_led;
80
81 // PPS sync
82 wire gps_pps_iob;
83 wire gps_pps_r;
84
85 // Counters
Sylvain Munaut60f664f2024-04-29 16:14:54 +020086 reg [1:0] tick_e1_sel[0:1];
87 wire [1:0] tick_e1_mux;
88
89 wire [15:0] cap_e1[0:1];
Sylvain Munautff0ab3e2020-10-03 20:15:28 +020090 wire [31:0] cap_gps;
91 wire [31:0] cnt_time;
Sylvain Munautbd83e532020-09-15 22:11:29 +020092
93 // PDM
94 reg [12:0] pdm_clk[0:1];
95 reg [ 8:0] pdm_e1[0:1];
96
97 // Boot
98 reg [1:0] boot_sel;
99 reg boot_now;
100
101
102 // Bus interface
103 // -------------
104
105 // Ack
106 always @(posedge clk)
107 wb_ack <= wb_cyc & ~wb_ack;
108
109 assign bus_clr = ~wb_cyc | wb_ack;
110
111 // Write enables
112 always @(posedge clk)
113 if (bus_clr | ~wb_we) begin
114 bus_we_boot <= 1'b0;
115 bus_we_gpio <= 1'b0;
116 bus_we_led <= 1'b0;
Sylvain Munaut60f664f2024-04-29 16:14:54 +0200117 bus_we_tick_sel <= 1'b0;
Sylvain Munautbd83e532020-09-15 22:11:29 +0200118 bus_we_pdm_clk[0] <= 1'b0;
119 bus_we_pdm_clk[1] <= 1'b0;
120 bus_we_pdm_e1[0] <= 1'b0;
121 bus_we_pdm_e1[1] <= 1'b0;
122 end else begin
123 bus_we_boot <= wb_addr == 4'h0;
124 bus_we_gpio <= wb_addr == 4'h1;
125 bus_we_led <= wb_addr == 4'h2;
Sylvain Munaut60f664f2024-04-29 16:14:54 +0200126 bus_we_tick_sel <= wb_addr == 4'h4;
Sylvain Munautbd83e532020-09-15 22:11:29 +0200127 bus_we_pdm_clk[0] <= wb_addr == 4'h8;
128 bus_we_pdm_clk[1] <= wb_addr == 4'h9;
129 bus_we_pdm_e1[0] <= wb_addr == 4'ha;
130 bus_we_pdm_e1[1] <= wb_addr == 4'hb;
131 end
132
133 // Read mux
134 always @(posedge clk)
135 if (bus_clr)
136 wb_rdata <= 32'h00000000;
137 else
138 case (wb_addr[3:0])
139 4'h1: wb_rdata <= { 12'h000, gpio_in, 4'h0, gpio_oe, 4'h0, gpio_out };
Sylvain Munaut3edf9dd2020-10-09 13:24:03 +0200140 4'h2: wb_rdata <= { 22'h000000, e1_led_active, e1_led };
Sylvain Munaut60f664f2024-04-29 16:14:54 +0200141 4'h4: wb_rdata <= { cap_e1[1], cap_e1[0] };
Sylvain Munautbd83e532020-09-15 22:11:29 +0200142 4'h6: wb_rdata <= cap_gps;
143 4'h7: wb_rdata <= cnt_time;
Sylvain Munaut205a1312020-10-03 20:23:41 +0200144`ifdef WITH_PDM_READBACK
Sylvain Munautbd83e532020-09-15 22:11:29 +0200145 4'h8: wb_rdata <= { pdm_clk[0][12], 19'h00000, pdm_clk[0][11:0] };
146 4'h9: wb_rdata <= { pdm_clk[1][12], 19'h00000, pdm_clk[1][11:0] };
147 4'ha: wb_rdata <= { pdm_e1[0][8], 23'h000000, pdm_e1[0][ 7:0] };
148 4'hb: wb_rdata <= { pdm_e1[1][8], 23'h000000, pdm_e1[1][ 7:0] };
Sylvain Munaut205a1312020-10-03 20:23:41 +0200149`endif
Sylvain Munautbd83e532020-09-15 22:11:29 +0200150 default: wb_rdata <= 32'hxxxxxxxx;
151 endcase
152
153
154 // GPIO (incl gps reset)
155 // ----
156
157 // IOB
158 SB_IO #(
159 .PIN_TYPE(6'b110100), // Reg in/out/oe
160 .PULLUP(1'b1),
161 .IO_STANDARD("SB_LVCMOS")
162 ) gpio_iob_I[3:0] (
163 .PACKAGE_PIN ({gps_reset_n, gpio}),
164 .CLOCK_ENABLE (1'b1),
165 .INPUT_CLK (clk),
166 .OUTPUT_CLK (clk),
167 .OUTPUT_ENABLE(gpio_oe),
168 .D_OUT_0 (gpio_out),
169 .D_IN_0 (gpio_in)
170 );
171
172 // Bus
173 always @(posedge clk or posedge rst)
174 if (rst) begin
175 gpio_oe <= 4'h0;
176 gpio_out <= 4'h0;
177 end else if (bus_we_gpio) begin
178 gpio_oe <= wb_wdata[11:8];
179 gpio_out <= wb_wdata[ 3:0];
180 end
181
182
183 // E1 led status
184 // -------------
185
186 always @(posedge clk or posedge rst)
187 if (rst)
188 e1_led <= 9'h00;
189 else if (bus_we_led)
190 e1_led <= wb_wdata[8:0];
191
192 assign e1_led_state = e1_led[7:0];
193 assign e1_led_run = e1_led[8];
194
195
196 // PPS input
197 // ---------
198
199 // IO reg
200 SB_IO #(
201 .PIN_TYPE(6'b000000), // Reg input, no output
202 .PULLUP(1'b0),
203 .IO_STANDARD("SB_LVCMOS")
Sylvain Munaut9e02d4c2022-05-03 13:59:49 +0200204 ) pps_iob_I (
Sylvain Munautbd83e532020-09-15 22:11:29 +0200205 .PACKAGE_PIN(gps_pps),
206 .INPUT_CLK (clk),
207 .D_IN_0 (gps_pps_iob)
208 );
209
210 // Deglitch
211 glitch_filter #(
212 .L(2),
213 .RST_VAL(1'b0),
214 .WITH_SYNCHRONIZER(1)
Sylvain Munaut9e02d4c2022-05-03 13:59:49 +0200215 ) pps_flt_I (
Sylvain Munautbd83e532020-09-15 22:11:29 +0200216 .in (gps_pps_iob),
217 .val (),
218 .rise (gps_pps_r),
219 .fall (),
220 .clk (clk),
221`ifdef SIM
222 .rst (rst)
223`else
224 // Don't reset so we let the filter settle before
225 // the rest of the logic engages
226 .rst (1'b0)
227`endif
228 );
229
230
231 // Counters
232 // --------
233
234 // E1 ticks
Sylvain Munaut60f664f2024-04-29 16:14:54 +0200235 always @(posedge clk)
236 if (bus_we_tick_sel) begin
237 tick_e1_sel[1] <= wb_wdata[17:16];
238 tick_e1_sel[0] <= wb_wdata[ 1: 0];
239 end
240
241 assign tick_e1_mux[0] = tick_e1[{1'b0, tick_e1_sel[0]}];
242 assign tick_e1_mux[1] = tick_e1[{1'b1, tick_e1_sel[1]}];
243
Sylvain Munautff0ab3e2020-10-03 20:15:28 +0200244 capcnt #(
245 .W(16)
Sylvain Munaut60f664f2024-04-29 16:14:54 +0200246 ) e1_cnt_I[1:0] (
Sylvain Munautff0ab3e2020-10-03 20:15:28 +0200247 .cnt_cur (),
Sylvain Munaut60f664f2024-04-29 16:14:54 +0200248 .cnt_cap ({ cap_e1[1], cap_e1[0] }),
249 .inc ({ tick_e1_mux[1], tick_e1_mux[0] }),
Sylvain Munautff0ab3e2020-10-03 20:15:28 +0200250 .cap (tick_usb_sof),
251 .clk (clk),
252 .rst (rst)
253 );
Sylvain Munautbd83e532020-09-15 22:11:29 +0200254
Sylvain Munautff0ab3e2020-10-03 20:15:28 +0200255 // Time / GPS
256 capcnt #(
257 .W(32)
258 ) time_cnt_I (
259 .cnt_cur (cnt_time),
260 .cnt_cap (cap_gps),
261 .inc (1'b1),
262 .cap (gps_pps_r),
263 .clk (clk),
264 .rst (rst)
265 );
Sylvain Munautbd83e532020-09-15 22:11:29 +0200266
267
268 // PDM outputs
269 // -----------
270
271 // Registers
272 always @(posedge clk or posedge rst)
273 if (rst) begin
274 pdm_clk[0] <= 0; // 13'h1800;
275 pdm_clk[1] <= 0; // 13'h1800;
276 pdm_e1[0] <= 0; // 9'h190;
277 pdm_e1[1] <= 0; // 9'h190;
278 end else begin
279 if (bus_we_pdm_clk[0]) pdm_clk[0] <= { wb_wdata[31], wb_wdata[11:0] };
280 if (bus_we_pdm_clk[1]) pdm_clk[1] <= { wb_wdata[31], wb_wdata[11:0] };
281 if (bus_we_pdm_e1[0]) pdm_e1[0] <= { wb_wdata[31], wb_wdata[ 7:0] };
282 if (bus_we_pdm_e1[1]) pdm_e1[1] <= { wb_wdata[31], wb_wdata[ 7:0] };
283 end
284
285 // PDM cores
286 pdm #(
287 .WIDTH(12),
288 .PHY("ICE40"),
289 .DITHER("YES")
290 ) pdm_clk_I[1:0] (
291 .pdm ({ clk_tune_hi, clk_tune_lo }),
292 .cfg_val({ pdm_clk[1][11:0], pdm_clk[0][11:0] }),
293 .cfg_oe ({ pdm_clk[1][12], pdm_clk[0][12] }),
294 .clk (clk),
295 .rst (rst)
296 );
297
298 pdm #(
299 .WIDTH(8),
300 .PHY("ICE40"),
301 .DITHER("NO")
302 ) pdm_e1_I[1:0] (
303 .pdm ({ e1_rx_bias[1], e1_rx_bias[0] }),
304 .cfg_val({ pdm_e1[1][7:0], pdm_e1[0][7:0] }),
305 .cfg_oe ({ pdm_e1[1][8], pdm_e1[0][8] }),
306 .clk (clk),
307 .rst (rst)
308 );
309
310
311 // DFU / Reboot
312 // ------------
313
314 always @(posedge clk or posedge rst)
315 if (rst) begin
316 boot_now <= 1'b0;
317 boot_sel <= 2'b00;
318 end else if (bus_we_boot) begin
319 boot_now <= wb_wdata[2];
320 boot_sel <= wb_wdata[1:0];
321 end
322
323 dfu_helper #(
324 .TIMER_WIDTH(26),
325 .BTN_MODE(0),
326 .DFU_MODE(0)
327 ) dfu_I (
328 .boot_sel(boot_sel),
329 .boot_now(boot_now),
330 .btn_pad (btn_val),
331 .btn_tick(btn_stb),
332 .btn_val (),
333 .rst_req (rst_req),
334 .clk (clk),
335 .rst (rst)
336 );
337
338endmodule // misc