Added two additional features: (1) Timer chaining, which allows one
timer to be clocked from the output of the other, forming a 64-bit
timer, and (2) User power-good signal, memory-mapped so that the state
of the user's 1.8V power domain can be assessed (should have the same
for the 3.3V domains). Also: The routing of the PLL output and trap
and IRQ inputs was moved from the single gpio pin to additional bits
in the user space, and an additional output routing was made for the
secondary clock.
diff --git a/verilog/dv/caravel/defs.h b/verilog/dv/caravel/defs.h
index 96630f1..abfcd44 100644
--- a/verilog/dv/caravel/defs.h
+++ b/verilog/dv/caravel/defs.h
@@ -106,9 +106,11 @@
#define reg_spimaster_data (*(volatile uint32_t*)0x24000004)
// System Area (0x2F00_0000)
-#define reg_pll_out_dest (*(volatile uint32_t*)0x2F00000c)
-#define reg_trap_out_dest (*(volatile uint32_t*)0x2F000010)
-#define reg_irq7_source (*(volatile uint32_t*)0x2F000014)
+#define reg_clk1_out_dest (*(volatile uint32_t*)0x2F000000)
+#define reg_clk2_out_dest (*(volatile uint32_t*)0x2F000004)
+#define reg_trap_out_dest (*(volatile uint32_t*)0x2F000008)
+#define reg_irq7_source (*(volatile uint32_t*)0x2F00000C)
+#define reg_irq8_source (*(volatile uint32_t*)0x2F000010)
// Crossbar Slave Addresses (0x8000_0000 - 0xB000_0000)
#define qspi_ctrl_slave (*(volatile uint32_t*)0x80000000)
diff --git a/verilog/dv/wb_utests/sysctrl_wb/sysctrl_wb_tb.v b/verilog/dv/wb_utests/sysctrl_wb/sysctrl_wb_tb.v
index b4fc6a5..0086016 100644
--- a/verilog/dv/wb_utests/sysctrl_wb/sysctrl_wb_tb.v
+++ b/verilog/dv/wb_utests/sysctrl_wb/sysctrl_wb_tb.v
@@ -46,13 +46,17 @@
integer i;
// System Control Default Register Addresses
- wire [31:0] pll_out_adr = uut.BASE_ADR | uut.PLL_OUT;
+ wire [31:0] clk1_out_adr = uut.BASE_ADR | uut.CLK1_OUT;
+ wire [31:0] clk2_out_adr = uut.BASE_ADR | uut.CLK2_OUT;
wire [31:0] trap_out_adr = uut.BASE_ADR | uut.TRAP_OUT;
wire [31:0] irq7_src_adr = uut.BASE_ADR | uut.IRQ7_SRC;
+ wire [31:0] irq8_src_adr = uut.BASE_ADR | uut.IRQ8_SRC;
- reg pll_output_dest;
+ reg clk1_output_dest;
+ reg clk2_output_dest;
reg trap_output_dest;
reg irq_7_inputsrc;
+ reg irq_8_inputsrc;
initial begin
// Reset Operation
@@ -61,18 +65,28 @@
wb_rst_i = 0;
#2;
- pll_output_dest = 1'b1;
+ clk1_output_dest = 1'b1;
+ clk2_output_dest = 1'b1;
trap_output_dest = 1'b1;
irq_7_inputsrc = 1'b1;
+ irq_8_inputsrc = 1'b1;
// Write to System Control Registers
- write(pll_out_adr, pll_output_dest);
+ write(clk1_out_adr, clk1_output_dest);
+ write(clk2_out_adr, clk2_output_dest);
write(trap_out_adr, trap_output_dest);
write(irq7_src_adr, irq_7_inputsrc);
+ write(irq8_src_adr, irq_8_inputsrc);
#2;
- read(pll_out_adr);
- if (wb_dat_o !== pll_output_dest) begin
- $display("Error reading PLL output destination register.");
+ read(clk1_out_adr);
+ if (wb_dat_o !== clk1_output_dest) begin
+ $display("Error reading CLK1 output destination register.");
+ $finish;
+ end
+
+ read(clk2_out_adr);
+ if (wb_dat_o !== clk2_output_dest) begin
+ $display("Error reading CLK2 output destination register.");
$finish;
end
@@ -88,6 +102,12 @@
$finish;
end
+ read(irq8_src_adr);
+ if (wb_dat_o !== irq_8_inputsrc) begin
+ $display("Error reading IRQ8 input source register.");
+ $finish;
+ end
+
$display("Success!");
$finish;
end
diff --git a/verilog/rtl/caravel.v b/verilog/rtl/caravel.v
index e5af073..fbaaa5c 100644
--- a/verilog/rtl/caravel.v
+++ b/verilog/rtl/caravel.v
@@ -344,6 +344,8 @@
.la_output(la_output_core),
.la_oen(la_oen),
// User Project IO Control
+ .mprj_pwrgood(mprj_pwrgood),
+ .mprj2_pwrgood(mprj2_pwrgood),
.mprj_io_loader_resetn(mprj_io_loader_resetn),
.mprj_io_loader_clock(mprj_io_loader_clock),
.mprj_io_loader_data(mprj_io_loader_data),
@@ -389,6 +391,8 @@
wire [3:0] mprj_sel_o_user;
wire [31:0] mprj_adr_o_user;
wire [31:0] mprj_dat_o_user;
+ wire mprj_pwrgood;
+ wire mprj2_pwrgood;
mgmt_protect mgmt_buffers (
.vccd(vccd),
@@ -417,7 +421,9 @@
.mprj_sel_o_user(mprj_sel_o_user),
.mprj_adr_o_user(mprj_adr_o_user),
.mprj_dat_o_user(mprj_dat_o_user),
- .la_data_in_mprj(la_data_in_mprj)
+ .la_data_in_mprj(la_data_in_mprj),
+ .user1_powergood(mprj_pwrgood),
+ .user2_powergood(mprj2_pwrgood)
);
diff --git a/verilog/rtl/counter_timer.v b/verilog/rtl/counter_timer.v
index 9e25281..f569182 100755
--- a/verilog/rtl/counter_timer.v
+++ b/verilog/rtl/counter_timer.v
@@ -8,6 +8,7 @@
) (
input wb_clk_i,
input wb_rst_i,
+ input strobe_in,
input [31:0] wb_adr_i,
input [31:0] wb_dat_i,
input [3:0] wb_sel_i,
@@ -17,6 +18,7 @@
output wb_ack_o,
output [31:0] wb_dat_o,
+ output strobe_out,
output irq
);
wire [31:0] counter_timer_reg_cfg_do;
@@ -48,6 +50,7 @@
counter_timer counter_timer_inst (
.resetn(resetn),
.clkin(wb_clk_i),
+ .strobe_in(strobe_in),
.reg_val_we(reg_val_we),
.reg_val_di(mem_wdata),
.reg_val_do(counter_timer_reg_val_do),
@@ -57,6 +60,7 @@
.reg_dat_we(reg_dat_we),
.reg_dat_di(mem_wdata),
.reg_dat_do(counter_timer_reg_dat_do),
+ .strobe_out(strobe_out),
.irq_out(irq)
);
@@ -65,6 +69,7 @@
module counter_timer (
input resetn,
input clkin,
+ input strobe_in,
input [3:0] reg_val_we,
input [31:0] reg_val_di,
@@ -77,22 +82,25 @@
input [3:0] reg_dat_we,
input [31:0] reg_dat_di,
output [31:0] reg_dat_do,
+ output strobe_out,
output irq_out
);
reg [31:0] value_cur;
reg [31:0] value_reset;
-reg irq_out;
+reg strobe_out;
+wire irq_out;
reg enable; // Enable (start) the counter/timer
reg lastenable; // Previous state of enable (catch rising/falling edge)
reg oneshot; // Set oneshot (1) mode or continuous (0) mode
reg updown; // Count up (1) or down (0)
reg irq_ena; // Enable interrupt on timeout
+reg chain; // Chain to a secondary timer
// Configuration register
-assign reg_cfg_do = {28'd0, irq_ena, updown, oneshot, enable};
+assign reg_cfg_do = {27'd0, irq_ena, chain, updown, oneshot, enable};
always @(posedge clkin or negedge resetn) begin
if (resetn == 1'b0) begin
@@ -100,6 +108,7 @@
lastenable <= 1'b0;
oneshot <= 1'b0;
updown <= 1'b0;
+ chain <= 1'b0;
irq_ena <= 1'b0;
end else begin
lastenable <= enable;
@@ -107,7 +116,8 @@
enable <= reg_cfg_di[0];
oneshot <= reg_cfg_di[1];
updown <= reg_cfg_di[2];
- irq_ena <= reg_cfg_di[3];
+ chain <= reg_cfg_di[3];
+ irq_ena <= reg_cfg_di[4];
end
end
end
@@ -131,10 +141,12 @@
// Counter/timer current value register and timer implementation
+assign irq_out = (irq_ena) ? strobe_out : 1'b0;
+
always @(posedge clkin or negedge resetn) begin
if (resetn == 1'b0) begin
value_cur <= 32'd0;
- irq_out <= 1'b0;
+ strobe_out <= 1'b0;
end else begin
if (reg_dat_we != 4'b0000) begin
if (reg_dat_we[3] == 1'b1) value_cur[31:24] <= reg_dat_di[31:24];
@@ -149,10 +161,12 @@
if (oneshot != 1'b1) begin
value_cur <= 32'd0;
end
- irq_out <= irq_ena;
+ strobe_out <= 1'b1;
end else begin
- value_cur <= value_cur + 1; // count up
- irq_out <= 1'b0;
+ if ((chain == 1'b0) || ((chain == 1'b1) && (strobe_in == 1'b1))) begin
+ value_cur <= value_cur + 1; // count up
+ strobe_out <= 1'b0;
+ end
end
end else begin
if (lastenable == 1'b0) begin
@@ -161,14 +175,16 @@
if (oneshot != 1'b1) begin
value_cur <= value_reset;
end
- irq_out <= irq_ena;
+ strobe_out <= 1'b1;
end else begin
- value_cur <= value_cur - 1; // count down
- irq_out <= 1'b0;
+ if ((chain == 1'b0) || ((chain == 1'b1) && (strobe_in == 1'b1))) begin
+ value_cur <= value_cur - 1; // count down
+ strobe_out <= 1'b0;
+ end
end
end
end else begin
- irq_out <= 1'b0;
+ strobe_out <= 1'b0;
end
end
end
diff --git a/verilog/rtl/mgmt_core.v b/verilog/rtl/mgmt_core.v
index db8d599..4e99ee9 100644
--- a/verilog/rtl/mgmt_core.v
+++ b/verilog/rtl/mgmt_core.v
@@ -45,6 +45,8 @@
// User Project Control Signals
input [MPRJ_IO_PADS-1:0] mgmt_in_data,
output [MPRJ_IO_PADS-1:0] mgmt_out_data,
+ input mprj_pwrgood,
+ input mprj2_pwrgood,
output mprj_io_loader_resetn,
output mprj_io_loader_clock,
output mprj_io_loader_data,
@@ -123,6 +125,11 @@
// flash_sck = mgmt_out_data[9] (output) (user area flash)
// flash_io0 = mgmt_in/out_data[10] (input) (user area flash)
// flash_io1 = mgmt_in/out_data[11] (output) (user area flash)
+ // irq2_pin = mgmt_in_data[12] (input)
+ // trap_mon = mgmt_in_data[13] (output)
+ // clk1_mon = mgmt_in_data[14] (output)
+ // clk2_mon = mgmt_in_data[15] (output)
+
// OEB lines for [0] and [1] are the only ones connected directly to
// the pad. All others have OEB controlled by the configuration bit
@@ -179,11 +186,15 @@
.pass_thru_mgmt_sdo(pass_thru_mgmt_sdo),
// SPI master->slave direct connection
.hk_connect(hk_connect),
+ // Secondary clock (for monitoring)
+ .user_clk(user_clk),
// Logic Analyzer
.la_input(la_input),
.la_output(la_output),
.la_oen(la_oen),
// User Project I/O Configuration
+ .mprj_pwrgood(mprj_pwrgood),
+ .mprj2_pwrgood(mprj2_pwrgood),
.mprj_io_loader_resetn(mprj_io_loader_resetn),
.mprj_io_loader_clock(mprj_io_loader_clock),
.mprj_io_loader_data(mprj_io_loader_data),
diff --git a/verilog/rtl/mgmt_protect.v b/verilog/rtl/mgmt_protect.v
index 8865ee4..df32f81 100644
--- a/verilog/rtl/mgmt_protect.v
+++ b/verilog/rtl/mgmt_protect.v
@@ -18,6 +18,8 @@
inout vssd,
inout vccd1,
inout vssd1,
+ inout vccd2,
+ inout vssd2,
input caravel_clk,
input caravel_clk2,
@@ -40,12 +42,17 @@
output [3:0] mprj_sel_o_user,
output [31:0] mprj_adr_o_user,
output [31:0] mprj_dat_o_user,
- output [127:0] la_data_in_mprj
+ output [127:0] la_data_in_mprj,
+ output user1_powergood,
+ output user2_powergood
);
- wire [73:0] mprj_logic1;
+ wire [74:0] mprj_logic1;
+ wire mprj2_logic1;
+ wire user1_powergood;
+ wire user2_powergood;
- sky130_fd_sc_hd__conb_1 mprj_logic_high [73:0] (
+ sky130_fd_sc_hd__conb_1 mprj_logic_high [74:0] (
.VPWR(vccd1),
.VGND(vssd1),
.VPB(vccd1),
@@ -54,6 +61,16 @@
.LO()
);
+ sky130_fd_sc_hd__conb_1 mprj2_logic_high (
+ .VPWR(vccd2),
+ .VGND(vssd2),
+ .VPB(vccd2),
+ .VNB(vssd2),
+ .HI(mprj2_logic1),
+ .LO()
+ );
+
+
sky130_fd_sc_hd__einvp_8 mprj_rstn_buf (
.VPWR(vccd),
.VGND(vssd),
@@ -160,4 +177,26 @@
.TE(~la_oen)
);
+ /* The conb cell output is a resistive connection directly to */
+ /* the power supply, so when returning the user1_powergood */
+ /* signal, make sure that it is buffered properly. */
+
+ sky130_fd_sc_hd__buf_8 mprj_pwrgood (
+ .VPWR(vccd),
+ .VGND(vssd),
+ .VPB(vccd),
+ .VNB(vssd),
+ .A(mprj_logic1[74]),
+ .X(user1_powergood)
+ );
+
+ sky130_fd_sc_hd__buf_8 mprj2_pwrgood (
+ .VPWR(vccd),
+ .VGND(vssd),
+ .VPB(vccd),
+ .VNB(vssd),
+ .A(mprj_logic2),
+ .X(user2_powergood)
+ );
+
endmodule
diff --git a/verilog/rtl/mgmt_soc.v b/verilog/rtl/mgmt_soc.v
index 6778da0..6f2173f 100644
--- a/verilog/rtl/mgmt_soc.v
+++ b/verilog/rtl/mgmt_soc.v
@@ -70,6 +70,8 @@
output [127:0] la_oen, // LA output enable (active low)
// User Project I/O Configuration (serial load)
+ input mprj_pwrgood,
+ input mprj2_pwrgood,
output mprj_io_loader_resetn,
output mprj_io_loader_clock,
output mprj_io_loader_data,
@@ -120,6 +122,8 @@
// SPI master->slave direct link
output hk_connect,
+ // User clock monitoring
+ input user_clk,
// WB MI A (User project)
input mprj_ack_i,
@@ -197,9 +201,10 @@
parameter LA_ENA_3 = 8'h1c;
// System Control Registers
- parameter PLL_OUT = 8'h00;
- parameter TRAP_OUT = 8'h04;
- parameter IRQ7_SRC = 8'h08;
+ parameter PWRGOOD = 8'h00;
+ parameter CLK_OUT = 8'h04;
+ parameter TRAP_OUT = 8'h08;
+ parameter IRQ_SRC = 8'h0c;
// Wishbone Interconnect
localparam ADR_WIDTH = 32;
@@ -254,6 +259,10 @@
// flash_sck = mgmt_out_data[9] (output) (user area flash)
// flash_io0 = mgmt_in/out_data[10] (input) (user area flash)
// flash_io1 = mgmt_in/out_data[11] (output) (user area flash)
+ // irq2_pin = mgmt_in_data[12] (input)
+ // trap_mon = mgmt_in_data[13] (output)
+ // clk1_mon = mgmt_in_data[14] (output)
+ // clk2_mon = mgmt_in_data[15] (output)
// OEB lines for [0] and [1] are the only ones connected directly to
// the pad. All others have OEB controlled by the configuration bit
@@ -265,20 +274,11 @@
wire gpio_outenb; // Intermediate GPIO out enable (bar)
wire gpio_out; // Intermediate GPIO output
- wire gpio; // GPIO output data
- wire gpio_pu; // GPIO pull-up enable
- wire gpio_pd; // GPIO pull-down enable
- wire gpio_oeb; // GPIO output enable (sense negative)
-
- wire pll_output_dest; // PLL clock output destination
wire trap_output_dest; // Trap signal output destination
+ wire clk1_output_dest; // Core clock1 signal output destination
+ wire clk2_output_dest; // Core clock2 signal output destination
wire irq_7_inputsrc; // IRQ 7 source
-
- // GPIO assignments
- assign gpio_out = (trap_output_dest == 1'b1) ? trap : gpio;
- assign gpio_outenb = (trap_output_dest == 1'b0) ? gpio_oeb : 1'b0;
- assign gpio_pullup = (trap_output_dest == 1'b0) ? gpio_pu : 1'b0;
- assign gpio_pulldown = (trap_output_dest == 1'b0) ? gpio_pd : 1'b0;
+ wire irq_8_inputsrc; // IRQ 8 source
// Convert GPIO signals to sky130_fd_io pad signals
convert_gpio_sigs convert_gpio_bit (
@@ -295,6 +295,7 @@
reg [31:0] irq;
wire irq_7;
+ wire irq_8;
wire irq_stall;
wire irq_uart;
wire irq_spi_master;
@@ -303,6 +304,7 @@
assign irq_stall = 0;
assign irq_7 = (irq_7_inputsrc == 1'b1) ? mgmt_in_data[7] : 1'b0;
+ assign irq_8 = (irq_8_inputsrc == 1'b1) ? mgmt_in_data[12] : 1'b0;
always @* begin
irq = 0;
@@ -491,6 +493,8 @@
.irq(irq_spi_master)
);
+ wire strobe_counter_timer0, strobe_counter_timer1;
+
// Wishbone Counter-timer 0
wire counter_timer0_stb_i;
wire counter_timer0_ack_o;
@@ -505,6 +509,7 @@
// Wishbone Interface
.wb_clk_i(wb_clk_i),
.wb_rst_i(wb_rst_i),
+ .strobe_in(strobe_counter_timer1),
.wb_adr_i(cpu_adr_o),
.wb_dat_i(cpu_dat_o),
@@ -515,6 +520,7 @@
.wb_stb_i(counter_timer0_stb_i),
.wb_ack_o(counter_timer0_ack_o),
.wb_dat_o(counter_timer0_dat_o),
+ .strobe_out(strobe_counter_timer0),
.irq(irq_counter_timer0)
);
@@ -532,6 +538,7 @@
// Wishbone Interface
.wb_clk_i(wb_clk_i),
.wb_rst_i(wb_rst_i),
+ .strobe_in(strobe_counter_timer0),
.wb_adr_i(cpu_adr_o),
.wb_dat_i(cpu_dat_o),
@@ -542,6 +549,7 @@
.wb_stb_i(counter_timer1_stb_i),
.wb_ack_o(counter_timer1_ack_o),
.wb_dat_o(counter_timer1_dat_o),
+ .strobe_out(strobe_counter_timer1),
.irq(irq_counter_timer1)
);
@@ -568,10 +576,10 @@
.wb_ack_o(gpio_ack_o),
.wb_dat_o(gpio_dat_o),
.gpio_in_pad(gpio_in_pad),
- .gpio(gpio),
- .gpio_oeb(gpio_oeb),
- .gpio_pu(gpio_pu),
- .gpio_pd(gpio_pd)
+ .gpio(gpio_out),
+ .gpio_oeb(gpio_outenb),
+ .gpio_pu(gpio_pullup),
+ .gpio_pd(gpio_pulldown)
);
// Wishbone Slave System Control Register
@@ -581,9 +589,10 @@
sysctrl_wb #(
.BASE_ADR(SYS_BASE_ADR),
- .PLL_OUT(PLL_OUT),
+ .PWRGOOD(PWRGOOD),
+ .CLK_OUT(CLK_OUT),
.TRAP_OUT(TRAP_OUT),
- .IRQ7_SRC(IRQ7_SRC)
+ .IRQ_SRC(IRQ_SRC)
) sysctrl (
.wb_clk_i(wb_clk_i),
.wb_rst_i(wb_rst_i),
@@ -598,9 +607,13 @@
.wb_ack_o(sys_ack_o),
.wb_dat_o(sys_dat_o),
- .pll_output_dest(pll_output_dest),
+ .usr1_pwrgood(mprj_pwrgood),
+ .usr2_pwrgood(mprj2_pwrgood),
.trap_output_dest(trap_output_dest),
- .irq_7_inputsrc(irq_7_inputsrc)
+ .clk1_output_dest(clk1_output_dest),
+ .clk2_output_dest(clk2_output_dest),
+ .irq_7_inputsrc(irq_7_inputsrc),
+ .irq_8_inputsrc(irq_8_inputsrc)
);
// Logic Analyzer
@@ -646,7 +659,14 @@
// mprj GPIO-as-output from applying data when that function
// is active
- assign mgmt_out_data[MPRJ_IO_PADS-1:7] = mgmt_out_pre[MPRJ_IO_PADS-1:7];
+ assign mgmt_out_data[MPRJ_IO_PADS-1:16] = mgmt_out_pre[MPRJ_IO_PADS-1:16];
+
+ // Routing of output monitors (PLL, trap, clk1, clk2)
+ assign mgmt_out_data[15] = clk2_output_dest ? user_clk : mgmt_out_pre[15];
+ assign mgmt_out_data[14] = clk1_output_dest ? clk : mgmt_out_pre[14];
+ assign mgmt_out_data[13] = trap_output_dest ? trap : mgmt_out_pre[13];
+
+ assign mgmt_out_data[12:7] = mgmt_out_pre[12:7];
assign mgmt_out_data[6] = uart_enabled ? ser_tx : mgmt_out_pre[6];
assign mgmt_out_data[5:0] = mgmt_out_pre[5:0];
diff --git a/verilog/rtl/sysctrl.v b/verilog/rtl/sysctrl.v
index 86ec1e5..acdb045 100644
--- a/verilog/rtl/sysctrl.v
+++ b/verilog/rtl/sysctrl.v
@@ -1,8 +1,9 @@
module sysctrl_wb #(
- parameter BASE_ADR = 32'h2F00_0000,
- parameter PLL_OUT = 8'h00,
- parameter TRAP_OUT = 8'h04,
- parameter IRQ7_SRC = 8'h08
+ parameter BASE_ADR = 32'h2F00_0000,
+ parameter PWRGOOD = 8'h00,
+ parameter CLK_OUT = 8'h04,
+ parameter TRAP_OUT = 8'h08,
+ parameter IRQ_SRC = 8'h0c
) (
input wb_clk_i,
input wb_rst_i,
@@ -17,9 +18,13 @@
output [31:0] wb_dat_o,
output wb_ack_o,
- output pll_output_dest,
+ input usr1_pwrgood,
+ input usr2_pwrgood,
+ output clk1_output_dest,
+ output clk2_output_dest,
output trap_output_dest,
- output irq_7_inputsrc
+ output irq_7_inputsrc,
+ output irq_8_inputsrc
);
@@ -36,9 +41,10 @@
sysctrl #(
.BASE_ADR(BASE_ADR),
- .PLL_OUT(PLL_OUT),
+ .PWRGOOD(PWRGOOD),
+ .CLK_OUT(CLK_OUT),
.TRAP_OUT(TRAP_OUT),
- .IRQ7_SRC(IRQ7_SRC)
+ .IRQ_SRC(IRQ_SRC)
) sysctrl (
.clk(wb_clk_i),
.resetn(resetn),
@@ -50,9 +56,12 @@
.iomem_rdata(wb_dat_o),
.iomem_ready(ready),
- .pll_output_dest(pll_output_dest),
+ .usr1_pwrgood(usr1_pwrgood),
+ .usr2_pwrgood(usr2_pwrgood),
+ .clk1_output_dest(clk1_output_dest),
+ .clk2_output_dest(clk2_output_dest),
.trap_output_dest(trap_output_dest),
-
+ .irq_8_inputsrc(irq_8_inputsrc),
.irq_7_inputsrc(irq_7_inputsrc)
);
@@ -60,9 +69,10 @@
module sysctrl #(
parameter BASE_ADR = 32'h2300_0000,
- parameter PLL_OUT = 8'h00,
- parameter TRAP_OUT = 8'h04,
- parameter IRQ7_SRC = 8'h08
+ parameter PWRGOOD = 8'h00,
+ parameter CLK_OUT = 8'h04,
+ parameter TRAP_OUT = 8'h08,
+ parameter IRQ_SRC = 8'h0c
) (
input clk,
input resetn,
@@ -74,45 +84,63 @@
output reg [31:0] iomem_rdata,
output reg iomem_ready,
- output pll_output_dest,
+ input usr1_pwrgood,
+ input usr2_pwrgood,
+ output clk1_output_dest,
+ output clk2_output_dest,
output trap_output_dest,
- output irq_7_inputsrc
+ output irq_7_inputsrc,
+ output irq_8_inputsrc
);
- reg pll_output_dest;
+ reg clk1_output_dest;
+ reg clk2_output_dest;
reg trap_output_dest;
reg irq_7_inputsrc;
+ reg irq_8_inputsrc;
- assign pll_out_sel = (iomem_addr[7:0] == PLL_OUT);
+ wire usr1_pwrgood;
+ wire usr2_pwrgood;
+
+ assign pwrgood_sel = (iomem_addr[7:0] == PWRGOOD);
+ assign clk_out_sel = (iomem_addr[7:0] == CLK_OUT);
assign trap_out_sel = (iomem_addr[7:0] == TRAP_OUT);
-
- assign irq7_sel = (iomem_addr[7:0] == IRQ7_SRC);
+ assign irq_sel = (iomem_addr[7:0] == IRQ_SRC);
always @(posedge clk) begin
if (!resetn) begin
- pll_output_dest <= 0;
+ clk1_output_dest <= 0;
+ clk2_output_dest <= 0;
trap_output_dest <= 0;
irq_7_inputsrc <= 0;
+ irq_8_inputsrc <= 0;
end else begin
iomem_ready <= 0;
if (iomem_valid && !iomem_ready && iomem_addr[31:8] == BASE_ADR[31:8]) begin
iomem_ready <= 1'b 1;
- if (pll_out_sel) begin
- iomem_rdata <= {31'd0, pll_output_dest};
- if (iomem_wstrb[0])
- pll_output_dest <= iomem_wdata[0];
+ if (pwrgood_sel) begin
+ iomem_rdata <= {30'd0, usr2_pwrgood, usr1_pwrgood};
+ // These are read-only bits; no write behavior on wstrb.
+
+ end else if (clk_out_sel) begin
+ iomem_rdata <= {30'd0, clk2_output_dest, clk1_output_dest};
+ if (iomem_wstrb[0]) begin
+ clk1_output_dest <= iomem_wdata[0];
+ clk2_output_dest <= iomem_wdata[1];
+ end
end else if (trap_out_sel) begin
iomem_rdata <= {31'd0, trap_output_dest};
if (iomem_wstrb[0])
trap_output_dest <= iomem_wdata[0];
- end else if (irq7_sel) begin
- iomem_rdata <= {31'd0, irq_7_inputsrc};
- if (iomem_wstrb[0])
+ end else if (irq_sel) begin
+ iomem_rdata <= {30'd0, irq_8_inputsrc, irq_7_inputsrc};
+ if (iomem_wstrb[0]) begin
irq_7_inputsrc <= iomem_wdata[0];
-
+ irq_8_inputsrc <= iomem_wdata[1];
+ end
end
end
end