summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Blake Kongslie2021-04-14 08:44:31 -0700
committerJulian Blake Kongslie2021-04-14 18:24:34 -0700
commit3975a7e26d0ad8c7f33e28e1222d1e09f7bcdb82 (patch)
tree0e98488c3daaa279bbc2733c3c45c99f76a2e19a
parentAdd UART receive opbit. (diff)
downloadnoncpu-3975a7e26d0ad8c7f33e28e1222d1e09f7bcdb82.tar.xz
Use internal PLL for clock and reset generation.
Diffstat (limited to '')
-rw-r--r--hdl/clock.sv140
-rw-r--r--hdl/top.sv20
-rw-r--r--sim/main.cpp10
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
3module 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
15enum
16 { AWAIT_LOCKED
17 , AWAIT_LOW
18 , AWAIT_HIGH
19 , AWAIT_LOW_2
20 , READY
21 } state = state.first;
22
23bit locked;
24
25`ifdef SYNTHESIS
26
27altpll
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
122always_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);
138end
139
140endmodule
diff --git a/hdl/top.sv b/hdl/top.sv
index 8d83f35..46620cb 100644
--- a/hdl/top.sv
+++ b/hdl/top.sv
@@ -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
11bit reset = 0; 11bit clk;
12bit have_reset = 0; 12bit reset;
13always_ff @(posedge clk) if (reset) have_reset <= 1; 13
14assign reset = !reset_n || !have_reset; 14clock
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
16bit mem_ready; 24bit mem_ready;
17bit mem_valid; 25bit 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 }