Created
January 30, 2020 13:30
-
-
Save sgherbst/9c8d3ed7b09074e6e145c0db58d2e3d0 to your computer and use it in GitHub Desktop.
SystemVerilog PLL Simulation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // run simulation with xrun pll.sv +access+rw | |
| // view results with simvision | |
| `timescale 1s / 1fs | |
| module ringosc ( | |
| input real vdd, | |
| output logic out | |
| ); | |
| // YOUR CODE HERE | |
| endmodule | |
| module ctrl ( | |
| input real in, | |
| input clk, | |
| input rst, | |
| output real out | |
| ); | |
| // YOUR CODE HERE | |
| endmodule | |
| module freqdiv #( | |
| parameter integer N=20 | |
| ) ( | |
| input in, | |
| output var out=1'b0 | |
| ); | |
| integer count=0; | |
| always @(posedge in) begin | |
| if (count==(N/2)-1) begin | |
| out <= ~out; | |
| count <= 0; | |
| end else begin | |
| out <= out; | |
| count <= count+1; | |
| end | |
| end | |
| endmodule | |
| module phasecmp #( | |
| parameter real tau=1e-9 | |
| ) ( | |
| input clk1, | |
| input clk2, | |
| output real out | |
| ); | |
| // generate up/down signals for a phase/frequency comparator | |
| logic up, dn; | |
| assign #(1e-12*1s) clr = up & dn; | |
| always @(posedge clk2 or posedge clr) begin | |
| if (clr == 1'b1) begin | |
| up <= 1'b0; | |
| end else begin | |
| up <= 1'b1; | |
| end | |
| end | |
| always @(posedge clk1 or posedge clr) begin | |
| if (clr == 1'b1) begin | |
| dn <= 1'b0; | |
| end else begin | |
| dn <= 1'b1; | |
| end | |
| end | |
| // apply filter to up-dn signal | |
| real dt; | |
| real filt_state=0.0; | |
| real last_inpt=0.0; | |
| real last_time=0.0; | |
| always @(up or dn) begin | |
| dt = $realtime - last_time; | |
| filt_state = filt_state*$exp(-dt/tau) + last_inpt*(1.0-$exp(-dt/tau)); | |
| last_inpt = (up===1'b1 ? 1.0 : 0.0) - (dn===1'b1 ? 1.0 : 0.0); | |
| last_time = $realtime; | |
| end | |
| assign out = filt_state; | |
| endmodule | |
| module pll ( | |
| input clkin, | |
| output clkout, | |
| input rst | |
| ); | |
| real vdd; | |
| ringosc ringosc_i ( | |
| .vdd(vdd), | |
| .out(clkout) | |
| ); | |
| logic divo; | |
| freqdiv freqdiv_i ( | |
| .in(clkout), | |
| .out(divo) | |
| ); | |
| real phmeas; | |
| phasecmp phasecmp_i ( | |
| .clk1(divo), | |
| .clk2(clkin), | |
| .out(phmeas) | |
| ); | |
| ctrl ctrl_i ( | |
| .in(phmeas), | |
| .clk(clkin), | |
| .rst(rst), | |
| .out(vdd) | |
| ); | |
| endmodule | |
| module tb; | |
| localparam real ref_freq=1e9; | |
| logic clkin, rst, clkout; | |
| always begin | |
| clkin = 1'b0; | |
| #(0.5/ref_freq*1s); | |
| clkin = 1'b1; | |
| #(0.5/ref_freq*1s); | |
| end | |
| pll pll_i ( | |
| .clkin(clkin), | |
| .clkout(clkout), | |
| .rst(rst) | |
| ); | |
| real tdiff, last_time; | |
| task meas_freq; | |
| @(posedge clkout); | |
| last_time = $realtime; | |
| @(posedge clkout); | |
| tdiff = $realtime - last_time; | |
| $display("Frequency of clkout at t=%0.1e: %0.3f GHz", $realtime, 1e-9/tdiff); | |
| endtask | |
| always begin | |
| #(1e-6); | |
| meas_freq(); | |
| end | |
| initial begin | |
| // setup | |
| $shm_open("waves.shm"); | |
| $shm_probe("AS"); | |
| // initialize reset | |
| rst = 1'b1; | |
| #(3e-9*1s); | |
| rst = 1'b0; | |
| // run simulation | |
| #(10e-6*1s); | |
| $finish; | |
| end | |
| endmodule |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment