Added lvds and sampler

This commit is contained in:
Joppe Blondel
2025-10-08 18:01:03 +02:00
parent 324bb108e3
commit 3b04f3a6be
6 changed files with 188 additions and 0 deletions

View File

@@ -29,6 +29,8 @@ xst_opts = -vlgincdir rtl
#files_vhdl =
files_verilog = rtl/toplevel/top_generic.v
rtl/core/nco_q15.v
rtl/core/sigmadelta_sampler.v
rtl/arch/spartan-6/lvds_comparator.v
files_con = boards/mimas_v1/constraints.ucf
files_other = rtl/util/conv.vh
@@ -42,4 +44,6 @@ ivl_opts = -Irtl
#files_sysverilog =
files_verilog = sim/tb/tb_nco_q15.v
rtl/core/nco_q15.v
rtl/core/lvds_comparator.v
sim/overrides/sigmadelta_sampler.v
files_other = rtl/util/conv.vh

View File

@@ -0,0 +1,17 @@
`timescale 1ns/1ps
// =============================================================================
// LVDS comparator
// Instantiating a GW1 TLVDS_IBUF
// =============================================================================
module lvds_comparator(
input wire a,
input wire b,
output wire o
);
TLVDS_IBUF lvds_buf (
.O(o),
.I(a),
.IB(b)
);
endmodule

View File

@@ -0,0 +1,20 @@
`timescale 1ns/1ps
// =============================================================================
// LVDS comparator
// Instantiating a spartan-6 IBUFDS
// =============================================================================
module lvds_comparator(
input wire a,
input wire b,
output wire o
);
IBUFDS #(
.DIFF_TERM("FALSE"),
.IOSTANDARD("LVDS33")
) lvds_buf (
.O(o),
.I(a),
.IB(b)
);
endmodule

View File

@@ -0,0 +1,13 @@
`timescale 1ns/1ps
// =============================================================================
// LVDS comparator
// Simple pass-though model
// =============================================================================
module lvds_comparator(
input wire a,
input wire b,
output wire o
);
assign o = a;
endmodule

View File

@@ -0,0 +1,23 @@
`timescale 1ns/1ps
// =============================================================================
// Sigma-Delta sampler
// Samples A>B at clk
// =============================================================================
module sigmadelta_sampler(
input wire clk,
input wire a,
input wire b,
output wire o
);
wire comp_out;
lvds_comparator comp (
.a(a), .b(b), .o(comp_out)
);
reg registered_comp_out;
always @(posedge clk) registered_comp_out <= o;
assign o = registered_comp_out;
endmodule

View File

@@ -0,0 +1,111 @@
`timescale 1ns/1ps
// =============================================================================
// Sigma-Delta sampler
// Simulates an RC circuit between O and B and a sine at A
// =============================================================================
module sigmadelta_sampler(
input wire clk,
input wire a,
input wire b,
output wire o
);
// Sine source (A input / P)
parameter real F_HZ = 1.5e3; // input sine frequency (1 kHz)
parameter real AMP = 1.5; // sine amplitude (V)
parameter real VCM = 1.65; // common-mode (V), centered in 0..3.3V
// Comparator behavior
parameter real VTH = 0.0; // threshold on (vp - vn)
parameter real VHYST = 0.05; // symmetric hysteresis half-width (V)
parameter integer ADD_HYST = 0; // 1 to enable hysteresis
// 1-bit DAC rails (feedback into RC)
parameter real VLOW = 0.0; // DAC 0 (V)
parameter real VHIGH = 3.3; // DAC 1 (V)
// RC filter (B input / N)
parameter real R_OHMS = 3300.0; // 3.3k
parameter real C_FARADS = 220e-12; // 220 pF
// Integration step (ties to `timescale`)
parameter integer TSTEP_NS = 10; // sim step in ns (choose << tau)
// ===== Internal state (simulation only) =====
real vp, vn; // comparator A/B inputs
real v_rc; // RC node voltage (== vn)
real v_dac; // DAC output voltage from O
real t_s; // time in seconds
real dt_s; // step in seconds
real tau_s; // R*C time constant in seconds
real two_pi;
reg q; // comparator latched output (pre-delay)
reg out;
reg sampler;
initial sampler <= 1'b0;
always @(posedge clk) begin
sampler <= out;
end
assign o = sampler;
// Helper task: update comparator with optional hysteresis
task automatic comp_update;
real diff;
begin
diff = (vp - vn);
if (ADD_HYST != 0) begin
// simple symmetric hysteresis around VTH
if (q && (diff < (VTH - VHYST))) q = 1'b0;
else if (!q && (diff > (VTH + VHYST))) q = 1'b1;
// else hold
end else begin
q = (diff > VTH) ? 1'b1 : 1'b0;
end
end
endtask
initial begin
// Init constants
two_pi = 6.283185307179586;
tau_s = R_OHMS * C_FARADS; // ~7.26e-7 s
dt_s = TSTEP_NS * 1.0e-9;
// Init states
t_s = 0.0;
q = 1'b0; // start low
out = 1'b0;
v_dac= VLOW;
v_rc = (VHIGH + VLOW)/2.0; // start mid-rail to reduce start-up transient
vn = v_rc;
vp = VCM;
// Main sim loop
forever begin
#(TSTEP_NS); // advance discrete time step
t_s = t_s + dt_s;
// 1) Update DAC from previous comparator state
v_dac = sampler ? VHIGH : VLOW;
// 2) RC low-pass driven by DAC: Euler step
// dv = (v_dac - v_rc) * dt/tau
v_rc = v_rc + (v_dac - v_rc) * (dt_s / tau_s);
vn = v_rc;
// 3) Input sine on A
vp = VCM + AMP * $sin(two_pi * F_HZ * t_s);
// 4) Comparator decision (with optional hysteresis)
comp_update();
// 5) Output with propagation delay
out = q;
end
end
endmodule