Skip to content

Commit

Permalink
[fpga] Increase CW310 base clock frequency to 24 MHz
Browse files Browse the repository at this point in the history
Set clock frequencies for CW310 to the following

clk_main:    24 MHz
clk_io_div4: 6 MHz

Also improve the SPI_HOST timing constraints to have the correct max
frequency, in addition to multicycle paths reflecting the correct
capture edges.

Signed-off-by: Alexander Williams <awill@opentitan.org>
  • Loading branch information
a-will committed Aug 8, 2023
1 parent f3e75ce commit 248e452
Show file tree
Hide file tree
Showing 6 changed files with 182 additions and 54 deletions.
21 changes: 0 additions & 21 deletions hw/top_earlgrey/clkgen_xil7series.core

This file was deleted.

34 changes: 19 additions & 15 deletions hw/top_earlgrey/data/clocks.xdc
Original file line number Diff line number Diff line change
Expand Up @@ -231,14 +231,29 @@ set_input_delay -clock clk_spi_pt -clock_fall -max ${spi_host_in_delay_max} \
# SPI Host clock origin buffer
set spi_host_0_peri [get_pins top_earlgrey/u_clkmgr_aon/u_clk_io_peri_cg/gen_xilinx.u_impl_xilinx/gen_gate.gen_bufgce.u_bufgce/O]

# Even though it's 2x the max possible frequency, keep the peripheral clock
# frequency for the output. This will enable shifting the latch edge for hold
# analysis by the proper amount to effect "half-cycle sampling" of SPI.
create_generated_clock -name clk_spi_host0 -divide_by 1 -add \
create_generated_clock -name clk_spi_host0 -divide_by 2 -add \
-source ${spi_host_0_peri} \
-master_clock [get_clocks -of_objects ${spi_host_0_peri}] \
[get_ports SPI_HOST_CLK]

# Multi-cycle path to adjust the hold edge, since launch and capture edges are
# opposite in the SPI_HOST_CLK domain.
set_multicycle_path -setup 1 -start \
-from [get_clocks -of_objects ${spi_host_0_peri}] \
-to [get_clocks clk_spi_host0]
set_multicycle_path -hold 1 -start \
-from [get_clocks -of_objects ${spi_host_0_peri}] \
-to [get_clocks clk_spi_host0]

# set multicycle path for data going from SPI_HOST_CLK to logic
# the SPI host logic will read these paths at "full cycle"
set_multicycle_path -setup -end 2 \
-from [get_clocks clk_spi_host0] \
-to [get_clocks -of_objects ${spi_host_0_peri}]
set_multicycle_path -hold -end 2 \
-from [get_clocks clk_spi_host0] \
-to [get_clocks -of_objects ${spi_host_0_peri}]

set spi_host_0_data [get_ports {SPI_HOST_D0 SPI_HOST_D1 SPI_HOST_D2 SPI_HOST_D3 SPI_HOST_CS_L}]
set_output_delay -clock clk_spi_host0 -min ${spi_host_out_hold} \
${spi_host_0_data} -add_delay
Expand All @@ -249,17 +264,6 @@ set_input_delay -clock clk_spi_host0 -clock_fall -min ${spi_host_in_delay_min}
set_input_delay -clock clk_spi_host0 -clock_fall -max ${spi_host_in_delay_max} \
${spi_host_0_data} -add_delay

# The setup analysis is already correct for half-cycle sampling: If the first
# posedge of the peripheral clock represents the negedge of SPI_HOST_CLK, then
# the next posedge of the peripheral clock is when data should be latched, the
# posedge of SPI_HOST_CLK.
# However, the latch edge for hold analysis represents the same edge and needs
# to be advanced by one cycle of the peripheral clock (half a cycle of
# SPI_HOST_CLK).
set_multicycle_path -hold -end \
-from [get_clocks -of_objects ${spi_host_0_peri}] \
-to [get_clocks clk_spi_host0] 1

