blob: 7aaa068d8925ac39c0bc58d3998b28f9a3e0b524 [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
40 input wire [ 1:0] tick_e1_rx,
41 input wire [ 1:0] tick_e1_tx,
42 input wire tick_usb_sof,
43
44 // Reset request
45 output wire rst_req,
46
47 // Wishbone
48 input wire [ 7:0] wb_addr,
49 output reg [31:0] wb_rdata,
50 input wire [31:0] wb_wdata,
51 input wire wb_we,
52 input wire wb_cyc,
53 output reg wb_ack,
54
55 // Clock / Reset
56 input wire clk,
57 input wire rst
58);
59
60 // Signals
61 // -------
62
63 genvar i;
64
65 // Bus
66 wire bus_clr;
67 reg bus_we_boot;
68 reg bus_we_gpio;
69 reg bus_we_led;
70 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 Munautff0ab3e2020-10-03 20:15:28 +020086 wire [15:0] cap_e1_rx[0:1];
87 wire [15:0] cap_e1_tx[0:1];
88 wire [31:0] cap_gps;
89 wire [31:0] cnt_time;
Sylvain Munautbd83e532020-09-15 22:11:29 +020090
91 // PDM
92 reg [12:0] pdm_clk[0:1];
93 reg [ 8:0] pdm_e1[0:1];
94
95 // Boot
96 reg [1:0] boot_sel;
97 reg boot_now;
98
99
100 // Bus interface
101 // -------------
102
103 // Ack
104 always @(posedge clk)
105 wb_ack <= wb_cyc & ~wb_ack;
106
107 assign bus_clr = ~wb_cyc | wb_ack;
108
109 // Write enables
110 always @(posedge clk)
111 if (bus_clr | ~wb_we) begin
112 bus_we_boot <= 1'b0;
113 bus_we_gpio <= 1'b0;
114 bus_we_led <= 1'b0;
115 bus_we_pdm_clk[0] <= 1'b0;
116 bus_we_pdm_clk[1] <= 1'b0;
117 bus_we_pdm_e1[0] <= 1'b0;
118 bus_we_pdm_e1[1] <= 1'b0;
119 end else begin
120 bus_we_boot <= wb_addr == 4'h0;
121 bus_we_gpio <= wb_addr == 4'h1;
122 bus_we_led <= wb_addr == 4'h2;
123 bus_we_pdm_clk[0] <= wb_addr == 4'h8;
124 bus_we_pdm_clk[1] <= wb_addr == 4'h9;
125 bus_we_pdm_e1[0] <= wb_addr == 4'ha;
126 bus_we_pdm_e1[1] <= wb_addr == 4'hb;
127 end
128
129 // Read mux
130 always @(posedge clk)
131 if (bus_clr)
132 wb_rdata <= 32'h00000000;
133 else
134 case (wb_addr[3:0])
135 4'h1: wb_rdata <= { 12'h000, gpio_in, 4'h0, gpio_oe, 4'h0, gpio_out };
Sylvain Munaut3edf9dd2020-10-09 13:24:03 +0200136 4'h2: wb_rdata <= { 22'h000000, e1_led_active, e1_led };
Sylvain Munautbd83e532020-09-15 22:11:29 +0200137 4'h4: wb_rdata <= { cap_e1_tx[0], cap_e1_rx[0] };
138 4'h5: wb_rdata <= { cap_e1_tx[1], cap_e1_rx[1] };
139 4'h6: wb_rdata <= cap_gps;
140 4'h7: wb_rdata <= cnt_time;
Sylvain Munaut205a1312020-10-03 20:23:41 +0200141`ifdef WITH_PDM_READBACK
Sylvain Munautbd83e532020-09-15 22:11:29 +0200142 4'h8: wb_rdata <= { pdm_clk[0][12], 19'h00000, pdm_clk[0][11:0] };
143 4'h9: wb_rdata <= { pdm_clk[1][12], 19'h00000, pdm_clk[1][11:0] };
144 4'ha: wb_rdata <= { pdm_e1[0][8], 23'h000000, pdm_e1[0][ 7:0] };
145 4'hb: wb_rdata <= { pdm_e1[1][8], 23'h000000, pdm_e1[1][ 7:0] };
Sylvain Munaut205a1312020-10-03 20:23:41 +0200146`endif
Sylvain Munautbd83e532020-09-15 22:11:29 +0200147 default: wb_rdata <= 32'hxxxxxxxx;
148 endcase
149
150
151 // GPIO (incl gps reset)
152 // ----
153
154 // IOB
155 SB_IO #(
156 .PIN_TYPE(6'b110100), // Reg in/out/oe
157 .PULLUP(1'b1),
158 .IO_STANDARD("SB_LVCMOS")
159 ) gpio_iob_I[3:0] (
160 .PACKAGE_PIN ({gps_reset_n, gpio}),
161 .CLOCK_ENABLE (1'b1),
162 .INPUT_CLK (clk),
163 .OUTPUT_CLK (clk),
164 .OUTPUT_ENABLE(gpio_oe),
165 .D_OUT_0 (gpio_out),
166 .D_IN_0 (gpio_in)
167 );
168
169 // Bus
170 always @(posedge clk or posedge rst)
171 if (rst) begin
172 gpio_oe <= 4'h0;
173 gpio_out <= 4'h0;
174 end else if (bus_we_gpio) begin
175 gpio_oe <= wb_wdata[11:8];
176 gpio_out <= wb_wdata[ 3:0];
177 end
178
179
180 // E1 led status
181 // -------------
182
183 always @(posedge clk or posedge rst)
184 if (rst)
185 e1_led <= 9'h00;
186 else if (bus_we_led)
187 e1_led <= wb_wdata[8:0];
188
189 assign e1_led_state = e1_led[7:0];
190 assign e1_led_run = e1_led[8];
191
192
193 // PPS input
194 // ---------
195
196 // IO reg
197 SB_IO #(
198 .PIN_TYPE(6'b000000), // Reg input, no output
199 .PULLUP(1'b0),
200 .IO_STANDARD("SB_LVCMOS")
Sylvain Munaut9e02d4c2022-05-03 13:59:49 +0200201 ) pps_iob_I (
Sylvain Munautbd83e532020-09-15 22:11:29 +0200202 .PACKAGE_PIN(gps_pps),
203 .INPUT_CLK (clk),
204 .D_IN_0 (gps_pps_iob)
205 );
206
207 // Deglitch
208 glitch_filter #(
209 .L(2),
210 .RST_VAL(1'b0),
211 .WITH_SYNCHRONIZER(1)
Sylvain Munaut9e02d4c2022-05-03 13:59:49 +0200212 ) pps_flt_I (
Sylvain Munautbd83e532020-09-15 22:11:29 +0200213 .in (gps_pps_iob),
214 .val (),
215 .rise (gps_pps_r),
216 .fall (),
217 .clk (clk),
218`ifdef SIM
219 .rst (rst)
220`else
221 // Don't reset so we let the filter settle before
222 // the rest of the logic engages
223 .rst (1'b0)
224`endif
225 );
226
227
228 // Counters
229 // --------
230
231 // E1 ticks
Sylvain Munautff0ab3e2020-10-03 20:15:28 +0200232 capcnt #(
233 .W(16)
234 ) e1_cnt_I[3:0] (
235 .cnt_cur (),
236 .cnt_cap ({cap_e1_tx[1], cap_e1_rx[1], cap_e1_tx[0], cap_e1_rx[0] }),
237 .inc ({tick_e1_tx[1], tick_e1_rx[1], tick_e1_tx[0], tick_e1_rx[0]}),
238 .cap (tick_usb_sof),
239 .clk (clk),
240 .rst (rst)
241 );
Sylvain Munautbd83e532020-09-15 22:11:29 +0200242
Sylvain Munautff0ab3e2020-10-03 20:15:28 +0200243 // Time / GPS
244 capcnt #(
245 .W(32)
246 ) time_cnt_I (
247 .cnt_cur (cnt_time),
248 .cnt_cap (cap_gps),
249 .inc (1'b1),
250 .cap (gps_pps_r),
251 .clk (clk),
252 .rst (rst)
253 );
Sylvain Munautbd83e532020-09-15 22:11:29 +0200254
255
256 // PDM outputs
257 // -----------
258
259 // Registers
260 always @(posedge clk or posedge rst)
261 if (rst) begin
262 pdm_clk[0] <= 0; // 13'h1800;
263 pdm_clk[1] <= 0; // 13'h1800;
264 pdm_e1[0] <= 0; // 9'h190;
265 pdm_e1[1] <= 0; // 9'h190;
266 end else begin
267 if (bus_we_pdm_clk[0]) pdm_clk[0] <= { wb_wdata[31], wb_wdata[11:0] };
268 if (bus_we_pdm_clk[1]) pdm_clk[1] <= { wb_wdata[31], wb_wdata[11:0] };
269 if (bus_we_pdm_e1[0]) pdm_e1[0] <= { wb_wdata[31], wb_wdata[ 7:0] };
270 if (bus_we_pdm_e1[1]) pdm_e1[1] <= { wb_wdata[31], wb_wdata[ 7:0] };
271 end
272
273 // PDM cores
274 pdm #(
275 .WIDTH(12),
276 .PHY("ICE40"),
277 .DITHER("YES")
278 ) pdm_clk_I[1:0] (
279 .pdm ({ clk_tune_hi, clk_tune_lo }),
280 .cfg_val({ pdm_clk[1][11:0], pdm_clk[0][11:0] }),
281 .cfg_oe ({ pdm_clk[1][12], pdm_clk[0][12] }),
282 .clk (clk),
283 .rst (rst)
284 );
285
286 pdm #(
287 .WIDTH(8),
288 .PHY("ICE40"),
289 .DITHER("NO")
290 ) pdm_e1_I[1:0] (
291 .pdm ({ e1_rx_bias[1], e1_rx_bias[0] }),
292 .cfg_val({ pdm_e1[1][7:0], pdm_e1[0][7:0] }),
293 .cfg_oe ({ pdm_e1[1][8], pdm_e1[0][8] }),
294 .clk (clk),
295 .rst (rst)
296 );
297
298
299 // DFU / Reboot
300 // ------------
301
302 always @(posedge clk or posedge rst)
303 if (rst) begin
304 boot_now <= 1'b0;
305 boot_sel <= 2'b00;
306 end else if (bus_we_boot) begin
307 boot_now <= wb_wdata[2];
308 boot_sel <= wb_wdata[1:0];
309 end
310
311 dfu_helper #(
312 .TIMER_WIDTH(26),
313 .BTN_MODE(0),
314 .DFU_MODE(0)
315 ) dfu_I (
316 .boot_sel(boot_sel),
317 .boot_now(boot_now),
318 .btn_pad (btn_val),
319 .btn_tick(btn_stb),
320 .btn_val (),
321 .rst_req (rst_req),
322 .clk (clk),
323 .rst (rst)
324 );
325
326endmodule // misc