Files
b210-k7-fpga/top/x400/cpld/common/ps_power_regs.v
T
Javier Valenzuela ffdcc016cc fpga: x4xx: Refactor MB CPLD code for future devices
Original-commit: e2a79712a7949ffec88135236c744dc5d8bde217
2023-05-23 09:05:27 +02:00

232 lines
7.3 KiB
Verilog

//
// Copyright 2021 Ettus Research, A National Instruments Brand
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// Module: ps_power_regs
//
// Description:
//
// Registers to control power supplies on the motherboard.
//
// Parameters:
//
// BASE_ADDRESS : Base address for CtrlPort registers.
// NUM_ADDRESSES : Number of bytes of address space to use.
//
`default_nettype none
module ps_power_regs #(
parameter BASE_ADDRESS = 0,
parameter NUM_ADDRESSES = 32
) (
input wire ctrlport_clk,
input wire ctrlport_rst,
// Request
input wire s_ctrlport_req_wr,
input wire s_ctrlport_req_rd,
input wire [19:0] s_ctrlport_req_addr,
input wire [31:0] s_ctrlport_req_data,
// Response
output reg s_ctrlport_resp_ack,
output reg [ 1:0] s_ctrlport_resp_status,
output reg [31:0] s_ctrlport_resp_data,
// iPass
output reg ipass_power_disable = 1'b0,
input wire [ 1:0] ipass_power_fault_n,
// Oscillators
output reg osc_100_en,
output reg osc_122_88_en
);
`include "../regmap/ps_power_regmap_utils.vh"
`include "../../../../lib/rfnoc/core/ctrlport.vh"
//----------------------------------------------------------
// Address Calculation
//----------------------------------------------------------
wire address_in_range = (s_ctrlport_req_addr >= BASE_ADDRESS) &&
(s_ctrlport_req_addr < BASE_ADDRESS + NUM_ADDRESSES);
//----------------------------------------------------------
// Internal Registers
//----------------------------------------------------------
reg [1:0] ipass_power_sticky = 2'b00;
reg [1:0] ipass_clear_sticky = 2'b00;
//----------------------------------------------------------
// Handling of ControlPort Requests
//----------------------------------------------------------
always @(posedge ctrlport_clk) begin
// Reset internal registers and responses
if (ctrlport_rst) begin
ipass_power_disable <= 1'b0;
s_ctrlport_resp_ack <= 1'b0;
s_ctrlport_resp_status <= CTRL_STS_OKAY;
s_ctrlport_resp_data <= {CTRLPORT_ADDR_W {1'bx}};
osc_100_en <= 1'b0;
osc_122_88_en <= 1'b0;
end else begin
// Default assignments
ipass_clear_sticky <= 2'b00;
// Write requests
if (s_ctrlport_req_wr) begin
// Always issue an ack and no data
s_ctrlport_resp_ack <= 1'b1;
s_ctrlport_resp_status <= CTRL_STS_OKAY;
s_ctrlport_resp_data <= {CTRLPORT_ADDR_W {1'bx}};
case (s_ctrlport_req_addr)
BASE_ADDRESS + IPASS_POWER_REG: begin
ipass_power_disable <= s_ctrlport_req_data[IPASS_DISABLE_POWER_BIT];
ipass_clear_sticky[0] <= s_ctrlport_req_data[IPASS_CLEAR_POWER_FAULT0];
ipass_clear_sticky[1] <= s_ctrlport_req_data[IPASS_CLEAR_POWER_FAULT1];
end
BASE_ADDRESS + OSC_POWER_REG: begin
osc_100_en <= s_ctrlport_req_data[OSC_100];
osc_122_88_en <= s_ctrlport_req_data[OSC_122_88];
end
// Error on undefined address
default: begin
if (address_in_range) begin
s_ctrlport_resp_status <= CTRL_STS_CMDERR;
// No response if out of range
end else begin
s_ctrlport_resp_ack <= 1'b0;
end
end
endcase
// Read request
end else if (s_ctrlport_req_rd) begin
// Default assumption: valid request
s_ctrlport_resp_ack <= 1'b1;
s_ctrlport_resp_status <= CTRL_STS_OKAY;
s_ctrlport_resp_data <= {CTRLPORT_DATA_W {1'b0}};
case (s_ctrlport_req_addr)
BASE_ADDRESS + IPASS_POWER_REG: begin
s_ctrlport_resp_data[IPASS_DISABLE_POWER_BIT] <= ipass_power_disable;
s_ctrlport_resp_data[IPASS_POWER_FAULT0] <= ipass_power_sticky[0];
s_ctrlport_resp_data[IPASS_POWER_FAULT1] <= ipass_power_sticky[1];
end
BASE_ADDRESS + OSC_POWER_REG: begin
s_ctrlport_resp_data[OSC_100] <= osc_100_en;
s_ctrlport_resp_data[OSC_122_88] <= osc_122_88_en;
end
// Error on undefined address
default: begin
s_ctrlport_resp_data <= {CTRLPORT_DATA_W {1'bx}};
if (address_in_range) begin
s_ctrlport_resp_status <= CTRL_STS_CMDERR;
// No response if out of range
end else begin
s_ctrlport_resp_ack <= 1'b0;
end
end
endcase
// No request
end else begin
s_ctrlport_resp_ack <= 1'b0;
end
end
end
//----------------------------------------------------------
// Sticky Logic of Power Registers
//----------------------------------------------------------
// Synchronize asynchronous inputs
wire [1:0] ipass_power_fault_lcl_n;
synchronizer #(
.WIDTH (2),
.STAGES (2),
.INITIAL_VAL (1'b0),
.FALSE_PATH_TO_IN (1)
) power_fault_sync (
.clk (ctrlport_clk),
.rst (ctrlport_rst),
.in (ipass_power_fault_n),
.out (ipass_power_fault_lcl_n)
);
always @(posedge ctrlport_clk) begin
if (ctrlport_rst) begin
ipass_power_sticky <= 2'b00;
end else begin
// Keep value if not cleared or set in case of fault
ipass_power_sticky <= (ipass_power_sticky & ~ipass_clear_sticky) | ~ipass_power_fault_lcl_n;
end
end
endmodule
`default_nettype wire
//XmlParse xml_on
//<regmap name="PS_POWER_REGMAP" readablestrobes="false" generatevhdl="true" ettusguidelines="true">
// <group name="PS_POWER_REGS">
// <info>
// Registers to control power supplies on the motherboard.
// </info>
//
// <register name="IPASS_POWER_REG" offset="0x00" size="32">
// <info>Controls the power supplies for the iPass connectors.</info>
// <bitfield name="IPASS_DISABLE_POWER_BIT" range="0">
// <info>Set to 1 to disable power for both iPass connectors.</info>
// </bitfield>
// <bitfield name="IPASS_CLEAR_POWER_FAULT0" range="30" readable="false">
// <info>Clear @.IPASS_POWER_FAULT0.</info>
// </bitfield>
// <bitfield name="IPASS_CLEAR_POWER_FAULT1" range="31" readable="false">
// <info>Clear @.IPASS_POWER_FAULT1.</info>
// </bitfield>
// <bitfield name="IPASS_POWER_FAULT0" range="30" writable="false">
// <info>
// Asserted signal indicates a power fault in power switch for iPass
// connector 0. Sticky bit. Asserted on occurrence. Reset using
// @.IPASS_CLEAR_POWER_FAULT0.
// </info>
// </bitfield>
// <bitfield name="IPASS_POWER_FAULT1" range="31" writable="false">
// <info>
// Asserted signal indicates a power fault in power switch for iPass
// connector 1. Sticky bit. Asserted on occurrence. Reset using
// @.IPASS_CLEAR_POWER_FAULT1.
// </info>
// </bitfield>
// </register>
//
// <register name="OSC_POWER_REG" offset="0x04" size="32">
// <info>Controls the power supplies for the oscillators.</info>
// <bitfield name="OSC_100" range="0">
// <info>Enables 5V power switch for the 100 MHz oscillator.</info>
// </bitfield>
// <bitfield name="OSC_122_88" range="1">
// <info>Enables 5V power switch for the 122.88 MHz oscillator.</info>
// </bitfield>
// </register>
// </group>
//</regmap>
//XmlParse xml_off