0% found this document useful (0 votes)
18 views6 pages

Code

Uploaded by

Huy Nguyễn
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
18 views6 pages

Code

Uploaded by

Huy Nguyễn
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 6

`timescale 1ns / 1ps

module equalizer (
input logic sample_clock,
input logic reset,
input logic signed [23:0] input_sample,
input logic [2:0] bass_gain_select, // 3-bit switch for bass gain (0.25 to 2.0)
input logic [2:0] mid_gain_select, // 3-bit switch for mid gain (0.25 to 2.0)
input logic [2:0] treb_gain_select, // 3-bit switch for treble gain (0.25 to 2.0)
output logic signed [23:0] output_sample
);
// Parameters
parameter int tap = 20;

// FIR Coefficients
logic signed [23:0] bass_coeff[0:tap-1] = '{
24'd1409, 24'd1478, 24'd1541, 24'd1597, 24'd1647, 24'd1689, 24'd1724,
24'd1750, 24'd1768, 24'd1777, 24'd1777, 24'd1768, 24'd1750, 24'd1724,
24'd1689, 24'd1647, 24'd1597, 24'd1541, 24'd1478, 24'd1409
};

logic signed [23:0] mid_coeff[0:tap-1] = '{


-24'd243, -24'd242, -24'd244, -24'd66, 24'd450, 24'd1369, 24'd2608,
24'd3948, 24'd5087, 24'd5742, 24'd5742, 24'd5087, 24'd3948, 24'd2608,
24'd1369, 24'd450, -24'd66, -24'd244, -24'd242, -24'd243
};

logic signed [23:0] treb_coeff[0:tap-1] = '{


24'd5, 24'd106, 24'd235, -24'd30, -24'd1284, -24'd3464, -24'd3825,
-24'd13978, 24'd3476, 24'd7528, 24'd7528, 24'd3476, -24'd13978,
-24'd3825, -24'd3464, -24'd1284, -24'd30, 24'd235, 24'd106, 24'd5
};

// Gain values
logic signed [15:0] gain_values[0:7] = '{
16'd64, // 0.25x
16'd128, // 0.5x
16'd192, // 0.75x
16'd256, // 1.0x
16'd320, // 1.25x
16'd384, // 1.5x
16'd448, // 1.75x
16'd512 // 2.0x
};
logic signed [15:0] bass_gain, mid_gain, treb_gain;

// Scaled coefficients
logic signed [23:0] scaled_bass_coeff[0:tap-1];
logic signed [23:0] scaled_mid_coeff [0:tap-1];
logic signed [23:0] scaled_treb_coeff[0:tap-1];

// FIR filter outputs


logic signed [23:0] bass_out, mid_out, treb_out;

// Assign gain values based on switch inputs


always_comb begin
bass_gain = gain_values[bass_gain_select];
mid_gain = gain_values[mid_gain_select];
treb_gain = gain_values[treb_gain_select];
end

// Scale coefficients based on gain


generate
genvar i;
for (i = 0; i < tap; i++) begin : scale_coeffs
assign scaled_bass_coeff[i] = (bass_coeff[i] * bass_gain) >>> 8;
assign scaled_mid_coeff[i] = (mid_coeff[i] * mid_gain) >>> 8;
assign scaled_treb_coeff[i] = (treb_coeff[i] * treb_gain) >>> 8;
end
endgenerate

// Instantiate FIR filters for each band


fir_20 bass_filter (
.sample_clock(sample_clock),
.reset(reset),
.input_sample(input_sample),
.coeff(scaled_bass_coeff),
.output_sample(bass_out)
);

fir_20 mid_filter (
.sample_clock(sample_clock),
.reset(reset),
.input_sample(input_sample),
.coeff(scaled_mid_coeff),
.output_sample(mid_out)
);
fir_20 treb_filter (
.sample_clock(sample_clock),
.reset(reset),
.input_sample(input_sample),
.coeff(scaled_treb_coeff),
.output_sample(treb_out)
);

// Combine outputs from all bands


assign output_sample = bass_out + mid_out + treb_out;

// Debugging logic
always_ff @(posedge sample_clock or negedge reset) begin
if (!reset) begin
$display("Reset applied. Gains set to zero.");
end else begin
$display("Bass Gain: %d, Mid Gain: %d, Treble Gain: %d", bass_gain, mid_gain, treb_gain);
end
end
endmodule

`timescale 1ns / 1ps

