diff --git a/.github/workflows/synthesis.yml b/.github/workflows/synthesis.yml index d82e3bb7..b279fb1b 100644 --- a/.github/workflows/synthesis.yml +++ b/.github/workflows/synthesis.yml @@ -26,12 +26,12 @@ jobs: - tool: quartus imagerepo: ghcr.io/raetro/quartus imagever: 21.1.1 - boards: 40 + boards: 43 labs: 12345 - tool: quartus imagerepo: ghcr.io/raetro/quartus imagever: 13.0sp1 - boards: 9 35 + boards: 10 36 labs: 12345 steps: - name: Checkout diff --git a/boards/tang_nano_9k_hdmi_tm1638/board_specific_top.sv b/boards/tang_nano_9k_hdmi_tm1638/board_specific_top.sv index 843cdf5e..180cd53f 100644 --- a/boards/tang_nano_9k_hdmi_tm1638/board_specific_top.sv +++ b/boards/tang_nano_9k_hdmi_tm1638/board_specific_top.sv @@ -417,10 +417,10 @@ module board_specific_top ( .clk ( clk ), .rst ( rst ), - .lr ( TF_CS ), - .ws ( TF_MOSI ), - .sck ( TF_SCLK ), - .sd ( TF_MISO ), + .lr ( TF_CS ), // 38 + .ws ( TF_MOSI ), // 37 + .sck ( TF_SCLK ), // 36 + .sd ( TF_MISO ), // 39 .value ( mic ) ); diff --git a/labs/3_music/3_0_oscilloscope/01_clean.bash b/labs/3_music/3_0_oscilloscope/01_clean.bash new file mode 100755 index 00000000..249b1079 --- /dev/null +++ b/labs/3_music/3_0_oscilloscope/01_clean.bash @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +set -Eeuo pipefail # See the meaning in scripts/README.md + +script=$(basename "$0") +source_script=${script/\.bash/.source_bash} +dir_source_script=../scripts/steps/$source_script + +for i in {1..3} +do + [ -f $dir_source_script ] && break + dir_source_script=../$dir_source_script +done + +if ! [ -f $dir_source_script ]; then + printf "$script: cannot find \"$source_script\"\n" 1>&2 + exit 1 +fi + +dir_source_script=$(readlink -f $dir_source_script) +. "$dir_source_script" diff --git a/labs/3_music/3_0_oscilloscope/02_simulate_rtl.bash b/labs/3_music/3_0_oscilloscope/02_simulate_rtl.bash new file mode 100755 index 00000000..249b1079 --- /dev/null +++ b/labs/3_music/3_0_oscilloscope/02_simulate_rtl.bash @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +set -Eeuo pipefail # See the meaning in scripts/README.md + +script=$(basename "$0") +source_script=${script/\.bash/.source_bash} +dir_source_script=../scripts/steps/$source_script + +for i in {1..3} +do + [ -f $dir_source_script ] && break + dir_source_script=../$dir_source_script +done + +if ! [ -f $dir_source_script ]; then + printf "$script: cannot find \"$source_script\"\n" 1>&2 + exit 1 +fi + +dir_source_script=$(readlink -f $dir_source_script) +. "$dir_source_script" diff --git a/labs/3_music/3_0_oscilloscope/03_synthesize_for_fpga.bash b/labs/3_music/3_0_oscilloscope/03_synthesize_for_fpga.bash new file mode 100755 index 00000000..249b1079 --- /dev/null +++ b/labs/3_music/3_0_oscilloscope/03_synthesize_for_fpga.bash @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +set -Eeuo pipefail # See the meaning in scripts/README.md + +script=$(basename "$0") +source_script=${script/\.bash/.source_bash} +dir_source_script=../scripts/steps/$source_script + +for i in {1..3} +do + [ -f $dir_source_script ] && break + dir_source_script=../$dir_source_script +done + +if ! [ -f $dir_source_script ]; then + printf "$script: cannot find \"$source_script\"\n" 1>&2 + exit 1 +fi + +dir_source_script=$(readlink -f $dir_source_script) +. "$dir_source_script" diff --git a/labs/3_music/3_0_oscilloscope/04_configure_fpga.bash b/labs/3_music/3_0_oscilloscope/04_configure_fpga.bash new file mode 100755 index 00000000..249b1079 --- /dev/null +++ b/labs/3_music/3_0_oscilloscope/04_configure_fpga.bash @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +set -Eeuo pipefail # See the meaning in scripts/README.md + +script=$(basename "$0") +source_script=${script/\.bash/.source_bash} +dir_source_script=../scripts/steps/$source_script + +for i in {1..3} +do + [ -f $dir_source_script ] && break + dir_source_script=../$dir_source_script +done + +if ! [ -f $dir_source_script ]; then + printf "$script: cannot find \"$source_script\"\n" 1>&2 + exit 1 +fi + +dir_source_script=$(readlink -f $dir_source_script) +. "$dir_source_script" diff --git a/labs/3_music/3_0_oscilloscope/05_run_gui_for_fpga_synthesis.bash b/labs/3_music/3_0_oscilloscope/05_run_gui_for_fpga_synthesis.bash new file mode 100755 index 00000000..249b1079 --- /dev/null +++ b/labs/3_music/3_0_oscilloscope/05_run_gui_for_fpga_synthesis.bash @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +set -Eeuo pipefail # See the meaning in scripts/README.md + +script=$(basename "$0") +source_script=${script/\.bash/.source_bash} +dir_source_script=../scripts/steps/$source_script + +for i in {1..3} +do + [ -f $dir_source_script ] && break + dir_source_script=../$dir_source_script +done + +if ! [ -f $dir_source_script ]; then + printf "$script: cannot find \"$source_script\"\n" 1>&2 + exit 1 +fi + +dir_source_script=$(readlink -f $dir_source_script) +. "$dir_source_script" diff --git a/labs/3_music/3_0_oscilloscope/06_choose_another_fpga_board.bash b/labs/3_music/3_0_oscilloscope/06_choose_another_fpga_board.bash new file mode 100755 index 00000000..249b1079 --- /dev/null +++ b/labs/3_music/3_0_oscilloscope/06_choose_another_fpga_board.bash @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +set -Eeuo pipefail # See the meaning in scripts/README.md + +script=$(basename "$0") +source_script=${script/\.bash/.source_bash} +dir_source_script=../scripts/steps/$source_script + +for i in {1..3} +do + [ -f $dir_source_script ] && break + dir_source_script=../$dir_source_script +done + +if ! [ -f $dir_source_script ]; then + printf "$script: cannot find \"$source_script\"\n" 1>&2 + exit 1 +fi + +dir_source_script=$(readlink -f $dir_source_script) +. "$dir_source_script" diff --git a/labs/3_music/3_0_oscilloscope/07_synthesize_for_asic.bash b/labs/3_music/3_0_oscilloscope/07_synthesize_for_asic.bash new file mode 100755 index 00000000..249b1079 --- /dev/null +++ b/labs/3_music/3_0_oscilloscope/07_synthesize_for_asic.bash @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +set -Eeuo pipefail # See the meaning in scripts/README.md + +script=$(basename "$0") +source_script=${script/\.bash/.source_bash} +dir_source_script=../scripts/steps/$source_script + +for i in {1..3} +do + [ -f $dir_source_script ] && break + dir_source_script=../$dir_source_script +done + +if ! [ -f $dir_source_script ]; then + printf "$script: cannot find \"$source_script\"\n" 1>&2 + exit 1 +fi + +dir_source_script=$(readlink -f $dir_source_script) +. "$dir_source_script" diff --git a/labs/3_music/3_0_oscilloscope/08_visualize_asic_synthesis_results_1.bash b/labs/3_music/3_0_oscilloscope/08_visualize_asic_synthesis_results_1.bash new file mode 100755 index 00000000..249b1079 --- /dev/null +++ b/labs/3_music/3_0_oscilloscope/08_visualize_asic_synthesis_results_1.bash @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +set -Eeuo pipefail # See the meaning in scripts/README.md + +script=$(basename "$0") +source_script=${script/\.bash/.source_bash} +dir_source_script=../scripts/steps/$source_script + +for i in {1..3} +do + [ -f $dir_source_script ] && break + dir_source_script=../$dir_source_script +done + +if ! [ -f $dir_source_script ]; then + printf "$script: cannot find \"$source_script\"\n" 1>&2 + exit 1 +fi + +dir_source_script=$(readlink -f $dir_source_script) +. "$dir_source_script" diff --git a/labs/3_music/3_0_oscilloscope/09_visualize_asic_synthesis_results_2.bash b/labs/3_music/3_0_oscilloscope/09_visualize_asic_synthesis_results_2.bash new file mode 100755 index 00000000..249b1079 --- /dev/null +++ b/labs/3_music/3_0_oscilloscope/09_visualize_asic_synthesis_results_2.bash @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +set -Eeuo pipefail # See the meaning in scripts/README.md + +script=$(basename "$0") +source_script=${script/\.bash/.source_bash} +dir_source_script=../scripts/steps/$source_script + +for i in {1..3} +do + [ -f $dir_source_script ] && break + dir_source_script=../$dir_source_script +done + +if ! [ -f $dir_source_script ]; then + printf "$script: cannot find \"$source_script\"\n" 1>&2 + exit 1 +fi + +dir_source_script=$(readlink -f $dir_source_script) +. "$dir_source_script" diff --git a/labs/3_music/3_0_oscilloscope/emooc_cc_wiring.jpg b/labs/3_music/3_0_oscilloscope/emooc_cc_wiring.jpg new file mode 100644 index 00000000..c7be45af Binary files /dev/null and b/labs/3_music/3_0_oscilloscope/emooc_cc_wiring.jpg differ diff --git a/labs/3_music/3_0_oscilloscope/gtkwave.tcl b/labs/3_music/3_0_oscilloscope/gtkwave.tcl new file mode 100644 index 00000000..67b1a193 --- /dev/null +++ b/labs/3_music/3_0_oscilloscope/gtkwave.tcl @@ -0,0 +1,19 @@ +# gtkwave::loadFile "dump.vcd" + +set all_signals [list] + +lappend all_signals tb.dut.clk +lappend all_signals tb.dut.rst +lappend all_signals tb.dut.lr +lappend all_signals tb.dut.ws +lappend all_signals tb.dut.sck +lappend all_signals tb.dut.sd +lappend all_signals tb.dut.value +lappend all_signals tb.dut.cnt +lappend all_signals tb.dut.sample_bit +lappend all_signals tb.dut.value_done +lappend all_signals tb.dut.shift + +set num_added [ gtkwave::addSignalsFromList $all_signals ] + +gtkwave::/Time/Zoom/Zoom_Full diff --git a/labs/3_music/3_0_oscilloscope/lab_specific_board_config.svh b/labs/3_music/3_0_oscilloscope/lab_specific_board_config.svh new file mode 100644 index 00000000..0fd1b10a --- /dev/null +++ b/labs/3_music/3_0_oscilloscope/lab_specific_board_config.svh @@ -0,0 +1,18 @@ +`ifndef LAB_SPECIFIC_CONFIG_SVH +`define LAB_SPECIFIC_CONFIG_SVH + + `define INSTANTIATE_TM1638_BOARD_CONTROLLER_MODULE + `define FORCE_NO_VIRTUAL_TM1638_USING_GRAPHICS +// `define USE_HCW132_VARIANT_OF_TM1638_BOARD_CONTROLLER_MODULE + + `define DUPLICATE_TM1638_SIGNALS_WITH_REGULAR +// `define CONCAT_REGULAR_SIGNALS_AND_TM1638 +// `define CONCAT_TM1638_SIGNALS_AND_REGULAR + + `define EMULATE_DYNAMIC_7SEG_ON_STATIC_WITHOUT_STICKY_FLOPS + + `define INSTANTIATE_GRAPHICS_INTERFACE_MODULE + `define INSTANTIATE_MICROPHONE_INTERFACE_MODULE + `define INSTANTIATE_SOUND_OUTPUT_INTERFACE_MODULE + +`endif // `ifndef LAB_SPECIFIC_CONFIG_SVH diff --git a/labs/3_music/3_0_oscilloscope/lab_top.sv b/labs/3_music/3_0_oscilloscope/lab_top.sv new file mode 100644 index 00000000..7b7efc76 --- /dev/null +++ b/labs/3_music/3_0_oscilloscope/lab_top.sv @@ -0,0 +1,123 @@ +`include "config.svh" + +module lab_top +# ( + parameter clk_mhz = 50, + w_key = 4, + w_sw = 8, + w_led = 8, + w_digit = 8, + w_gpio = 100, + + screen_width = 640, + screen_height = 480, + + w_red = 4, + w_green = 4, + w_blue = 4, + + w_x = $clog2 ( screen_width ), + w_y = $clog2 ( screen_height ) +) +( + input clk, + input slow_clk, + input rst, + + // Keys, switches, LEDs + + input [w_key - 1:0] key, + input [w_sw - 1:0] sw, + output logic [w_led - 1:0] led, + + // A dynamic seven-segment display + + output logic [ 7:0] abcdefgh, + output logic [w_digit - 1:0] digit, + + // Graphics + + input [w_x - 1:0] x, + input [w_y - 1:0] y, + + output logic [w_red - 1:0] red, + output logic [w_green - 1:0] green, + output logic [w_blue - 1:0] blue, + + // Microphone, sound output and UART + + input [ 23:0] mic, + output [ 15:0] sound, + + input uart_rx, + output uart_tx, + + // General-purpose Input/Output + + inout [w_gpio - 1:0] gpio +); + + //------------------------------------------------------------------------ + + // assign led = '0; + // assign abcdefgh = '0; + // assign digit = '0; + // assign red = '0; + // assign green = '0; + // assign blue = '0; + assign sound = '0; + assign uart_tx = '1; + + logic white; + assign red = {w_red {white}}; + assign green = {w_green{white}}; + assign blue = {w_blue {white}}; + + + //------------------------------------------------------------------------ + // + // Oscilloscope + // + //------------------------------------------------------------------------ + + // It is enough for the counter to be 20 bit. Why? + + logic [23:0] prev_mic; + logic [19:0] counter; + logic [19:0] distance; + logic signed [w_y-1:0] bufy[screen_width/2]; + wire signed [w_y-1:0] micy = {mic[23], (mic[23]?~&mic[22:16]:|mic[22:16])? ~{(w_y-1){$signed(mic[23])}} : mic[15-:w_y-1]}; + wire [w_x-1:0] cnt = counter[19-:w_x]; + localparam logic signed [w_y-1:0] midy = screen_height/2; + + always_comb + white = (x>>1) < (distance[19-:w_x]) && y == midy - bufy[(x>>1)] && x < screen_width && y < screen_height; + + always_ff @ (posedge clk or posedge rst) + if (rst) + begin + prev_mic <= '0; + counter <= '0; + distance <= '0; + end + else + begin + if (cnt < screen_width/2) + bufy[cnt] <= micy; + + prev_mic <= mic; + + // Crossing from negative to positive numbers + if ( prev_mic [$left ( prev_mic )] == 1'b1 + & mic [$left ( mic )] == 1'b0 ) + begin + distance <= counter; + counter <= 20'h0; + end + else if (counter != ~ 20'h0) // To prevent overflow + begin + counter <= counter + 20'h1; + end + end + +endmodule diff --git a/labs/3_music/3_0_oscilloscope/mic_waves.png b/labs/3_music/3_0_oscilloscope/mic_waves.png new file mode 100644 index 00000000..52015ec7 Binary files /dev/null and b/labs/3_music/3_0_oscilloscope/mic_waves.png differ diff --git a/labs/3_music/3_0_oscilloscope/tb.sv b/labs/3_music/3_0_oscilloscope/tb.sv new file mode 100644 index 00000000..635253ca --- /dev/null +++ b/labs/3_music/3_0_oscilloscope/tb.sv @@ -0,0 +1,148 @@ +`include "config.svh" + +// This testbench is for microphone module only + +module tb; + + logic clk; + logic rst; + wire lr; + wire ws; + wire sck; + logic sd; + wire [23:0] value; + + //------------------------------------------------------------------------ + + inmp441_mic_i2s_receiver dut (.*); + + //------------------------------------------------------------------------ + + initial + begin + clk = 1'b0; + + forever + # 5 clk = ~ clk; + end + + //------------------------------------------------------------------------ + + initial + begin + rst <= 1'bx; + repeat (2) @ (posedge clk); + rst <= 1'b1; + repeat (2) @ (posedge clk); + rst <= 1'b0; + end + + //------------------------------------------------------------------------ + + initial + begin + `ifdef __ICARUS__ + $dumpvars; + `endif + + @ (negedge rst); + + repeat (100000) + begin + sd <= $urandom (); + @ (posedge clk); + end + + $finish; + end + +endmodule + +//---------------------------------------------------------------------------- + +`ifdef UNDEFINED + +module tb; + + localparam clk_mhz = 1, + w_key = 4, + w_sw = 8, + w_led = 8, + w_digit = 8, + w_gpio = 100; + + //------------------------------------------------------------------------ + + logic clk; + logic rst; + logic [3:0] key; + logic [7:0] sw; + + //------------------------------------------------------------------------ + + lab_top + # ( + .clk_mhz ( clk_mhz ), + .w_key ( w_key ), + .w_sw ( w_sw ), + .w_led ( w_led ), + .w_digit ( w_digit ), + .w_gpio ( w_gpio ) + ) + i_lab_top + ( + .clk ( clk ), + .slow_clk ( clk ), + .rst ( rst ), + .key ( key ), + .sw ( sw ) + ); + + //------------------------------------------------------------------------ + + initial + begin + clk = 1'b0; + + forever + # 5 clk = ~ clk; + end + + //------------------------------------------------------------------------ + + initial + begin + rst <= 1'bx; + repeat (2) @ (posedge clk); + rst <= 1'b1; + repeat (2) @ (posedge clk); + rst <= 1'b0; + end + + //------------------------------------------------------------------------ + + initial + begin + `ifdef __ICARUS__ + $dumpvars; + `endif + + key <= '0; + sw <= '0; + + @ (negedge rst); + + repeat (50) + begin + @ (posedge clk); + + key <= $urandom (); + sw <= $urandom (); + end + + $finish; + end + +endmodule + +`endif diff --git a/peripherals/inmp441_mic_i2s_receiver_new.sv b/peripherals/inmp441_mic_i2s_receiver_new.sv index 7ff424db..184a19f1 100644 --- a/peripherals/inmp441_mic_i2s_receiver_new.sv +++ b/peripherals/inmp441_mic_i2s_receiver_new.sv @@ -40,11 +40,11 @@ module inmp441_mic_i2s_receiver logic sck_negedge; // Tracks SCK negedge always_ff @ (posedge clk or posedge rst) - if (rst) + if (rst) begin cnt <= '0; sck_posedge <= '0; sck_negedge <= '0; - else + end else if (cnt == sck_clock_divisor - 1'b1) // Every N cycles drive SCK up or down begin sck <= ~ sck;