Last active
November 15, 2023 14:56
-
-
Save prydin/0ba58168533d66b1c786625ec91f0e54 to your computer and use it in GitHub Desktop.
DDS attempt
This file contains 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
module dds | |
#(parameter ACC_LENGTH = 48, | |
parameter PHASE_LENGTH = 14 | |
) ( | |
input sys_clk, | |
input spi_clk, | |
input spi_data, | |
input freq_cs, | |
input phaseshift_cs, | |
input [1:0] mode_in, | |
output [PHASE_LENGTH-1:0] waveform_out | |
); | |
reg [0:0] freq_latch; | |
reg [0:0] phaseshift_latch; | |
wire [ACC_LENGTH-1:0] freq_in; | |
wire [PHASE_LENGTH-1:0] phaseshift_in; | |
wire [PHASE_LENGTH-1:0] reduced_phase; | |
wire [PHASE_LENGTH-1:0] reduced_phase_tri; | |
// Input loading logic. | |
// When the CS goes inactive for an SPI input, the value | |
// held by an SPI shift register is ready to be loaded | |
// into the phase accumulator. To avoid messes, we | |
// wait until the system clock goes low, since | |
// the system does it's calculations on the positive edge. | |
always @(negedge freq_cs) begin | |
freq_latch <= 1; | |
end | |
always @(negedge phaseshift_cs) begin | |
phaseshift_latch <= 1; | |
end | |
always @(posedge sys_clk) begin | |
if(freq_latch) begin | |
freq_latch <= 0; | |
end | |
if(phaseshift_latch) begin | |
phaseshift_latch <= 0; | |
end | |
end | |
// Shift registers to handle SPI communication | |
// Frequency register | |
shiftreg #( | |
.LENGTH(ACC_LENGTH) | |
) freq_spi ( | |
.clk(spi_clk), | |
.cs(freq_cs), | |
.d(spi_data), | |
.out(freq_in[ACC_LENGTH-1:0]), | |
.latch(freq_latch) | |
); | |
// Phase shift register | |
shiftreg #( | |
.LENGTH(PHASE_LENGTH) | |
) phaseshift_spi ( | |
.clk(spi_clk), | |
.cs(phase_cs), | |
.d(spi_data), | |
.out(phaseshift_in[PHASE_LENGTH-1:0]), | |
.latch(phaseshift_latch)); | |
// Phase accumulator | |
phase_acc #( | |
.ACC_LENGTH(ACC_LENGTH), | |
.OUT_LENGTH(PHASE_LENGTH) | |
) phase_acc ( | |
.clk(sys_clk), | |
.increment(freq_in), | |
.phaseshift(phaseshift_in), | |
.out(reduced_phase), | |
.tri_out(reduced_phase_tri) | |
); | |
// Waveform shaper | |
waveform_shaper #( | |
.LENGTH(PHASE_LENGTH) | |
) waveform_shaper ( | |
.clk(sys_clk), | |
.phase(reduced_phase[PHASE_LENGTH-1:0]), | |
.triangle(reduced_phase_tri[PHASE_LENGTH-1:0]), | |
.mode(mode_in[1:0]), | |
.out(waveform_out[PHASE_LENGTH-1:0]) | |
); | |
endmodule | |
module waveform_shaper #( | |
parameter LENGTH=14 | |
) ( | |
input clk, | |
input [LENGTH-1:0] phase, | |
input [LENGTH-1:0] triangle, | |
input [1:0] mode, | |
output reg [LENGTH-1:0] out | |
); | |
always @(posedge clk) begin | |
case(mode) | |
2'b00: out <= phase; // Ramp | |
2'b01: out <= triangle; // Triangle | |
2'b10: out <= 0; // TODO: Sine lookup table | |
endcase | |
end | |
endmodule | |
module phase_acc #( | |
parameter ACC_LENGTH = 48, | |
parameter OUT_LENGTH = 14 | |
) ( | |
input clk, | |
input [ACC_LENGTH-1:0] increment, | |
input [OUT_LENGTH-1:0] phaseshift, | |
output reg [OUT_LENGTH-1:0] out, | |
output reg [OUT_LENGTH-1:0] tri_out | |
); | |
reg [ACC_LENGTH-1:0] acc; | |
reg [ACC_LENGTH-1:0] tri_acc; | |
reg [0:0] tri_slope; | |
// Calculate the new value on positive clock | |
always @(posedge clk) begin | |
acc <= acc + increment; | |
tri_acc <= tri_slope ? tri_acc - increment * 2 : tri_acc + increment * 2; | |
// Flip triangle wave slope when we're half way through | |
// the phase, i.e. when the MSB flips. | |
if(tri_slope == 0 && acc[ACC_LENGTH-1] == 0) tri_slope <= 1; // Flip from up to down | |
if(tri_slope == 1 && acc[ACC_LENGTH-1] == 1) tri_slope <= 0; // Flip from down to up | |
end | |
// Update the output on negative clock | |
always @(negedge clk) begin | |
// Reduce to 14 bits and add phase shift | |
out[OUT_LENGTH-1:0] <= acc[ACC_LENGTH - OUT_LENGTH - 1:0] + phaseshift; | |
tri_out[OUT_LENGTH-1:0] <= tri_acc[ACC_LENGTH - OUT_LENGTH - 1:0] + phaseshift; | |
end | |
endmodule | |
module shiftreg #( | |
parameter LENGTH = 48 | |
) ( | |
input clk, | |
input cs, | |
input d, | |
input latch, | |
output reg [LENGTH-1:0] out | |
); | |
reg [LENGTH-1:0] pipeline; | |
integer i; | |
always @(posedge clk) begin | |
if (cs) begin | |
for(i = 1; i < LENGTH; i = i + 1) begin | |
pipeline[i] <= pipeline[i - 1]; | |
end | |
pipeline[0] <= d; | |
end | |
end | |
// Latch current state to "out" port. | |
always @(posedge latch) begin | |
out = pipeline; | |
end | |
endmodule | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment