Added a behavioral model for the ring oscillator, and a testbench
for running the PLL (in behavioral mode), specifically for switching
to and from PLL bypass mode from the processor itself.
diff --git a/verilog/rtl/digital_pll.v b/verilog/rtl/digital_pll.v
index 9754180..d4fe6ff 100644
--- a/verilog/rtl/digital_pll.v
+++ b/verilog/rtl/digital_pll.v
@@ -31,12 +31,11 @@
wire [25:0] itrim; // Internally generated trim bits
wire [25:0] otrim; // Trim bits applied to the ring oscillator
wire [3:0] nint; // Internal divided down clocks
- wire reset; // Internal positive sense reset
wire resetbb; // Internal buffered negative sense reset
wire creset; // Controller reset
wire ireset; // Internal reset (external reset OR extclk_sel)
- assign ireset = reset | extclk_sel;
+ assign ireset = ~resetb | extclk_sel;
// In DCO mode: Hold controller in reset and apply external trim value
assign itrim = (dco == 1'b0) ? otrim : ext_trim;
diff --git a/verilog/rtl/digital_pll_controller.v b/verilog/rtl/digital_pll_controller.v
index ddc553d..d4f7a4c 100644
--- a/verilog/rtl/digital_pll_controller.v
+++ b/verilog/rtl/digital_pll_controller.v
@@ -99,9 +99,13 @@
if (prep == 3'b111) begin
if (sum > div) begin
- tval <= tval + 1;
+ if (tval < 127) begin
+ tval <= tval + 1;
+ end
end else if (sum < div) begin
- tval <= tval - 1;
+ if (tval > 0) begin
+ tval <= tval - 1;
+ end
end
end
end else begin
diff --git a/verilog/rtl/ring_osc2x13.v b/verilog/rtl/ring_osc2x13.v
index c0531bd..9bf6252 100644
--- a/verilog/rtl/ring_osc2x13.v
+++ b/verilog/rtl/ring_osc2x13.v
@@ -131,8 +131,60 @@
input [25:0] trim;
output[1:0] clockp;
- wire [12:0] d;
+`ifdef FUNCTIONAL // i.e., behavioral model below
+
+ reg [1:0] clockp;
+ reg hiclock;
+ integer i;
+ real delay;
+ wire [5:0] bcount;
+
+ assign bcount = trim[0] + trim[1] + trim[2]
+ + trim[3] + trim[4] + trim[5] + trim[6] + trim[7]
+ + trim[8] + trim[9] + trim[10] + trim[11] + trim[12]
+ + trim[13] + trim[14] + trim[15] + trim[16] + trim[17]
+ + trim[18] + trim[19] + trim[20] + trim[21] + trim[22]
+ + trim[23] + trim[24] + trim[25];
+
+ initial begin
+ hiclock <= 1'b0;
+ delay = 3.0;
+ end
+
+ // Fastest operation is 214 MHz = 4.67ns
+ // Delay per trim is 0.02385
+ // Run "hiclock" at 2x this rate, then use positive and negative
+ // edges to derive the 0 and 90 degree phase clocks.
+
+ always #delay begin
+ hiclock <= (hiclock === 1'b0);
+ end
+
+ always @(trim) begin
+ // Implement trim as a variable delay, one delay per trim bit
+ delay = 1.168 + 0.012 * $itor(bcount);
+ end
+
+ always @(posedge hiclock or posedge reset) begin
+ if (reset == 1'b1) begin
+ clockp[0] <= 1'b0;
+ end else begin
+ clockp[0] <= (clockp[0] === 1'b0);
+ end
+ end
+
+ always @(negedge hiclock or posedge reset) begin
+ if (reset == 1'b1) begin
+ clockp[1] <= 1'b0;
+ end else begin
+ clockp[1] <= (clockp[1] === 1'b0);
+ end
+ end
+
+`else // !FUNCTIONAL; i.e., gate level netlist below
+
wire [1:0] clockp;
+ wire [12:0] d;
wire [1:0] c;
// Main oscillator loop stages
@@ -176,4 +228,6 @@
.Y(clockp[1])
);
+`endif // !FUNCTIONAL
+
endmodule