diff --git a/example_soc/fpga/fpga_icebreaker.f b/example_soc/fpga/fpga_icebreaker.f index 823be01..03f19af 100644 --- a/example_soc/fpga/fpga_icebreaker.f +++ b/example_soc/fpga/fpga_icebreaker.f @@ -1,5 +1,5 @@ file fpga_icebreaker.v -list ../soc/soc.f - file ../libfpga/common/reset_sync.v file ../libfpga/common/fpga_reset.v + +list ../soc/soc.f diff --git a/example_soc/fpga/fpga_icebreaker.v b/example_soc/fpga/fpga_icebreaker.v index 1bb599c..c9ac1cf 100644 --- a/example_soc/fpga/fpga_icebreaker.v +++ b/example_soc/fpga/fpga_icebreaker.v @@ -61,7 +61,10 @@ reset_sync trst_sync_u ( .rst_n_out (trst_n) ); -example_soc soc_u ( +example_soc #( + .MUL_FAST (1), + .EXTENSION_C (0) +) soc_u ( .clk (clk_sys), .rst_n (rst_n_sys), diff --git a/example_soc/fpga/fpga_ulx3s.f b/example_soc/fpga/fpga_ulx3s.f index 784a0a2..0d9490b 100644 --- a/example_soc/fpga/fpga_ulx3s.f +++ b/example_soc/fpga/fpga_ulx3s.f @@ -1,9 +1,11 @@ file fpga_ulx3s.v -list ../soc/soc.f - -# ECP5 DTM is not in main list because the JTAGG primitive doesn't exist on -# most platforms -list ../../hdl/debug/dtm/hazard3_ecp5_jtag_dtm.f - +file pll_25_50.v file ../libfpga/common/reset_sync.v file ../libfpga/common/fpga_reset.v + +list ../soc/soc.f + +# ECP5 DTM is not in main SoC list because the JTAGG primitive doesn't exist +# on most platforms +list ../../hdl/debug/dtm/hazard3_ecp5_jtag_dtm.f + diff --git a/example_soc/fpga/fpga_ulx3s.v b/example_soc/fpga/fpga_ulx3s.v index 6661599..5015f53 100644 --- a/example_soc/fpga/fpga_ulx3s.v +++ b/example_soc/fpga/fpga_ulx3s.v @@ -25,24 +25,37 @@ module fpga_ulx3s ( input wire uart_rx ); -wire clk_sys = clk_osc; +wire clk_sys; +wire pll_sys_locked; wire rst_n_sys; -wire trst_n; + +pll_25_50 pll_sys ( + .clkin (clk_osc), + .clkout0 (clk_sys), + .locked (pll_sys_locked) +); fpga_reset #( .SHIFT (3) ) rstgen ( .clk (clk_sys), - .force_rst_n (1'b1), + .force_rst_n (pll_sys_locked), .rst_n (rst_n_sys) ); example_soc #( - .DTM_TYPE ("ECP5") + .DTM_TYPE ("ECP5"), + .SRAM_DEPTH (1 << 10), + + .CSR_COUNTER (0), + .MUL_FAST (0), + .EXTENSION_C (0), + .EXTENSION_M (0), ) soc_u ( .clk (clk_sys), .rst_n (rst_n_sys), + // JTAG connections provided internally by ECP5 JTAGG primitive .tck (1'b0), .trst_n (1'b0), .tms (1'b0), diff --git a/example_soc/fpga/pll_25_50.v b/example_soc/fpga/pll_25_50.v new file mode 100644 index 0000000..e30ff3d --- /dev/null +++ b/example_soc/fpga/pll_25_50.v @@ -0,0 +1,46 @@ +// diamond 3.7 accepts this PLL +// diamond 3.8-3.9 is untested +// diamond 3.10 or higher is likely to abort with error about unable to use feedback signal +// cause of this could be from wrong CPHASE/FPHASE parameters +module pll_25_50 +( + input clkin, // 25 MHz, 0 deg + output clkout0, // 50 MHz, 0 deg + output locked +); +(* FREQUENCY_PIN_CLKI="25" *) +(* FREQUENCY_PIN_CLKOP="50" *) +(* ICP_CURRENT="12" *) (* LPF_RESISTOR="8" *) (* MFG_ENABLE_FILTEROPAMP="1" *) (* MFG_GMCREF_SEL="2" *) +EHXPLLL #( + .PLLRST_ENA("DISABLED"), + .INTFB_WAKE("DISABLED"), + .STDBY_ENABLE("DISABLED"), + .DPHASE_SOURCE("DISABLED"), + .OUTDIVIDER_MUXA("DIVA"), + .OUTDIVIDER_MUXB("DIVB"), + .OUTDIVIDER_MUXC("DIVC"), + .OUTDIVIDER_MUXD("DIVD"), + .CLKI_DIV(1), + .CLKOP_ENABLE("ENABLED"), + .CLKOP_DIV(12), + .CLKOP_CPHASE(5), + .CLKOP_FPHASE(0), + .FEEDBK_PATH("CLKOP"), + .CLKFB_DIV(2) + ) pll_i ( + .RST(1'b0), + .STDBY(1'b0), + .CLKI(clkin), + .CLKOP(clkout0), + .CLKFB(clkout0), + .CLKINTFB(), + .PHASESEL0(1'b0), + .PHASESEL1(1'b0), + .PHASEDIR(1'b1), + .PHASESTEP(1'b1), + .PHASELOADREG(1'b1), + .PLLWAKESYNC(1'b0), + .ENCLKOP(1'b0), + .LOCK(locked) + ); +endmodule diff --git a/example_soc/icebreaker-openocd.cfg b/example_soc/icebreaker-openocd.cfg index 9b46db0..3620010 100644 --- a/example_soc/icebreaker-openocd.cfg +++ b/example_soc/icebreaker-openocd.cfg @@ -1,8 +1,8 @@ adapter driver ftdi # 30 MHz -- a bit exciting but it seems reliable -adapter speed 30000 -ftdi_tdo_sample_edge falling +adapter speed 3000 +# ftdi_tdo_sample_edge falling # JTAG is on FTDI B channel so it doesn't inadvertently assert flash CS pin # (usually UART would be on the B channel). diff --git a/example_soc/soc/example_soc.v b/example_soc/soc/example_soc.v index acf8454..8fb02fc 100644 --- a/example_soc/soc/example_soc.v +++ b/example_soc/soc/example_soc.v @@ -21,7 +21,10 @@ `default_nettype none module example_soc #( - parameter DTM_TYPE = "JTAG" // can be "JTAG" or "ECP5" + parameter DTM_TYPE = "JTAG", // can be "JTAG" or "ECP5" + parameter SRAM_DEPTH = 1 << 15, // default 32 kwords -> 128 kB + + `include "hazard3_config.vh" ) ( // System clock + reset input wire clk, @@ -225,29 +228,27 @@ wire [W_DATA-1:0] proc_hrdata; wire uart_irq; -// Processor instantiation. Parameters can be set here or by modifying -// hazard3_config.vh. Turn on all the ISA support but ignore performance -// options like faster multiply/divide. - hazard3_cpu_1port #( + // These must have the values given here for you to end up with a useful SoC: .RESET_VECTOR (32'h0000_00c0), .MTVEC_INIT (32'h0000_0000), - - .EXTENSION_C (0), - .EXTENSION_M (1), .CSR_M_MANDATORY (1), .CSR_M_TRAP (1), - .CSR_COUNTER (1), .DEBUG_SUPPORT (1), - - .MUL_FAST (1), - .NUM_IRQ (1), - - .MVENDORID_VAL (32'h0), - .MARCHID_VAL (32'h0), - .MIMPID_VAL (32'h0), - .MHARTID_VAL (32'h0) + // Can be overridden from the defaults in hazard3_config.vh during + // instantiation of example_soc(): + .EXTENSION_C (EXTENSION_C), + .EXTENSION_M (EXTENSION_M), + .CSR_COUNTER (CSR_COUNTER), + .MVENDORID_VAL (MVENDORID_VAL), + .MARCHID_VAL (MARCHID_VAL), + .MIMPID_VAL (MIMPID_VAL), + .MHARTID_VAL (MHARTID_VAL), + .REDUCED_BYPASS (REDUCED_BYPASS), + .MULDIV_UNROLL (MULDIV_UNROLL), + .MUL_FAST (MUL_FAST), + .MTVEC_WMASK (MTVEC_WMASK) ) cpu ( .clk (clk), .rst_n (rst_n_cpu), @@ -405,7 +406,7 @@ ahbl_to_apb apb_bridge_u ( // zero-initialised so don't leave the little guy hanging too long) ahb_sync_sram #( - .DEPTH (1 << 15) // 32k x 32 = 128 kB + .DEPTH (SRAM_DEPTH) ) sram0 ( .clk (clk), .rst_n (rst_n), diff --git a/example_soc/synth/Icebreaker.mk b/example_soc/synth/Icebreaker.mk index 37e2846..62f1b09 100644 --- a/example_soc/synth/Icebreaker.mk +++ b/example_soc/synth/Icebreaker.mk @@ -1,6 +1,8 @@ CHIPNAME=fpga_icebreaker DOTF=../fpga/fpga_icebreaker.f SYNTH_OPT=-dsp +PNR_OPT=--timing-allow-fail + DEVICE=up5k PACKAGE=sg48 diff --git a/example_soc/synth/ULX3S.mk b/example_soc/synth/ULX3S.mk index 08bd296..e8125fa 100644 --- a/example_soc/synth/ULX3S.mk +++ b/example_soc/synth/ULX3S.mk @@ -3,6 +3,7 @@ TOP=fpga_ulx3s DOTF=../fpga/fpga_ulx3s.f SYNTH_OPT=-abc9 +PNR_OPT=--timing-allow-fail DEVICE=um5g-85k PACKAGE=CABGA381 diff --git a/hdl/debug/dtm/hazard3_ecp5_jtag_dtm.v b/hdl/debug/dtm/hazard3_ecp5_jtag_dtm.v index 1349e0b..afe747f 100644 --- a/hdl/debug/dtm/hazard3_ecp5_jtag_dtm.v +++ b/hdl/debug/dtm/hazard3_ecp5_jtag_dtm.v @@ -21,8 +21,9 @@ // // Brian Swetland pointed out on Twitter that the standard RISC-V JTAG-DTM // only uses two DRs (DTMCS and DMI), besides the standard IDCODE and BYPASS -// whic. This file instantiates the guts of Hazard3's standard JTAG-DTM and -// connects the DTMCS and DMI registers to the JTAGG primitive's ER1/ER2 DRs. +// which are provided already by the ECP5 TAP. This file instantiates the +// guts of Hazard3's standard JTAG-DTM and connects the DTMCS and DMI +// registers to the JTAGG primitive's ER1/ER2 DRs. // // The exciting part is that upstream OpenOCD already allows you to set the IR // length *and* set custom DTMCS/DMI IR values for RISC-V JTAG DTMs. This @@ -59,8 +60,6 @@ wire jtdo2; wire jtdo1; wire jtdi; wire jtck_posedge_dont_use; -wire jrti2; -wire jrti1; wire jshift; wire jupdate; wire jrst_n; @@ -72,8 +71,8 @@ JTAGG jtag_u ( .JTDO1 (jtdo1), .JTDI (jtdi), .JTCK (jtck_posedge_dont_use), - .JRTI2 (jrti2), - .JRTI1 (jrti1), + .JRTI2 (/* unused */), + .JRTI1 (/* unused */), .JSHIFT (jshift), .JUPDATE (jupdate), .JRSTN (jrst_n), @@ -81,10 +80,10 @@ JTAGG jtag_u ( .JCE1 (jce1) ); -// JTAGG primitive asserts its signals synchronously to JTCK's posedge -// (I think), but you get weird and inconsistent results if you try to -// consume them synchronously on JTCK's posedge, possibly due to a lack of -// hold constraints in nextpnr. +// JTAGG primitive asserts its signals synchronously to JTCK's posedge, but +// you get weird and inconsistent results if you try to consume them +// synchronously on JTCK's posedge, possibly due to a lack of hold +// constraints in nextpnr. // // A quick hack is to move the sampling onto the negedge of the clock. This // then creates more problems because we would be running our shift logic on