## Set asynchronous clock groups
set_clock_groups -asynchronous \
-group {clk_main clk_spi_host0} \
Expand Down
26 changes: 13 additions & 13 deletions hw/top_earlgrey/rtl/clkgen_xil7series.sv
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ module clkgen_xil7series # (
logic locked_pll;
logic io_clk_buf;
logic io_rst_buf_n;
logic clk_10_buf;
logic clk_10_unbuf;
logic clk_main_buf;
logic clk_main_unbuf;
logic clk_fb_buf;
logic clk_fb_unbuf;
logic clk_48_buf;
Expand All @@ -30,10 +30,11 @@ module clkgen_xil7series # (
.BANDWIDTH ("OPTIMIZED"),
.COMPENSATION ("ZHOLD"),
.STARTUP_WAIT ("FALSE"),
.DIVCLK_DIVIDE (1),
.CLKFBOUT_MULT_F (12.000),
.CLKIN1_PERIOD (10.000), // f_CLKIN = 100 MHz
.DIVCLK_DIVIDE (1), // f_PFD = 100 MHz
.CLKFBOUT_MULT_F (12.000), // f_VCO = 1200 MHz
.CLKFBOUT_PHASE (0.000),
.CLKOUT0_DIVIDE_F (120.0),
.CLKOUT0_DIVIDE_F (50.0), // f_main = 24 MHz
.CLKOUT0_PHASE (0.000),
.CLKOUT0_DUTY_CYCLE (0.500),
.CLKOUT1_DIVIDE (25),
Expand All @@ -45,12 +46,11 @@ module clkgen_xil7series # (
.CLKOUT4_PHASE (0.000),
.CLKOUT4_DUTY_CYCLE (0.500),
.CLKOUT4_CASCADE ("TRUE"),
.CLKOUT6_DIVIDE (120),
.CLKIN1_PERIOD (10.000)
.CLKOUT6_DIVIDE (120)
) pll (
.CLKFBOUT (clk_fb_unbuf),
.CLKFBOUTB (),
.CLKOUT0 (clk_10_unbuf),
.CLKOUT0 (clk_main_unbuf),
.CLKOUT0B (),
.CLKOUT1 (clk_48_unbuf),
.CLKOUT1B (),
Expand Down Expand Up @@ -100,9 +100,9 @@ module clkgen_xil7series # (
);

if (AddClkBuf == 1) begin : gen_clk_bufs
BUFG clk_10_bufg (
.I (clk_10_unbuf),
.O (clk_10_buf)
BUFG clk_main_bufg (
.I (clk_main_unbuf),
.O (clk_main_buf)
);

BUFG clk_48_bufg (
Expand All @@ -111,13 +111,13 @@ module clkgen_xil7series # (
);
end else begin : gen_no_clk_bufs
// BUFGs added by downstream modules, no need to add here
assign clk_10_buf = clk_10_unbuf;
assign clk_main_buf = clk_main_unbuf;
assign clk_48_buf = clk_48_unbuf;
end

// outputs
// clock
assign clk_main_o = clk_10_buf;
assign clk_main_o = clk_main_buf;
assign clk_48MHz_o = clk_48_buf;
assign clk_aon_o = clk_aon_buf;

Expand Down
1 change: 0 additions & 1 deletion hw/top_englishbreakfast/clkgen_xil7series.core

This file was deleted.

21 changes: 21 additions & 0 deletions hw/top_englishbreakfast/clkgen_xil7series.core
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
CAPI=2:
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0

# TODO: long term this should be merged into AST.

name: "lowrisc:systems:clkgen_xil7series"
description: "Clock generation infrastructure for Xilinx 7-Series FPGAs."
filesets:
files_rtl:
files:
- rtl/clkgen_xil7series.sv
# piggy-back here for now
- rtl/usr_access_xil7series.sv
file_type: systemVerilogSource

targets:
default:
filesets:
- files_rtl
1 change: 0 additions & 1 deletion hw/top_englishbreakfast/rtl/clkgen_xil7series.sv

This file was deleted.

126 changes: 126 additions & 0 deletions hw/top_englishbreakfast/rtl/clkgen_xil7series.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

module clkgen_xil7series # (
// Add BUFG if not done by downstream logic
parameter bit AddClkBuf = 1
) (
input clk_i,
input rst_ni,
input srst_ni,
output clk_main_o,
output clk_48MHz_o,
output clk_aon_o,
output rst_no
);
logic locked_pll;
logic io_clk_buf;
logic io_rst_buf_n;
logic clk_25_buf;
logic clk_25_unbuf;
logic clk_fb_buf;
logic clk_fb_unbuf;
logic clk_48_buf;
logic clk_48_unbuf;
logic clk_aon_buf;
logic clk_aon_unbuf;

