diff options
| -rw-r--r-- | hdl/clock.sv | 140 | ||||
| -rw-r--r-- | hdl/top.sv | 20 | ||||
| -rw-r--r-- | sim/main.cpp | 10 |
3 files changed, 159 insertions, 11 deletions
diff --git a/hdl/clock.sv b/hdl/clock.sv new file mode 100644 index 0000000..b33645b --- /dev/null +++ b/hdl/clock.sv | |||
| @@ -0,0 +1,140 @@ | |||
| 1 | `include "util.svh" | ||
| 2 | |||
| 3 | module clock | ||
| 4 | #( DIVIDE_BY = 1 | ||
| 5 | , MULTIPLY_BY = 1 | ||
| 6 | , NATIVE_PERIOD_PICOSECONDS = 20_000 | ||
| 7 | ) | ||
| 8 | ( input bit native_clk | ||
| 9 | , input bit reset_n | ||
| 10 | |||
| 11 | , output bit target_clk | ||
| 12 | , output bit reset | ||
| 13 | ); | ||
| 14 | |||
| 15 | enum | ||
| 16 | { AWAIT_LOCKED | ||
| 17 | , AWAIT_LOW | ||
| 18 | , AWAIT_HIGH | ||
| 19 | , AWAIT_LOW_2 | ||
| 20 | , READY | ||
| 21 | } state = state.first; | ||
| 22 | |||
| 23 | bit locked; | ||
| 24 | |||
| 25 | `ifdef SYNTHESIS | ||
| 26 | |||
| 27 | altpll | ||
| 28 | #( .bandwidth_type("AUTO") | ||
| 29 | , .clk0_divide_by(DIVIDE_BY) | ||
| 30 | , .clk0_duty_cycle(50) | ||
| 31 | , .clk0_multiply_by(MULTIPLY_BY) | ||
| 32 | , .clk0_phase_shift(0) | ||
| 33 | , .compensate_clock("CLK0") | ||
| 34 | , .inclk0_input_frequency(NATIVE_PERIOD_PICOSECONDS) | ||
| 35 | , .intended_device_family("Cyclone 10 LP") | ||
| 36 | , .lpm_hint("CBX_MODULE_PREFIX=clock") | ||
| 37 | , .lpm_type("altpll") | ||
| 38 | , .operation_mode("NORMAL") | ||
| 39 | , .pll_type("AUTO") | ||
| 40 | , .port_activeclock("PORT_UNUSED") | ||
| 41 | , .port_areset("PORT_USED") | ||
| 42 | , .port_clkbad0("PORT_UNUSED") | ||
| 43 | , .port_clkbad1("PORT_UNUSED") | ||
| 44 | , .port_clkloss("PORT_UNUSED") | ||
| 45 | , .port_clkswitch("PORT_UNUSED") | ||
| 46 | , .port_configupdate("PORT_UNUSED") | ||
| 47 | , .port_fbin("PORT_UNUSED") | ||
| 48 | , .port_inclk0("PORT_USED") | ||
| 49 | , .port_inclk1("PORT_UNUSED") | ||
| 50 | , .port_locked("PORT_USED") | ||
| 51 | , .port_pfdena("PORT_UNUSED") | ||
| 52 | , .port_phasecounterselect("PORT_UNUSED") | ||
| 53 | , .port_phasedone("PORT_UNUSED") | ||
| 54 | , .port_phasestep("PORT_UNUSED") | ||
| 55 | , .port_phaseupdown("PORT_UNUSED") | ||
| 56 | , .port_pllena("PORT_UNUSED") | ||
| 57 | , .port_scanaclr("PORT_UNUSED") | ||
| 58 | , .port_scanclk("PORT_UNUSED") | ||
| 59 | , .port_scanclkena("PORT_UNUSED") | ||
| 60 | , .port_scandata("PORT_UNUSED") | ||
| 61 | , .port_scandataout("PORT_UNUSED") | ||
| 62 | , .port_scandone("PORT_UNUSED") | ||
| 63 | , .port_scanread("PORT_UNUSED") | ||
| 64 | , .port_scanwrite("PORT_UNUSED") | ||
| 65 | , .port_clk0("PORT_USED") | ||
| 66 | , .port_clk1("PORT_UNUSED") | ||
| 67 | , .port_clk2("PORT_UNUSED") | ||
| 68 | , .port_clk3("PORT_UNUSED") | ||
| 69 | , .port_clk4("PORT_UNUSED") | ||
| 70 | , .port_clk5("PORT_UNUSED") | ||
| 71 | , .port_clkena0("PORT_UNUSED") | ||
| 72 | , .port_clkena1("PORT_UNUSED") | ||
| 73 | , .port_clkena2("PORT_UNUSED") | ||
| 74 | , .port_clkena3("PORT_UNUSED") | ||
| 75 | , .port_clkena4("PORT_UNUSED") | ||
| 76 | , .port_clkena5("PORT_UNUSED") | ||
| 77 | , .port_extclk0("PORT_UNUSED") | ||
| 78 | , .port_extclk1("PORT_UNUSED") | ||
| 79 | , .port_extclk2("PORT_UNUSED") | ||
| 80 | , .port_extclk3("PORT_UNUSED") | ||
| 81 | , .self_reset_on_loss_lock("ON") | ||
| 82 | , .width_clock(5) | ||
| 83 | ) pll | ||
| 84 | ( .areset(!reset_n) | ||
| 85 | , .inclk(native_clk) | ||
| 86 | , .clk(target_clk) | ||
| 87 | , .locked(locked) | ||
| 88 | , .activeclock() | ||
| 89 | , .clkbad() | ||
| 90 | , .clkena({6{1'b1}}) | ||
| 91 | , .clkloss() | ||
| 92 | , .clkswitch(1'b0) | ||
| 93 | , .configupdate(1'b0) | ||
| 94 | , .extclkena({4{1'b1}}) | ||
| 95 | , .fbin(1'b1) | ||
| 96 | , .fbmimicbidir() | ||
| 97 | , .fbout() | ||
| 98 | , .fref() | ||
| 99 | , .icdrclk() | ||
| 100 | , .pfdena(1'b1) | ||
| 101 | , .phasecounterselect({4{1'b1}}) | ||
| 102 | , .phasedone() | ||
| 103 | , .phasestep(1'b1) | ||
| 104 | , .phaseupdown(1'b1) | ||
| 105 | , .pllena(1'b1) | ||
| 106 | , .scanaclr(1'b0) | ||
| 107 | , .scanclk(1'b0) | ||
| 108 | , .scanclkena(1'b1) | ||
| 109 | , .scandata(1'b0) | ||
| 110 | , .scandataout() | ||
| 111 | , .scandone() | ||
| 112 | , .scanread(1'b0) | ||
| 113 | , .scanwrite(1'b0) | ||
| 114 | , .sclkout0() | ||
| 115 | , .sclkout1() | ||
| 116 | , .vcooverrange() | ||
| 117 | , .vcounderrange() | ||
| 118 | ); | ||
| 119 | |||
| 120 | `endif | ||
| 121 | |||
| 122 | always_latch begin | ||
| 123 | `ifndef SYNTHESIS | ||
| 124 | target_clk = native_clk; | ||
| 125 | locked = 1; | ||
| 126 | `endif | ||
| 127 | |||
| 128 | if (!reset_n || !locked) state = AWAIT_LOCKED; | ||
| 129 | |||
| 130 | case (state) | ||
| 131 | AWAIT_LOCKED: if (locked) state = AWAIT_LOW; | ||
| 132 | AWAIT_LOW: if (!target_clk) state = AWAIT_HIGH; | ||
| 133 | AWAIT_HIGH: if (target_clk) state = AWAIT_LOW_2; | ||
| 134 | AWAIT_LOW_2: if (!target_clk) state = READY; | ||
| 135 | endcase | ||
| 136 | |||
| 137 | reset = !(state == READY); | ||
| 138 | end | ||
| 139 | |||
| 140 | endmodule | ||
| @@ -4,14 +4,22 @@ module top | |||
| 4 | #( ADDR_BITS = 14 | 4 | #( ADDR_BITS = 14 |
| 5 | , DATA_BITS = 12 | 5 | , DATA_BITS = 12 |
| 6 | ) | 6 | ) |
| 7 | ( input bit clk // verilator public | 7 | ( input bit native_clk // verilator public |
| 8 | , input bit reset_n // verilator public | 8 | , input bit reset_n // verilator public |
| 9 | ); | 9 | ); |
| 10 | 10 | ||
| 11 | bit reset = 0; | 11 | bit clk; |
| 12 | bit have_reset = 0; | 12 | bit reset; |
| 13 | always_ff @(posedge clk) if (reset) have_reset <= 1; | 13 | |
| 14 | assign reset = !reset_n || !have_reset; | 14 | clock |
| 15 | #( .DIVIDE_BY(10) | ||
| 16 | , .MULTIPLY_BY(9) | ||
| 17 | ) pll | ||
| 18 | ( .native_clk(native_clk) | ||
| 19 | , .reset_n(reset_n) | ||
| 20 | , .target_clk(clk) | ||
| 21 | , .reset(reset) | ||
| 22 | ); | ||
| 15 | 23 | ||
| 16 | bit mem_ready; | 24 | bit mem_ready; |
| 17 | bit mem_valid; | 25 | bit mem_valid; |
diff --git a/sim/main.cpp b/sim/main.cpp index 9bf42bd..f082464 100644 --- a/sim/main.cpp +++ b/sim/main.cpp | |||
| @@ -23,16 +23,16 @@ int main(int argc, const char *argv[]) | |||
| 23 | 23 | ||
| 24 | std::uint64_t time = 0; | 24 | std::uint64_t time = 0; |
| 25 | 25 | ||
| 26 | top.clk = 0; | 26 | top.native_clk = 0; |
| 27 | top.reset_n = 0; | 27 | top.reset_n = 0; |
| 28 | top.eval(); | 28 | top.eval(); |
| 29 | vcd.dump(++time); | 29 | vcd.dump(++time); |
| 30 | 30 | ||
| 31 | top.clk = 1; | 31 | top.native_clk = 1; |
| 32 | top.eval(); | 32 | top.eval(); |
| 33 | vcd.dump(++time); | 33 | vcd.dump(++time); |
| 34 | 34 | ||
| 35 | top.clk = 0; | 35 | top.native_clk = 0; |
| 36 | top.reset_n = 1; | 36 | top.reset_n = 1; |
| 37 | top.eval(); | 37 | top.eval(); |
| 38 | vcd.dump(++time); | 38 | vcd.dump(++time); |
| @@ -40,10 +40,10 @@ int main(int argc, const char *argv[]) | |||
| 40 | std::cout << "*** MAIN LOOP ***\n"; | 40 | std::cout << "*** MAIN LOOP ***\n"; |
| 41 | 41 | ||
| 42 | for (unsigned int i = 0; i < 100000 && !Verilated::gotFinish(); ++i) { | 42 | for (unsigned int i = 0; i < 100000 && !Verilated::gotFinish(); ++i) { |
| 43 | top.clk = 1; | 43 | top.native_clk = 1; |
| 44 | top.eval(); | 44 | top.eval(); |
| 45 | vcd.dump(++time); | 45 | vcd.dump(++time); |
| 46 | top.clk = 0; | 46 | top.native_clk = 0; |
| 47 | top.eval(); | 47 | top.eval(); |
| 48 | vcd.dump(++time); | 48 | vcd.dump(++time); |
| 49 | } | 49 | } |
