From f82d3c74df96574a90272aa428bec86844a0078f Mon Sep 17 00:00:00 2001 From: Niels Moseley Date: Fri, 27 Oct 2017 01:26:35 +0200 Subject: [PATCH] Added hex display drivers to the DE0 board so it will display the allophone codes while playing. --- boards/Digilent DE0/Speech256_DE0.qsf | 15 +++ boards/Digilent DE0/speech256_de0.v | 165 ++++++++++++++++++++++- verilog/controller/controller.v | 3 +- verilog/pwmdac/pwmdac.v | 40 ++++-- verilog/source/source.v | 13 +- verilog/source/source_tb.v | 2 +- verilog/speech256_top/speech256_top.v | 6 +- verilog/speech256_top/speech256_top_tb.v | 18 ++- 8 files changed, 235 insertions(+), 27 deletions(-) diff --git a/boards/Digilent DE0/Speech256_DE0.qsf b/boards/Digilent DE0/Speech256_DE0.qsf index c7c8261..c5c6235 100644 --- a/boards/Digilent DE0/Speech256_DE0.qsf +++ b/boards/Digilent DE0/Speech256_DE0.qsf @@ -74,6 +74,20 @@ set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[2] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[3] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[4] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX1_D[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX1_D[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX1_D[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX1_D[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX1_D[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX1_D[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX1_D[6] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX2_D[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX2_D[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX2_D[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX2_D[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX2_D[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX2_D[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX2_D[6] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to UART_TXD set_location_assignment PIN_B1 -to LEDG[9] set_location_assignment PIN_B2 -to LEDG[8] @@ -337,5 +351,6 @@ set_global_assignment -name VERILOG_FILE ../../verilog/pwmdac/pwmdac.v set_global_assignment -name VERILOG_FILE ../../verilog/source/source.v set_global_assignment -name VERILOG_FILE ../../verilog/spmul/spmul.v set_global_assignment -name VERILOG_FILE ../../verilog/sd2dac/sd2dac.v +set_global_assignment -name VERILOG_FILE segmentdisplay.v set_global_assignment -name VERILOG_FILE ../../verilog/speech256_top/speech256_top.v set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/boards/Digilent DE0/speech256_de0.v b/boards/Digilent DE0/speech256_de0.v index 4a18e63..91fac18 100644 --- a/boards/Digilent DE0/speech256_de0.v +++ b/boards/Digilent DE0/speech256_de0.v @@ -12,12 +12,16 @@ module Speech256_DE0 ( SW, BUTTON, LEDG, - UART_TXD + UART_TXD, + HEX1_D, + HEX2_D ); input CLOCK_50; input [0:5] SW; input [0:2] BUTTON; + output [6:0] HEX1_D; + output [6:0] HEX2_D; output [9:0] LEDG; output UART_TXD; @@ -27,7 +31,7 @@ module Speech256_DE0 ( reg [3:0] divcnt; // clock divider counter reg [2:0] cur_state, next_state; - reg [3:0] rom_addr; + reg [7:0] rom_addr; reg [5:0] rom_data; reg inc_rom_addr; @@ -38,6 +42,21 @@ module Speech256_DE0 ( wire ldq; wire rst_an; + // 7-segment display for allophone display + segmentdisplay u_disp1 ( + .clk (clk), + .latch (data_stb), + .hexdigit_in (rom_data[3:0]), + .display_out (HEX1_D) + ); + + segmentdisplay u_disp2 ( + .clk (clk), + .latch (data_stb), + .hexdigit_in ({2'b00, rom_data[5:4]}), + .display_out (HEX2_D) + ); + SPEECH256_TOP u_speech256_top ( .clk (clk), .rst_an (rst_an), @@ -122,7 +141,8 @@ module Speech256_DE0 ( endcase // allophone ROM - // hello, world + // hello, world +`ifdef HELLO_WORLD case (rom_addr) 4'd0: rom_data <= 6'h1B; @@ -150,5 +170,144 @@ module Speech256_DE0 ( rom_data <= 6'h03; endcase end +`else + case (rom_addr) + 8'h00: rom_data <= 6'h21; + 8'h01: rom_data <= 6'h14; + 8'h02: rom_data <= 6'h00; + 8'h03: rom_data <= 6'h2B; + 8'h04: rom_data <= 6'h13; + 8'h05: rom_data <= 6'h04; + 8'h06: rom_data <= 6'h21; + 8'h07: rom_data <= 6'h14; + 8'h08: rom_data <= 6'h00; + 8'h09: rom_data <= 6'h2B; + 8'h0A: rom_data <= 6'h13; + 8'h0B: rom_data <= 6'h03; + 8'h0C: rom_data <= 6'h0D; + 8'h0D: rom_data <= 6'h3E; + 8'h0E: rom_data <= 6'h2D; + 8'h0F: rom_data <= 6'h02; + 8'h10: rom_data <= 6'h10; + 8'h11: rom_data <= 6'h13; + 8'h12: rom_data <= 6'h02; + 8'h13: rom_data <= 6'h0D; + 8'h14: rom_data <= 6'h27; + 8'h15: rom_data <= 6'h16; + 8'h16: rom_data <= 6'h04; + 8'h17: rom_data <= 6'h06; + 8'h18: rom_data <= 6'h10; + 8'h19: rom_data <= 6'h02; + 8'h1A: rom_data <= 6'h18; + 8'h1B: rom_data <= 6'h28; + 8'h1C: rom_data <= 6'h27; + 8'h1D: rom_data <= 6'h14; + 8'h1E: rom_data <= 6'h15; + 8'h1F: rom_data <= 6'h03; + 8'h20: rom_data <= 6'h06; + 8'h21: rom_data <= 6'h02; + 8'h22: rom_data <= 6'h2A; + 8'h23: rom_data <= 6'h1A; + 8'h24: rom_data <= 6'h0B; + 8'h25: rom_data <= 6'h11; + 8'h26: rom_data <= 6'h03; + 8'h27: rom_data <= 6'h21; + 8'h28: rom_data <= 6'h1F; + 8'h29: rom_data <= 6'h02; + 8'h2A: rom_data <= 6'h1D; + 8'h2B: rom_data <= 6'h1A; + 8'h2C: rom_data <= 6'h0D; + 8'h2D: rom_data <= 6'h04; + 8'h2E: rom_data <= 6'h21; + 8'h2F: rom_data <= 6'h14; + 8'h30: rom_data <= 6'h23; + 8'h31: rom_data <= 6'h04; + 8'h32: rom_data <= 6'h19; + 8'h33: rom_data <= 6'h07; + 8'h34: rom_data <= 6'h07; + 8'h35: rom_data <= 6'h37; + 8'h36: rom_data <= 6'h37; + 8'h37: rom_data <= 6'h02; + 8'h38: rom_data <= 6'h1A; + 8'h39: rom_data <= 6'h0B; + 8'h3A: rom_data <= 6'h15; + 8'h3B: rom_data <= 6'h03; + 8'h3C: rom_data <= 6'h38; + 8'h3D: rom_data <= 6'h0F; + 8'h3E: rom_data <= 6'h35; + 8'h3F: rom_data <= 6'h04; + 8'h40: rom_data <= 6'h2B; + 8'h41: rom_data <= 6'h3C; + 8'h42: rom_data <= 6'h35; + 8'h43: rom_data <= 6'h03; + 8'h44: rom_data <= 6'h2E; + 8'h45: rom_data <= 6'h0F; + 8'h46: rom_data <= 6'h0F; + 8'h47: rom_data <= 6'h0B; + 8'h48: rom_data <= 6'h03; + 8'h49: rom_data <= 6'h0D; + 8'h4A: rom_data <= 6'h1F; + 8'h4B: rom_data <= 6'h03; + 8'h4C: rom_data <= 6'h1D; + 8'h4D: rom_data <= 6'h0E; + 8'h4E: rom_data <= 6'h13; + 8'h4F: rom_data <= 6'h03; + 8'h50: rom_data <= 6'h28; + 8'h51: rom_data <= 6'h28; + 8'h52: rom_data <= 6'h3A; + 8'h53: rom_data <= 6'h03; + 8'h54: rom_data <= 6'h28; + 8'h55: rom_data <= 6'h28; + 8'h56: rom_data <= 6'h06; + 8'h57: rom_data <= 6'h23; + 8'h58: rom_data <= 6'h03; + 8'h59: rom_data <= 6'h37; + 8'h5A: rom_data <= 6'h37; + 8'h5B: rom_data <= 6'h0C; + 8'h5C: rom_data <= 6'h1E; + 8'h5D: rom_data <= 6'h02; + 8'h5E: rom_data <= 6'h29; + 8'h5F: rom_data <= 6'h37; + 8'h60: rom_data <= 6'h03; + 8'h61: rom_data <= 6'h37; + 8'h62: rom_data <= 6'h37; + 8'h63: rom_data <= 6'h07; + 8'h64: rom_data <= 6'h07; + 8'h65: rom_data <= 6'h23; + 8'h66: rom_data <= 6'h0C; + 8'h67: rom_data <= 6'h0B; + 8'h68: rom_data <= 6'h03; + 8'h69: rom_data <= 6'h14; + 8'h6A: rom_data <= 6'h02; + 8'h6B: rom_data <= 6'h0D; + 8'h6C: rom_data <= 6'h03; + 8'h6D: rom_data <= 6'h0B; + 8'h6E: rom_data <= 6'h06; + 8'h6F: rom_data <= 6'h0B; + 8'h70: rom_data <= 6'h03; + 8'h71: rom_data <= 6'h0D; + 8'h72: rom_data <= 6'h07; + 8'h73: rom_data <= 6'h07; + 8'h74: rom_data <= 6'h0B; + 8'h75: rom_data <= 6'h04; + 8'h76: rom_data <= 6'h13; + 8'h77: rom_data <= 6'h02; + 8'h78: rom_data <= 6'h0D; + 8'h79: rom_data <= 6'h13; + 8'h7A: rom_data <= 6'h03; + 8'h7B: rom_data <= 6'h28; + 8'h7C: rom_data <= 6'h28; + 8'h7D: rom_data <= 6'h35; + 8'h7E: rom_data <= 6'h0B; + 8'h7F: rom_data <= 6'h02; + 8'h80: rom_data <= 6'h39; + 8'h81: rom_data <= 6'h35; + 8'h82: rom_data <= 6'h10; + 8'h83: rom_data <= 6'h10; + 8'h84: rom_data <= 6'h04; + default: rom_data <= 6'h00; + endcase + end +`endif endmodule diff --git a/verilog/controller/controller.v b/verilog/controller/controller.v index f6b7b9c..9783b07 100644 --- a/verilog/controller/controller.v +++ b/verilog/controller/controller.v @@ -166,8 +166,7 @@ module CONTROLLER ( if (serve_pitch_data) begin duration <= dur_tmp; - //amp_out <= {4'b0000, amp_tmp[15:4]}; - amp_out <= {amp_tmp[13:0],2'b00}; + amp_out <= amp_tmp; period_out <= period_tmp; end diff --git a/verilog/pwmdac/pwmdac.v b/verilog/pwmdac/pwmdac.v index 18042ab..5d7307e 100644 --- a/verilog/pwmdac/pwmdac.v +++ b/verilog/pwmdac/pwmdac.v @@ -9,6 +9,8 @@ // For a 10 kHz output rate, the clock rate should be 2.560 MHz // +//`define USE_PREFILTER + module PWMDAC ( clk, rst_an, @@ -36,25 +38,25 @@ module PWMDAC ( // pre-emphasis filter reg signed [7:0] last_data; - reg signed [10:0] sum1r_d; - reg signed [10:0] sum1r; wire signed [10:0] sum1; - wire signed [13:0] sum2; - reg signed [7:0] quantdata; + + // 7- bit signed quantization input + // so we now have 20kHz carrier instead of 10kHz + // .. + reg signed [6:0] quantdata; assign sum1 = $signed({data[7] ,{data, 2'b00}}) + data - $signed({last_data, 2'b00}); - assign sum2 = $signed({sum1r[10],{sum1r, 2'b00}}) + sum1r - $signed({sum1r_d, 2'b00}); // output saturation always @(*) begin - if (sum2[13] ^ sum2[12] != 0) + if (sum1[10] ^ sum1[9] != 0) begin // saturation needed - quantdata = sum2[13] ? 8'h80 : 8'h7F; + quantdata = sum1[10] ? 8'h80 : 8'h7F; end else - quantdata = sum2[12:5]; + quantdata = sum1[9:3]; end always @(posedge clk, negedge rst_an) @@ -74,17 +76,27 @@ module PWMDAC ( // compare counter with data // and set output accordingly. - if (quantdata > counter) - dacout <= 1; - else - dacout <= 0; + // + // Note, we use 7 bits of the counter + // as a PWM waveform to get 2x 10 kHz carrier wave + // but the counter itself needs to be 8 bits + // so the sample rate is still 10ksps! + `ifdef USE_PREFILTER + if (quantdata > $signed(counter[6:0])) + dacout <= 1; + else + dacout <= 0; + `else + if ($signed(data[7:1]) > $signed(counter[6:0])) + dacout <= 1; + else + dacout <= 0; + `endif // load new data into DAC when // counter is 127 if (counter == 8'h7F) begin - sum1r <= sum1; - sum1r_d <= sum1r; last_data <= data; data <= din; din_ack <= 1; diff --git a/verilog/source/source.v b/verilog/source/source.v index 820b428..5cdcf80 100644 --- a/verilog/source/source.v +++ b/verilog/source/source.v @@ -61,7 +61,7 @@ module SOURCE ( // ------------------------------------------------------------ // LFSR NOISE GENERATOR // ------------------------------------------------------------ - if (periodcnt == 64) + if (periodcnt >= 64) begin periodcnt <= 0; period_done <= 1; @@ -70,7 +70,7 @@ module SOURCE ( periodcnt <= periodcnt + 1; // lfsr polynomial is X^17 + X^3 + 1 - lfsr = {lfsr[15:0], lfsr[16] ^ lfsr[2]}; + lfsr <= {lfsr[15:0], lfsr[16] ^ lfsr[2]}; source_out <= lfsr[0] ? {1'b0, amplitude} : {1'b1, ~amplitude}; end else @@ -79,7 +79,7 @@ module SOURCE ( // PULSE GENERATOR // ------------------------------------------------------------ // make periodcnt count from 0 .. period-1 - if (periodcnt == period) + if (periodcnt >= period) begin periodcnt <= 0; period_done <= 1; @@ -90,7 +90,12 @@ module SOURCE ( if (periodcnt < 8) source_out <= {1'b0, amplitude}; else - source_out <= 16'h0000; + source_out <= 16'h0000; + + // reset the noise generator when not in use, + // so it also works on FPGA's where there + // is no reset :) + lfsr <= 17'h1; //note: never reset the LFSR to zero! end end last_strobe <= strobe; diff --git a/verilog/source/source_tb.v b/verilog/source/source_tb.v index b861299..c00e388 100644 --- a/verilog/source/source_tb.v +++ b/verilog/source/source_tb.v @@ -21,7 +21,7 @@ module SOURCE_TB; .period (period), .amplitude (amp), .strobe (strobe), - .period_done (period_done) + .period_done (period_done), .source_out (source_out) ); diff --git a/verilog/speech256_top/speech256_top.v b/verilog/speech256_top/speech256_top.v index ee8c6eb..6413094 100644 --- a/verilog/speech256_top/speech256_top.v +++ b/verilog/speech256_top/speech256_top.v @@ -53,7 +53,9 @@ module SPEECH256_TOP ( SOURCE u_source ( .clk (clk), .rst_an (rst_an), - .period (period), + //.period ({period[6:0], 1'b0}), + //.period ({1'b0,period[7:1]}), + .period (period[7:0]), .amplitude (amp[14:0]), .strobe (src_strobe), .period_done (period_done), @@ -87,7 +89,7 @@ module SPEECH256_TOP ( PWMDAC u_pwmdac ( .clk (clk), .rst_an (rst_an), - .din (sig_filter[12:5]), // add +18dB gain .. FIXME: add saturation ?? + .din (sig_filter[10:3]), // add +30dB gain .. FIXME: add saturation ?? .din_ack (pwmdac_ack), .dacout (pwm_out) ); diff --git a/verilog/speech256_top/speech256_top_tb.v b/verilog/speech256_top/speech256_top_tb.v index 4136d53..a8f19a2 100644 --- a/verilog/speech256_top/speech256_top_tb.v +++ b/verilog/speech256_top/speech256_top_tb.v @@ -31,6 +31,8 @@ module SPEECH256_TOP_TB; initial begin + + `ifdef HELLOWORLD // hello, world allophones[0] = 6'h1B; allophones[1] = 6'h07; @@ -44,7 +46,21 @@ module SPEECH256_TOP_TB; allophones[9] = 6'h15; allophones[10] = 6'h03; allophones[11] = 6'h00; - + `else + // E.T. phone + allophones[0] = 6'h13; + allophones[1] = 6'h02; + allophones[2] = 6'h0D; + allophones[3] = 6'h13; + allophones[4] = 6'h03; + allophones[5] = 6'h00; + allophones[6] = 6'h00; + allophones[7] = 6'h00; + allophones[8] = 6'h00; + allophones[9] = 6'h00; + allophones[10] = 6'h00; + allophones[11] = 6'h00; + `endif fd = $fopen("dacout.sw","wb"); $dumpfile ("speech256_top.vcd"); $dumpvars;