Skip to content

Commit

Permalink
Audio implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
SagarDevAchar authored Aug 20, 2024
1 parent 6508942 commit 6841e52
Show file tree
Hide file tree
Showing 7 changed files with 270 additions and 20 deletions.
6 changes: 3 additions & 3 deletions docs/info.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ You can also include images in this folder and reference them in the markdown. E

## How it works

Explain how your project works
It just works!

## How to test

Explain how to use your project
Just provide clock and reset

## External hardware

List external hardware used in your project (e.g. PMOD, LED display, etc), if any
VGA and Audio PMOD
21 changes: 12 additions & 9 deletions info.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ project:
# Don't forget to also update `PROJECT_SOURCES` in test/Makefile.
source_files:
- "project.v"
- "vga_controller.v"
- "audio_engine.v"
- "freq_synth.v"

# The pinout of your project. Leave unused pins blank. DO NOT delete or add any pins.
pinout:
Expand All @@ -32,14 +35,14 @@ pinout:
ui[7]: ""

# Outputs
uo[0]: ""
uo[1]: ""
uo[2]: ""
uo[3]: ""
uo[4]: ""
uo[5]: ""
uo[6]: ""
uo[7]: ""
uo[0]: "Video Red MSB"
uo[1]: "Video Green MSB"
uo[2]: "Video Blue MSB"
uo[3]: "Video V-Sync"
uo[4]: "Video Red LSB"
uo[5]: "Video Green LSB"
uo[6]: "Video Blue LSB"
uo[7]: "Video H-Sync"

# Bidirectional pins
uio[0]: ""
Expand All @@ -49,7 +52,7 @@ pinout:
uio[4]: ""
uio[5]: ""
uio[6]: ""
uio[7]: ""
uio[7]: "Audio Output"

# Do not change!
yaml_version: 6
132 changes: 132 additions & 0 deletions src/audio_engine.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
`default_nettype none

module audio_engine(
output wire audio,
input wire clk, rst_n
);

parameter [6:0] NOTE_B1 = 7'd100;
parameter [6:0] NOTE_D2 = 7'd84;
parameter [6:0] NOTE_E2 = 7'd74;
parameter [6:0] NOTE_F2 = 7'd70;
parameter [6:0] NOTE_G2 = 7'd62;
parameter [6:0] NOTE_A2 = 7'd55;
parameter [6:0] NOTE_C3 = 7'd47;
parameter [6:0] NOTE_D3 = 7'd42;
parameter [6:0] NOTE_E3 = 7'd37;
parameter [6:0] NOTE_F3 = 7'd35;
parameter [6:0] NOTE_G3 = 7'd31;
parameter [6:0] NOTE_A3 = 7'd28;

function [6:0] seq_lut (input [6:0] timestamp);
begin
if (~timestamp[6]) begin
if (~timestamp[4]) begin
case (timestamp[3:0])
4'h0,
4'h1,
4'h3,
4'h4,
4'h6,
4'h7,
4'h9,
4'hA: seq_lut = NOTE_C3;
4'h2,
4'h8,
4'hE: seq_lut = NOTE_F2;
4'h5,
4'hB: seq_lut = NOTE_A2;
4'hC: seq_lut = NOTE_D2;
4'hD: seq_lut = NOTE_E2;
4'hF: seq_lut = NOTE_G2;
endcase
end else begin
case (timestamp[3:0])
4'h0,
4'h1,
4'h3,
4'h4,
4'h6,
4'h7,
4'h9,
4'hA,
4'hC,
4'hD,
4'hF: seq_lut = NOTE_G2;
4'h2,
4'h8,
4'hE: seq_lut = NOTE_D2;
4'h5,
4'hB: seq_lut = NOTE_B1;
endcase
end
end else begin
if (~timestamp[2]) begin
case (timestamp[1:0])
4'h0,
4'h1: seq_lut = NOTE_A2;
4'h2: seq_lut = NOTE_A3;
4'h3: seq_lut = NOTE_F2;
endcase
end else begin
if (~(timestamp[4] & timestamp[3])) begin
case (timestamp[1:0])
4'h0: seq_lut = NOTE_C3;
4'h1: seq_lut = NOTE_E3;
4'h2,
4'h3: seq_lut = NOTE_D3;
endcase
end else begin
case (timestamp[1:0])
4'h0,
4'h2: seq_lut = NOTE_D3;
4'h1: seq_lut = NOTE_F3;
4'h3: seq_lut = NOTE_C3;
endcase
end
end
end
end
endfunction

wire synth_clk, seq_clk, seq_active;
reg [4:0] seq_ctr;
reg [6:0] seq_time;
wire [6:0] seq_hp;

reg [17:0] counter;
always @(posedge clk or negedge rst_n) begin
if (~rst_n)
counter <= 17'd0;
else
counter <= counter + 1;
end

assign synth_clk = counter[10];
assign seq_clk = counter[17];

always @(posedge seq_clk or negedge rst_n) begin
if (~rst_n) begin
seq_ctr <= 5'd0;
seq_time <= 8'd0;
end else begin
if (seq_ctr == 5'd19) begin
seq_ctr <= 5'd0;
seq_time <= seq_time + 1;
end else
seq_ctr <= seq_ctr + 5'd1;
end
end

assign seq_hp = seq_lut(seq_time);
assign seq_active = seq_ctr < 8'd10;

freq_synth freq_synth1 (
.audio(audio),
.synth_clk(synth_clk), .rst_n(rst_n),
.hp(seq_hp),
.active(seq_active)
);

wire _unused = 0;
endmodule
2 changes: 1 addition & 1 deletion src/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

"//": "CLOCK_PERIOD - Increase this in case you are getting setup time violations.",
"//": "The value is in nanoseconds, so 20ns == 50MHz.",
"CLOCK_PERIOD": 20,
"CLOCK_PERIOD": 40,

"//": "Hold slack margin - Increase them in case you are getting hold violations.",
"PL_RESIZER_HOLD_SLACK_MARGIN": 0.1,
Expand Down
28 changes: 28 additions & 0 deletions src/freq_synth.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
`default_nettype none

