0% found this document useful (0 votes)
6 views

Code

Uploaded by

Huy Nguyễn
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views

Code

Uploaded by

Huy Nguyễn
Copyright
© © All Rights Reserved
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