module fir_20 (
input logic sample_clock,
input logic reset,
input logic signed [23:0] input_sample,
input logic signed [23:0] coeff [0:19], // FIR coefficients (dynamic input)
output logic signed [23:0] output_sample
);
parameter int tap = 20;

// Registers for FIR calculation


logic signed [23:0] Areg [0:tap-1]; // Input shift register
logic signed [47:0] Coeff_mul [0:tap-1]; // Multiplied values
logic signed [47:0] Sum; // Accumulator for the sum

// Shift register to load input samples


always_ff @(posedge sample_clock or negedge reset) begin
if (!reset) begin
for (int i = 0; i < tap; i++) begin
Areg[i] <= 0;
end
end else begin
for (int i = tap-1; i > 0; i--) begin
Areg[i] <= Areg[i-1];
end
Areg[0] <= input_sample;
end
end

// Multiply inputs with coefficients


always_comb begin
for (int i = 0; i < tap; i++) begin
Coeff_mul[i] = Areg[i] * coeff[i];
end
end

// Accumulate the results


always_comb begin
Sum = 0;
for (int i = 0; i < tap; i++) begin
Sum += Coeff_mul[i];
end
end

// Truncate and assign the output


assign output_sample = Sum[47:24];

endmodule

`timescale 1ns / 1ps

module equalizer_tb();
localparam FILE_PATH = "audio.hex";
localparam OUT_PATH = "output.hex";
localparam FREQ = 100_000_000;
localparam WD_IN = 24;
localparam WD_OUT = 24;
localparam PERIOD = 1_000_000_000 / FREQ;
localparam HALF_PERIOD = PERIOD / 2;

reg clk, reset_n;


reg signed [WD_IN-1:0] input_sample;
wire signed [WD_OUT-1:0] output_sample;
reg [2:0] bass_gain_select, mid_gain_select, treb_gain_select;
integer file, status, outfile;
integer gain_case = 0;

// Instantiate DUT
equalizer dut (
.sample_clock(clk),
.reset(reset_n),
.input_sample(input_sample),
.bass_gain_select(bass_gain_select),
.mid_gain_select(mid_gain_select),
.treb_gain_select(treb_gain_select),
.output_sample(output_sample)
);

// Clock generation
always #HALF_PERIOD clk = ~clk;

// Testbench logic
initial begin
// Initialize signals
clk = 0;
reset_n = 0;
input_sample = 0;

// Set default gain to 111


bass_gain_select = 3'b111; // Initial value for Bass
mid_gain_select = 3'b111; // Initial value for Mid
treb_gain_select = 3'b111; // Initial value for Treble

$display("Initial Bass Gain Select = %b, Mid Gain Select = %b, Treble Gain Select = %b",
bass_gain_select, mid_gain_select, treb_gain_select);

// Apply reset
$display("Applying reset...");
repeat (5) @(posedge clk);
reset_n = 1;
$display("Reset released...");

// Open input and output files


file = $fopen(FILE_PATH, "r");
outfile = $fopen(OUT_PATH, "w");
if (file == 0) begin
$fatal("Error: Input file '%s' could not be opened.", FILE_PATH);
end
if (outfile == 0) begin
$fatal("Error: Output file '%s' could not be opened.", OUT_PATH);
end

// Iterate through gain cases


for (gain_case = 0; gain_case < 8; gain_case = gain_case + 1) begin
@(posedge clk);
// Update gain selectors
bass_gain_select <= gain_case[2:0];
mid_gain_select <= gain_case[2:0];
treb_gain_select <= gain_case[2:0];
#1; // Ensure values propagate
$display("DEBUG: Gain Case = %0d | Bass Gain Select = %b | Mid Gain Select = %b | Treble Gain
Select = %b",
gain_case, bass_gain_select, mid_gain_select, treb_gain_select);

// Process input samples


while (!$feof(file)) begin
@(posedge clk);
status = $fscanf(file, "%h\n", input_sample);
if (status != 1) break;

@(posedge clk);
$fdisplay(outfile, "Gain Case %0d: Input = %h | Output = %h",
gain_case, input_sample, output_sample);
end
$rewind(file); // Rewind file for the next gain case
end

// Close files and finish simulation


$fclose(file);
$fclose(outfile);
$display("Simulation complete. Output written to '%s'.", OUT_PATH);
$finish;
end

// Monitor signals
initial begin
$monitor("Time = %0t | Reset = %b | Gain Case = %0d | Bass Gain Select = %b | Mid Gain Select =
%b | Treble Gain Select = %b",
$time, reset_n, gain_case, bass_gain_select, mid_gain_select, treb_gain_select);
end
endmodule

You might also like