module freq_synth(
output wire audio,
input wire synth_clk, rst_n,
input wire [6:0] hp,
input wire active
);

reg audio_reg;
reg [6:0] hp_ctr;
always @ (posedge synth_clk or negedge rst_n) begin
if (~active | ~rst_n) begin
audio_reg <= 1'd0;
hp_ctr <= 1'd1;
end else begin
if (hp_ctr == hp) begin
hp_ctr <= 1'd1;
audio_reg <= ~audio_reg;
end else
hp_ctr <= hp_ctr + 1'd1;
end
end

assign audio = audio_reg & active;

wire _unused = 0;
endmodule
45 changes: 38 additions & 7 deletions src/project.v
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024 Your Name
* Copyright (c) 2024 Sagar Dev Achar
* SPDX-License-Identifier: Apache-2.0
*/

Expand All @@ -16,12 +16,43 @@ module tt_um_demosiine_sda (
input wire rst_n // reset_n - low to reset
);

// All output pins must be assigned. If not used, assign to 0.
assign uo_out = ui_in + uio_in; // Example: ou_out is the sum of ui_in and uio_in
assign uio_out = 0;
assign uio_oe = 0;
wire [1:0] r, g, b;
wire audio;

wire [9:0] x, y;
wire h_sync, v_sync;
wire frame_active;

vga_controller vga_controller_1 (
.x(x), .y(y),
.h_sync(h_sync), .v_sync(v_sync),
.frame_active(frame_active),
.clk(clk), .rst_n(rst_n)
);

/*graphics_engine graphics_engine_1 (
.r(r), .g(g), .b(b),
.x(x), .y(y),
.frame_active(frame_active), .v_sync(v_sync),
.clk(clk), .rst_n(rst_n)
);*/

audio_engine audio_engine_1 (
.audio(audio),
.clk(clk), .rst_n(rst_n)
);

// All output pins must be assigned. If not used, assign to 0.
assign uo_out = {
h_sync, b[0], g[0], r[0],
v_sync, b[1], g[1], r[1]
};
assign uio_out = {audio, 7'd0};
assign uio_oe = 8'b1000_0000;

// List all unused inputs to prevent warnings
wire _unused = &{ena, clk, rst_n, 1'b0};
assign {r, g, b} = 6'b11_11_11;

// List all unused inputs to prevent warnings
wire _unused = &{ena, ui_in, uio_in};

endmodule
56 changes: 56 additions & 0 deletions src/vga_controller.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Derived from TinyTapeout/vga-playground/blob/main/src/examples/common/hvsync_generator.v
// Just some refactoring to maintain coding style

`default_nettype none

module vga_controller (
output reg [9:0] x, y,
output reg h_sync, v_sync,
output wire frame_active,
input wire clk, rst_n
);

// declarations for TV-simulator sync parameters
// horizontal constants
parameter W_DISPLAY = 640; // horizontal display width
parameter W_BACK = 48; // horizontal left border (back porch)
parameter W_FRONT = 16; // horizontal right border (front porch)
parameter W_SYNC = 96; // horizontal sync width
// vertical constants
parameter H_DISPLAY = 480; // vertical display height
parameter H_TOP = 33; // vertical top border
parameter H_BOTTOM = 10; // vertical bottom border
parameter H_SYNC = 2; // vertical sync # lines
// derived constants
parameter W_SYNC_START = W_DISPLAY + W_FRONT;
parameter W_SYNC_END = W_DISPLAY + W_FRONT + W_SYNC - 1;
parameter W_MAX = W_DISPLAY + W_BACK + W_FRONT + W_SYNC - 1;
parameter H_SYNC_START = H_DISPLAY + H_BOTTOM;
parameter H_SYNC_END = H_DISPLAY + H_BOTTOM + H_SYNC - 1;
parameter H_MAX = H_DISPLAY + H_TOP + H_BOTTOM + H_SYNC - 1;

wire h_limit = (x == W_MAX) || rst_n; // set when x is maximum
wire v_limit = (y == H_MAX) || rst_n; // set when y is maximum

// horizontal position counter
always @(posedge clk) begin
h_sync <= (x >= W_SYNC_START && x <= W_SYNC_END);
if(h_limit)
x <= 0;
else
x <= x + 1;
end

// vertical position counter
always @(posedge clk) begin
v_sync <= (y >= H_SYNC_START && y <= H_SYNC_END);
if(h_limit)
if (v_limit)
y <= 0;
else
y <= y + 1;
end

// frame_active is set when beam is in visible frame
assign frame_active = (x < W_DISPLAY) && (y < H_DISPLAY);
endmodule

0 comments on commit 6841e52

Please sign in to comment.