Waveform Generation • Fundamental part of signal processing is the signal. • Within the context of hardware implementations of signal processing this signal may arise from: • A local waverform/signal generator. • Continuous stream from a processor bus. • Samples from a Analog-to-Digital Coverters (ADCs from the outside world). • We also need to get these signals into the outside world: • Digital-to-analog Converters (DACs) • Over the next few lectures we will investigate these topics.
Waveform Generation • Some common types of waveform signal generators: • Ramp Generator. • Arbitrary Waveform Generator (AWG) • Period Signal Generator - Pulse Train • Sinusoidal Signals- Direct Digital Synthesizer (DDS) • (Pseudo) Random Number Generator (RNG) • Communication signals & Modulation
Time Base • Common to all these types of signals and waveform generators we need some type of time base (sample base) “n”, which will consist of: • Sample duration ( Δ t = 1/ f SMP ) • Used to relate the signal to the outside world. • Sample count (n) • The sample base itself. • Count Limit (N) • Since hardware numbers are confined to a finite width.
Implementation • A sample base can be implemented with a simple counter. module counter #( n_next parameter WIDTH = W, z -1 parameter LIMIT = N) ( input wire clock, z -1 output reg [WIDTH-1:0] n = 0, = wrap N-1 output wire wrap); 1 wire [WIDTH-1:0] n_next; sum wire [WIDTH-1:0] sum; 0 1 0 assign wrap = (n == (LIMIT-1)); assign sum = n + 1; n assign n_next = wrap ? 0 : sum; always@(posedge clock) The “clock” is not explicitly n <= n_next; shown in the block diagram? Where is it? endmodule
Simulation `timescale 1ns/1ps module ex1_tb; localparam WIDTH=8; localparam N=24; reg clock; wire [WIDTH-1:0] n; wire wrap; counter #( .WIDTH(WIDTH), .LIMIT(N)) dut ( .clock(clock), .n(n), .wrap(wrap)); always begin clock <= 1'b0; Not only do we have a sample #5; base to generate other clock <= 1'b1; waveforms, we also have a signal #5; – ramp. end endmodule
Configurable Logic Block
Implementation • A slight modification. module counter #( clock parameter WIDTH = W, reset parameter LIMIT = N) ( enable input wire clock, input wire reset, n_next input wire enable, z -1 z -1 output reg [WIDTH-1:0] n = 0, = wrap N-1 output wire wrap); wire [WIDTH-1:0] n_next; 1 wire [WIDTH-1:0] sum; sum 0 assign wrap = (n == (LIMIT-1)); 1 0 assign sum = n + 1; assign n_next = wrap ? 0 : sum; n always@(posedge clock) begin The “clock” is not explicitly shown if (reset) n <= 0; • in the block diagram? else if (enable) n <= n_next; Where is it? end • Similar for reset & enable. • These already exist in the hardware. endmodule • Just need to hook them up. •
Simulation ... wire [2:0] n0; wire [4:0] n1; wire wrap0; wire wrap1; counter #( .WIDTH(3), .LIMIT(6)) dut0 ( .clock(clock), .reset(1’b0), .enable(1’b1), .n(n0), .wrap(wrap0)); counter #( .WIDTH(5), .LIMIT(24)) dut1 ( .clock(clock), time expansion for n1; .reset(1’b0), What about time compression; .enable(wrap0); .n(n1), .wrap(wrap1)); ...
Implementation • A slight modification. module counter #( parameter WIDTH = W, parameter LIMIT = N, clock parameter STEP = D) ( reset input wire clock, enable input wire reset, input wire enable, n_next z -1 z -1 output reg [WIDTH-1:0] n = 0, output wire wrap); >= wrap LIMIT-STEP wire [WIDTH-1:0] n_next; wire [WIDTH-1:0] sum; STEP wire [WIDTH-1:0] diff; sum 0 assign wrap = (n >= (LIMIT-STEP)); diff 1 assign sum = n + STEP; assign diff = n-(LIMIT-STEP); - assign n_next = wrap ? diff : sum; subtraction n always@(posedge clock) begin if (reset) n <= 0; else if (enable) n <= n_next; end endmodule
Simulation ... wire [7:0] n0; wire wrap0; counter #( .WIDTH(8), .LIMIT(32), .STEP(4)) dut0 ( .clock(clock), .reset(1’b0), .enable(1’b1), .n(n0), .wrap(wrap0)); ... Count by 4’s. What about fractional?
Simulation ... wire [2:0] n0; wire [4:0] n1; wire wrap0; wire wrap1; counter #( .WIDTH(3), .LIMIT(5), .STEP(3)) wrap0 is high 3/5 th of the time. dut0 ( .clock(clock), .reset(1’b0), .enable(1’b1), .n(n0), .wrap(wrap0)); counter #( .WIDTH(5), .LIMIT(24), .STEP(1)) dut1 ( .clock(clock), .reset(1’b0), .enable(wrap0); .n(n1), .wrap(wrap1)); ...
Pulse Train Counter n < WIDTH wrap LIMIT(200) STEP(1) DUTY CYCLE = WIDTH/LIMIT clock *not* reset Clock, reset, enable are enable assumed to be connected to a clock, reset=0, enable=1.
The Arbitrary Waveform Generator address Counter Memory n Addr Data wrap LIMIT(DEPTH) DEPTH() STEP(1) WIDTH() ROM_FILENAME() clock clock reset reset enable enable
Verilog Memory • Verilog memory can be inferred from the register array definition. module waveform_rom #( parameter DATA_WIDTH = XX, parameter ROM_DEPTH = XX, parameter ADDR_WIDTH = XX, parameter ROM_FILENAME = “wave.mem”) ( input wire clock, If the rom register variable input wire reset, is used incorrectly, the input wire enable, build tools may not be able input wire [ADDR_WIDTH-1:0] addr, to make use of the BLOCK RAM output reg [DATA_WIDTH-1:0] do = 0); available within the PL. reg [DATA_WIDTH-1:0] rom [ROM_DEPTH-1:0]; initial $readmemh(ROM_FILENAME,rom); always@(posedge clock) begin if (reset) do <= 0; else if (enable) do <= rom[addr]; end endmodule
Simulation ... counter #( .WIDTH(12), .LIMIT(4096), .STEP(1)) dut0 ( .clock(clock), .reset(1'b0), .enable(1'b1), .n(addr), .wrap(wrap0)); waveform_rom #( .DATA_WIDTH(12), .ROM_DEPTH(4096), .ADDR_WIDTH(12)) wfm0 ( .clock(clock), .reset(1'b0), .enable(1'b1), .addr(addr), .do(do)); always begin clock <= 1'b0; #5; clock <= 1'b1; #5; end ...
The Arbitrary Waveform Generator address Counter Memory n Addr Data wrap LIMIT(DEPTH) DEPTH() STEP(1) WIDTH() ROM_FILENAME() clock clock Trigger reset reset enable enable Stop after one pulse, Trigger to initiate.
The Arbitrary Waveform Generator rate address Counter Counter Memory n n Addr Data wrap wrap LIMIT(L) LIMIT(DEPTH) DEPTH() STEP(1) STEP(S) WIDTH() ROM_FILENAME() clock clock clock reset reset reset enable enable enable Trigger Stop after one pulse, Trigger to initiate. • Time Scale of S/L. • For a specific ratio it typically is best • to find the lowest denominator. For example S/L of 2/3 is better than 4/6. •
The Arbitrary Waveform Generator Counter Counter Memory n n Addr Data wrap wrap LIMIT(L) LIMIT(DEPTH) DEPTH() STEP(1) STEP(S) WIDTH() ROM_FILENAME() clock clock clock reset reset reset enable enable enable Trigger
Back a few slides ... counter #( .WIDTH(12), .LIMIT(4096), .STEP(1)) dut0 ( .clock(clock), .reset(1'b0), .enable(1'b1), .n(addr), .wrap(wrap0)); waveform_rom #( What if the waveform is one cycle of a .DATA_WIDTH(12), • sinusoid? .ROM_DEPTH(4096), .ADDR_WIDTH(12)) wfm0 ( .clock(clock), .reset(1'b0), .enable(1'b1), .addr(addr), .do(do)); always begin clock <= 1'b0; #5; clock <= 1'b1; #5; end ...
Back a few slides ... counter #( .WIDTH(12), .LIMIT(4096), .STEP(1)) dut0 ( .clock(clock), .reset(1'b0), .enable(1'b1), .n(addr), .wrap(wrap0)); waveform_rom #( What if the waveform is one cycle of a .DATA_WIDTH(12), • sinusoid? .ROM_DEPTH(4096), .ADDR_WIDTH(12)) wfm0 ( .clock(clock), .reset(1'b0), .enable(1'b1), .addr(addr), .do(do)); always begin clock <= 1'b0; #5; clock <= 1'b1; #5; end Direct Digital Synthesizer (DDS) ...
DDS Clock frequency is 100MHz • ROM Depth is 64 and contains 1 cycle. • What is the signal frequency. • Period = • Frequency = 1/Period = •
DDS rate address Counter Counter Memory n n Addr Data wrap wrap “single cycle” LIMIT(L) LIMIT(D) DEPTH(D) STEP(1) STEP(S) WIDTH() ROM_FILENAME() clock clock clock reset reset reset enable enable enable Variables F: Clock frequency • D: number of points in the sine single cycle rom file. • S: step size of address counter • L: limit of the rate counter • Frequency F out =
DDS rate address Counter Counter Memory L D limit n limit n Addr Data 1 S step wrap step wrap “single cycle” DEPTH(D) WIDTH() WIDTH() WIDTH() ROM_FILENAME() clock clock clock reset reset reset enable enable enable Variables F: Clock frequency • D: number of points in the sine single cycle rom file. • S: step size of address counter • L: limit of the rate counter • Frequency F out = (F/D)*(S/L)
DDS Counter D limit n K step wrap WIDTH() clock reset enable rate address Counter Counter Memory D L limit n limit n Addr Data 1 step wrap step wrap “single cycle” DEPTH(D) WIDTH() WIDTH() WIDTH() ROM_FILENAME() clock clock clock reset reset reset enable enable enable What does this do?
Recommend
More recommend