Skip to content

Instantly share code, notes, and snippets.

@prydin
Last active November 15, 2023 14:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save prydin/0ba58168533d66b1c786625ec91f0e54 to your computer and use it in GitHub Desktop.
Save prydin/0ba58168533d66b1c786625ec91f0e54 to your computer and use it in GitHub Desktop.
DDS attempt
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