Added hex display drivers to the DE0 board so it will display the allophone codes while playing.

This commit is contained in:
Niels Moseley 2017-10-27 01:26:35 +02:00
parent 1c293f13e8
commit f82d3c74df
8 changed files with 235 additions and 27 deletions

View File

@ -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

View File

@ -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),
@ -123,6 +142,7 @@ module Speech256_DE0 (
// allophone ROM
// 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

View File

@ -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

View File

@ -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)
//
// 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;

View File

@ -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;
@ -91,6 +91,11 @@ module SOURCE (
source_out <= {1'b0, amplitude};
else
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;

View File

@ -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)
);

View File

@ -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)
);

View File

@ -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;