blob: 934ba0559f06928ba57cc7694c850c0062d61857 [file] [log] [blame]
/*
* misc.v
*
* vim: ts=4 sw=4
*
* Misc peripheral functions
*
* Copyright (C) 2019-2020 Sylvain Munaut <tnt@246tNt.com>
* SPDX-License-Identifier: CERN-OHL-S-2.0
*/
`default_nettype none
module misc (
// PDM outputs
output wire e1_vref_ct_pdm,
output wire e1_vref_p_pdm,
output wire e1_vref_n_pdm,
output wire clk_tune_hi,
output wire clk_tune_lo,
// Button
input wire btn,
// Ticks
input wire tick_e1_rx,
input wire tick_e1_tx,
input wire tick_usb_sof,
// Reset request
output wire rst_req,
// Wishbone
input wire [ 7:0] wb_addr,
output reg [31:0] wb_rdata,
input wire [31:0] wb_wdata,
input wire wb_we,
input wire wb_cyc,
output reg wb_ack,
// Clock / Reset
input wire clk,
input wire rst
);
// Signals
// -------
// Bus
wire bus_clr;
reg bus_we_boot;
reg [ 1:0] bus_we_pdm_clk;
reg [ 2:0] bus_we_pdm_e1;
// Counters
wire [15:0] cap_e1_rx;
wire [15:0] cap_e1_tx;
wire [31:0] cnt_time;
// PDM
reg [12:0] pdm_clk[0:1];
reg [ 8:0] pdm_e1[0:2];
// Boot
reg [1:0] boot_sel;
reg boot_now;
// Bus interface
// -------------
// Ack
always @(posedge clk)
wb_ack <= wb_cyc & ~wb_ack;
assign bus_clr = ~wb_cyc | wb_ack;
// Write enables
always @(posedge clk)
if (bus_clr | ~wb_we) begin
bus_we_boot <= 1'b0;
bus_we_pdm_clk[0] <= 1'b0;
bus_we_pdm_clk[1] <= 1'b0;
bus_we_pdm_e1[0] <= 1'b0;
bus_we_pdm_e1[1] <= 1'b0;
bus_we_pdm_e1[2] <= 1'b0;
end else begin
bus_we_boot <= wb_addr == 4'h0;
bus_we_pdm_clk[0] <= wb_addr == 4'h8;
bus_we_pdm_clk[1] <= wb_addr == 4'h9;
bus_we_pdm_e1[0] <= wb_addr == 4'ha;
bus_we_pdm_e1[1] <= wb_addr == 4'hb;
bus_we_pdm_e1[2] <= wb_addr == 4'hc;
end
// Read mux
always @(posedge clk)
if (bus_clr)
wb_rdata <= 32'h00000000;
else
case (wb_addr[3:0])
4'h4: wb_rdata <= { cap_e1_tx, cap_e1_rx };
4'h7: wb_rdata <= cnt_time;
4'h8: wb_rdata <= { pdm_clk[0][12], 19'h00000, pdm_clk[0][11:0] };
4'h9: wb_rdata <= { pdm_clk[1][12], 19'h00000, pdm_clk[1][11:0] };
4'ha: wb_rdata <= { pdm_e1[0][8], 23'h000000, pdm_e1[0][ 7:0] };
4'hb: wb_rdata <= { pdm_e1[1][8], 23'h000000, pdm_e1[1][ 7:0] };
4'hc: wb_rdata <= { pdm_e1[2][8], 23'h000000, pdm_e1[2][ 7:0] };
default: wb_rdata <= 32'hxxxxxxxx;
endcase
// Counters
// --------
// E1 ticks
capcnt #(
.W(16)
) e1_cnt_I[1:0] (
.cnt_cur (),
.cnt_cap ({cap_e1_tx, cap_e1_rx }),
.inc ({tick_e1_tx, tick_e1_rx}),
.cap (tick_usb_sof),
.clk (clk),
.rst (rst)
);
// Time
capcnt #(
.W(32)
) time_cnt_I (
.cnt_cur (cnt_time),
.cnt_cap (),
.inc (1'b1),
.cap (1'b0),
.clk (clk),
.rst (rst)
);
// PDM outputs
// -----------
// Registers
always @(posedge clk or posedge rst)
if (rst) begin
pdm_clk[0] <= 0; // 13'h1800;
pdm_clk[1] <= 0; // 13'h1800;
pdm_e1[0] <= 0; // 9'h190;
pdm_e1[1] <= 0; // 9'h190;
pdm_e1[2] <= 0; // 9'h190;
end else begin
if (bus_we_pdm_clk[0]) pdm_clk[0] <= { wb_wdata[31], wb_wdata[11:0] };
if (bus_we_pdm_clk[1]) pdm_clk[1] <= { wb_wdata[31], wb_wdata[11:0] };
if (bus_we_pdm_e1[0]) pdm_e1[0] <= { wb_wdata[31], wb_wdata[ 7:0] };
if (bus_we_pdm_e1[1]) pdm_e1[1] <= { wb_wdata[31], wb_wdata[ 7:0] };
if (bus_we_pdm_e1[2]) pdm_e1[2] <= { wb_wdata[31], wb_wdata[ 7:0] };
end
// PDM cores
pdm #(
.WIDTH(12),
.PHY("ICE40"),
.DITHER("YES")
) pdm_clk_I[1:0] (
.pdm ({ clk_tune_hi, clk_tune_lo }),
.cfg_val({ pdm_clk[1][11:0], pdm_clk[0][11:0] }),
.cfg_oe ({ pdm_clk[1][12], pdm_clk[0][12] }),
.clk (clk),
.rst (rst)
);
pdm #(
.WIDTH(8),
.PHY("ICE40"),
.DITHER("NO")
) pdm_e1_I[2:0] (
.pdm ({ e1_vref_ct_pdm, e1_vref_p_pdm, e1_vref_n_pdm }),
.cfg_val({ pdm_e1[2][7:0], pdm_e1[1][7:0], pdm_e1[0][7:0] }),
.cfg_oe ({ pdm_e1[2][8], pdm_e1[1][8], pdm_e1[0][8] }),
.clk (clk),
.rst (rst)
);
// DFU / Reboot
// ------------
always @(posedge clk or posedge rst)
if (rst) begin
boot_now <= 1'b0;
boot_sel <= 2'b00;
end else if (bus_we_boot) begin
boot_now <= wb_wdata[2];
boot_sel <= wb_wdata[1:0];
end
dfu_helper #(
.TIMER_WIDTH(26),
.BTN_MODE(3),
.DFU_MODE(0)
) dfu_I (
.boot_sel(boot_sel),
.boot_now(boot_now),
.btn_pad (btn),
.btn_val (),
.rst_req (rst_req),
.clk (clk),
.rst (rst)
);
endmodule // misc