/* * rpdac.v * Copyright (C) 2015 Krzysztof Mazur * * Random Pattern 1-bit Digital-to-Analog Converter * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ /* * rpdac - Random Pattern 1-bit Digital-to-Analog Converter * * The rpdac implements 2-bit DAC on 1-bit DAC using 4 cycle random * patters. The output pattern does not depend on data and it's believed * that this DAC is artifact-free, acts as ideally dithered and * also has no DC offset. However it's not verified. */ module rpdac(clk, reset, sync_in, rnd_in, in, sync_out, out); input clk; /* System Clock */ input reset; /* DAC reset */ input sync_in; /* DAC output clock */ input [2:0] rnd_in; /* random input, uniform distributed */ input [1:0] in; /* 2-bit analog input */ output sync_out; /* DAC input clock */ output out; /* 1-bit analog output */ /* * We use four phases to implement perfect 2-bit DAC. The fill rate * is 0/4, 1/4, 2/4 or 3/4. */ reg [1:0] phase = 0; always @(posedge clk) begin if (reset) phase <= 0; else if (sync_in) phase <= phase + 1; else phase <= phase; end assign sync_out = sync_in && (phase == 3); reg [3:0] pattern = 0; always @(posedge clk) begin if (reset) begin pattern <= 0; end else if (sync_out) begin case (in) 0: pattern <= 4'h0; 1: pattern <= 1 << rnd_in[1:0]; 2: begin /* * There are only 6 possible patterns that should * have equal probability. However, we want to use * uniform random bits. Because the minimum * required number of bits is three we just * use three bits. However, to additional * possibilities exist. We map them as two * high frequency patterns. This has not effect * on DC performance, the output is still random, * but we increase power of higher frequencies, * which even improves performance. */ case (rnd_in) 0: pattern <= 4'h3; 1: pattern <= 4'h6; 2: pattern <= 4'hc; 3: pattern <= 4'h9; 4: pattern <= 4'h5; 5: pattern <= 4'h5; 6: pattern <= 4'ha; 7: pattern <= 4'ha; endcase end 3: pattern <= 4'hf ^ (1 << rnd_in[1:0]); endcase end else if (sync_in) begin pattern <= { pattern[2:0], 1'b0 }; end else begin pattern <= pattern; end end assign out = pattern[3]; endmodule