diff --git a/verilog/controller/controller.v b/verilog/controller/controller.v index b1bc7c5..315fd11 100644 --- a/verilog/controller/controller.v +++ b/verilog/controller/controller.v @@ -16,6 +16,7 @@ module CONTROLLER ( amp_out, // amplitude output coeff_out, // 8-bit coefficient data out coeff_stb, // '1' when coeff_out holds new coefficient data + clear_states, // outputs '1' to reset filter states period_done_in // should be '1' when the source finished a period ); @@ -26,6 +27,7 @@ module CONTROLLER ( input rst_an; //////////// OUTPUTS ////////// + output reg clear_states; output reg ldq; output reg coeff_stb; output reg signed [9:0] coeff_out; @@ -165,13 +167,14 @@ module CONTROLLER ( if (serve_pitch_data) begin duration <= dur_tmp; - amp_out <= {4'b0000, amp_tmp[15:4]}; + //amp_out <= {4'b0000, amp_tmp[15:4]}; + amp_out <= {amp_tmp[13:0],2'b00}; period_out <= period_tmp; end if (set_ldq == 1) ldq <= 1; - else if (reset_ldq == 1) + else if (data_stb == 1) ldq <= 0; if ((period_done_in == 1) && (!serve_next_allo_data)) @@ -243,25 +246,29 @@ module CONTROLLER ( dur_load <= 0; allo_load <= 0; load_cur_cmd <= 0; - set_ldq <= 0; - reset_ldq <= 0; + set_ldq <= 0; + clear_states <= 0; + serve_pitch_data <= 0; dur_cnt_clear <= 0; case (cur_state) S_IDLE: begin - set_ldq <= 1; if (serve_next_allo_data == 1) begin - // we've run out of allophone data .. + // we've run out of allophone data .. end if (data_stb == 1) begin allo_load <= 1; + //reset_ldq <= 1; next_state <= S_JMPADDR1; - end - rom_addr_sel <= ROM_ADDR_ZERO; + end + else + set_ldq <= 1; + + rom_addr_sel <= ROM_ADDR_ZERO; end S_JMPADDR1: begin @@ -285,7 +292,6 @@ module CONTROLLER ( // perform jmp rom_addr_sel <= ROM_ADDR_JMP; next_state <= S_CMDDECODE; - reset_ldq <= 1; end S_CMDDECODE: begin @@ -334,7 +340,16 @@ module CONTROLLER ( begin serve_pitch_data <= 1; dur_cnt_clear <= 1; - next_state <= (cur_cmd == 4'd2) ? S_LOADCOEF1 : S_CMDDECODE; + if (cur_cmd == 4'd2) + begin + clear_states <= 1; + next_state <= S_LOADCOEF1; + end + else + begin + next_state <= S_CMDDECODE; + end + end end S_LOADCOEF1: diff --git a/verilog/controller/controller_tb.v b/verilog/controller/controller_tb.v index a9e7534..2a2c343 100644 --- a/verilog/controller/controller_tb.v +++ b/verilog/controller/controller_tb.v @@ -11,6 +11,7 @@ module CONTROLLER_TB; reg [5:0] data_in; reg data_stb, serve_next; reg period_done; + wire clear_states; wire ldq; wire [9:0] coeff; @@ -29,6 +30,7 @@ module CONTROLLER_TB; .amp_out (amp), .coeff_out (coeff), .coeff_stb (coeff_load), + .clear_states (clear_states), .period_done_in (period_done) ); diff --git a/verilog/controller/xlat.v b/verilog/controller/xlat.v index e66c0d8..20011b0 100644 --- a/verilog/controller/xlat.v +++ b/verilog/controller/xlat.v @@ -24,7 +24,7 @@ module XLAT ( output reg [9:0] c10_out; wire sign; - assign sign = c8_in[7]; + assign sign = ~c8_in[7]; always@(*) begin diff --git a/verilog/filter/filter.v b/verilog/filter/filter.v index 1b2ff39..53661cd 100644 --- a/verilog/filter/filter.v +++ b/verilog/filter/filter.v @@ -20,7 +20,7 @@ module FILTER ( // coefficient loading interface coef_in, // 10 bit sign-magnitude coefficient coef_load, // pulse '1' to load the coefficient into the internal register - + clear_states, // set to '1' to reset internal filter states // signal I/O and handshaking sig_in, // 16-bit (scaled) source input signal sig_out, // 16-bit filter output signal @@ -39,6 +39,7 @@ module FILTER ( input signed [15:0] sig_in; input signed [9:0] coef_in; input start, coef_load; + input clear_states; // zero all states //////////// FILTER OUTPUTS ////////// output wire signed [15:0] sig_out; @@ -56,7 +57,7 @@ module FILTER ( reg do_accu; // if 1, the accumulator is updated reg double_mode; // if 1, the input to the accumulator is x2 reg update_states; // shift the state registers - reg clear_states; // zero all states + reg update_coeffs; // shift the coefficient registers reg [3:0] cur_state; // current FSM state reg [3:0] next_state; // next FSM state diff --git a/verilog/filter/filter_tb.v b/verilog/filter/filter_tb.v index efed501..9b872dc 100644 --- a/verilog/filter/filter_tb.v +++ b/verilog/filter/filter_tb.v @@ -6,7 +6,7 @@ // module FILTER_TB; - reg clk, rst_an, start, coef_load, check_finish; + reg clk, rst_an, start, coef_load, check_finish, clear_states; reg signed [15:0] sig_in; reg signed [9:0] coef_in; reg [3:0] reg_sel; @@ -22,6 +22,7 @@ module FILTER_TB; .rst_an (rst_an), .coef_in (coef_in), .coef_load (coef_load), + .clear_states (clear_states), .sig_in (sig_in), .sig_out (sig_out), .start (start), @@ -41,6 +42,7 @@ module FILTER_TB; coef_in = 0; coef_load = 0; start = 0; + clear_states = 0; check_finish = 0; #10 @@ -52,29 +54,29 @@ module FILTER_TB; #10 coef_load = 1; // section 1 - coef_in = 10'h3C9; + coef_in = 10'h1C9; #10 - coef_in = 10'h1E4; + coef_in = 10'h3E4; #10 // section 2 - coef_in = 10'h2B8; + coef_in = 10'h0B8; #10 - coef_in = 10'h1CF; + coef_in = 10'h3CF; #10 // section 3 - coef_in = 10'h238; + coef_in = 10'h038; #10 - coef_in = 10'h080; + coef_in = 10'h280; #10 // section 4 - coef_in = 10'h195; + coef_in = 10'h395; #10 - coef_in = 10'h1BF; + coef_in = 10'h3BF; #10 // section 5 - coef_in = 10'h135; + coef_in = 10'h335; #10 - coef_in = 10'h1BF; + coef_in = 10'h3BF; #10 // section 6 coef_in = 10'h000; @@ -118,7 +120,7 @@ module FILTER_TB; #10 coef_load = 0; start = 1; - #10000; + #20000; check_finish = 1; end diff --git a/verilog/speech256_top/speech256_top.v b/verilog/speech256_top/speech256_top.v index d36cb22..b76d63e 100644 --- a/verilog/speech256_top/speech256_top.v +++ b/verilog/speech256_top/speech256_top.v @@ -7,12 +7,14 @@ // module SPEECH256_TOP ( - clk, // global Speech256 clock + clk, // global Speech256 clock (256*10kHz) rst_an, ldq, // load request, is high when new allophone can be loaded data_in, // allophone input data_stb, // allophone strobe input - dac_out, // 1-bit PWM DAC output + pwm_out, // 1-bit PWM DAC output + sample_out, + sample_stb ); //////////// CLOCK ////////// @@ -22,8 +24,10 @@ module SPEECH256_TOP ( input rst_an; //////////// OUTPUTS ////////// - output dac_out; + output pwm_out; output ldq; + output signed [15:0] sample_out; + output sample_stb; //////////// INPUTS ////////// input [5:0] data_in; @@ -35,6 +39,7 @@ module SPEECH256_TOP ( wire signed [15:0] sig_source; wire signed [15:0] sig_filter; wire period_done; + wire clear_states; wire [7:0] period; wire [7:0] dur; @@ -60,6 +65,7 @@ module SPEECH256_TOP ( .rst_an (rst_an), .coef_in (coef_bus), .coef_load (coef_load), + .clear_states (clear_states), .sig_in (sig_source), .sig_out (sig_filter), .start (pwmdac_ack), @@ -71,7 +77,7 @@ module SPEECH256_TOP ( .rst_an (rst_an), .din (sig_filter[15:8]), .din_ack (pwmdac_ack), - .dacout (dac_out) + .dacout (pwm_out) ); CONTROLLER u_controller ( @@ -84,9 +90,13 @@ module SPEECH256_TOP ( .amp_out (amp), .coeff_out (coef_bus), .coeff_stb (coef_load), + .clear_states (clear_states), .period_done_in (period_done) ); + assign sample_out = sig_filter[15:0]; + assign sample_stb = src_strobe; + always @(posedge clk, negedge rst_an) begin if (rst_an == 0) diff --git a/verilog/speech256_top/speech256_top_tb.v b/verilog/speech256_top/speech256_top_tb.v index 53d3a50..4136d53 100644 --- a/verilog/speech256_top/speech256_top_tb.v +++ b/verilog/speech256_top/speech256_top_tb.v @@ -9,7 +9,12 @@ module SPEECH256_TOP_TB; reg clk, rst_an; reg [5:0] data_in; reg data_stb; - wire ldq,dac_out; + wire sample_stb; + wire signed [15:0] sample_out; + wire ldq,pwm_out; + + reg [7:0] allophones[0:10]; + reg [3:0] allo_idx; SPEECH256_TOP u_speech256_top ( .clk (clk), @@ -17,34 +22,65 @@ module SPEECH256_TOP_TB; .ldq (ldq), .data_in (data_in), .data_stb (data_stb), - .dac_out (dac_out) + .pwm_out (pwm_out), + .sample_out (sample_out), + .sample_stb (sample_stb) ); integer fd; // file descriptor initial begin + // hello, world + allophones[0] = 6'h1B; + allophones[1] = 6'h07; + allophones[2] = 6'h2D; + allophones[3] = 6'h35; + allophones[4] = 6'h03; + allophones[5] = 6'h2E; + allophones[6] = 6'h1E; + allophones[7] = 6'h33; + allophones[8] = 6'h2D; + allophones[9] = 6'h15; + allophones[10] = 6'h03; + allophones[11] = 6'h00; + fd = $fopen("dacout.sw","wb"); $dumpfile ("speech256_top.vcd"); $dumpvars; clk = 0; rst_an = 0; - data_stb = 0; + allo_idx = 0; #5 - rst_an = 1; - #5 - data_in = 7; - data_stb = 1; - #5 - data_stb = 0; - #300000 + rst_an <= 1; + //#5 + //#9000000 //$fclose(fd); - $finish; + //$finish; end + reg last_sample_stb; always @(posedge clk) - begin - $fwrite(fd,"%u", {31'd0,dac_out}); + begin + // check for new output sample + if ((sample_stb == 1) && (last_sample_stb != sample_stb)) + begin + $fwrite(fd,"%u", $signed( {sample_out, 16'h0000} )); + end + last_sample_stb <= sample_stb; + + // check for next allophone + if ((ldq == 1) && (data_stb == 0)) + begin + data_stb <= 1; + data_in <= allophones[allo_idx]; + $display("Allophone %d", allo_idx); + allo_idx <= allo_idx + 1; + if (allo_idx == 11) + $finish; + end + else + data_stb <= 0; end always