MMCME2_ADV #(
.BANDWIDTH ("OPTIMIZED"),
.COMPENSATION ("ZHOLD"),
.STARTUP_WAIT ("FALSE"),
.DIVCLK_DIVIDE (1),
.CLKFBOUT_MULT_F (12.000),
.CLKFBOUT_PHASE (0.000),
.CLKOUT0_DIVIDE_F (120.0),
.CLKOUT0_PHASE (0.000),
.CLKOUT0_DUTY_CYCLE (0.500),
.CLKOUT1_DIVIDE (25),
.CLKOUT1_PHASE (0.000),
.CLKOUT1_DUTY_CYCLE (0.500),
// With CLKOUT4_CASCADE, CLKOUT6's divider is an input to CLKOUT4's
// divider. The effective ratio is a multiplication of the two.
.CLKOUT4_DIVIDE (40),
.CLKOUT4_PHASE (0.000),
.CLKOUT4_DUTY_CYCLE (0.500),
.CLKOUT4_CASCADE ("TRUE"),
.CLKOUT6_DIVIDE (120),
.CLKIN1_PERIOD (10.000)
) pll (
.CLKFBOUT (clk_fb_unbuf),
.CLKFBOUTB (),
.CLKOUT0 (clk_25_unbuf),
.CLKOUT0B (),
.CLKOUT1 (clk_48_unbuf),
.CLKOUT1B (),
.CLKOUT2 (),
.CLKOUT2B (),
.CLKOUT3 (),
.CLKOUT3B (),
.CLKOUT4 (clk_aon_unbuf),
.CLKOUT5 (),
.CLKOUT6 (),
// Input clock control
.CLKFBIN (clk_fb_buf),
.CLKIN1 (clk_i),
.CLKIN2 (1'b0),
// Tied to always select the primary input clock
.CLKINSEL (1'b1),
// Ports for dynamic reconfiguration
.DADDR (7'h0),
.DCLK (1'b0),
.DEN (1'b0),
.DI (16'h0),
.DO (),
.DRDY (),
.DWE (1'b0),
// Phase shift signals
.PSCLK (1'b0),
.PSEN (1'b0),
.PSINCDEC (1'b0),
.PSDONE (),
// Other control and status signals
.CLKFBSTOPPED (),
.CLKINSTOPPED (),
.LOCKED (locked_pll),
.PWRDWN (1'b0),
// Do not reset MMCM on external reset, otherwise ILA disconnects at a reset
.RST (1'b0));

// output buffering
BUFG clk_fb_bufg (
.I (clk_fb_unbuf),
.O (clk_fb_buf)
);

BUFG clk_aon_bufg (
.I (clk_aon_unbuf),
.O (clk_aon_buf)
);

if (AddClkBuf == 1) begin : gen_clk_bufs
BUFG clk_25_bufg (
.I (clk_25_unbuf),
.O (clk_25_buf)
);

BUFG clk_48_bufg (
.I (clk_48_unbuf),
.O (clk_48_buf)
);
end else begin : gen_no_clk_bufs
// BUFGs added by downstream modules, no need to add here
assign clk_25_buf = clk_25_unbuf;
assign clk_48_buf = clk_48_unbuf;
end

// outputs
// clock
assign clk_main_o = clk_25_buf;
assign clk_48MHz_o = clk_48_buf;
assign clk_aon_o = clk_aon_buf;

// reset
assign rst_no = locked_pll & rst_ni & srst_ni;
endmodule
6 changes: 3 additions & 3 deletions sw/device/lib/arch/device_fpga_cw310.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@

const device_type_t kDeviceType = kDeviceFpgaCw310;

const uint64_t kClockFreqCpuMhz = 10;
const uint64_t kClockFreqCpuMhz = 24;

const uint64_t kClockFreqCpuHz = kClockFreqCpuMhz * 1000 * 1000;

uint64_t to_cpu_cycles(uint64_t usec) { return usec * kClockFreqCpuMhz; }

const uint64_t kClockFreqHiSpeedPeripheralHz = 10 * 1000 * 1000; // 10MHz
const uint64_t kClockFreqHiSpeedPeripheralHz = 24 * 1000 * 1000; // 24MHz

const uint64_t kClockFreqPeripheralHz = 25 * 100 * 1000; // 2.5MHz
const uint64_t kClockFreqPeripheralHz = 6 * 1000 * 1000; // 6MHz

const uint64_t kClockFreqUsbHz = 48 * 1000 * 1000; // 48MHz

Expand Down

0 comments on commit 248e452

Please sign in to comment.