mirror of
https://github.com/trcwm/Speech256.git
synced 2025-06-07 16:48:32 +02:00
non-working top level
This commit is contained in:
parent
2f89161c65
commit
704cd3d4cb
357
verilog/controller/controller.v
Normal file
357
verilog/controller/controller.v
Normal file
@ -0,0 +1,357 @@
|
||||
//
|
||||
// Speecht256 top level
|
||||
//
|
||||
// Niels Moseley - Moseley Instruments 2017
|
||||
// http://www.moseleyinstruments.com
|
||||
//
|
||||
//
|
||||
|
||||
module CONTROLLER (
|
||||
clk, // global Speech256 clock
|
||||
rst_an,
|
||||
ldq, // load request, is high when new allophone can be loaded
|
||||
data_in, // allophone input
|
||||
data_stb, // allophone strobe input
|
||||
period_out, // pitch period output
|
||||
amp_out, // amplitude output
|
||||
coeff_out, // 8-bit coefficient data out
|
||||
coeff_stb, // '1' when coeff_out holds new coefficient data
|
||||
period_done_in // should be '1' when the source finished a period
|
||||
);
|
||||
|
||||
//////////// CLOCK //////////
|
||||
input clk;
|
||||
|
||||
//////////// RESET, ACTIVE LOW //////////
|
||||
input rst_an;
|
||||
|
||||
//////////// OUTPUTS //////////
|
||||
output reg ldq;
|
||||
output reg coeff_stb;
|
||||
output reg signed [7:0] coeff_out;
|
||||
output reg [15:0] amp_out;
|
||||
output reg [7:0] period_out;
|
||||
//output reg [7:0] dur_out;
|
||||
|
||||
//////////// INPUTS //////////
|
||||
input [5:0] data_in;
|
||||
input data_stb;
|
||||
input source_stb_in;
|
||||
input period_done_in; // used for duration counting
|
||||
|
||||
// internal counter and data registers
|
||||
wire [7:0] rom_data;
|
||||
reg [11:0] rom_addr;
|
||||
reg [11:0] last_rom_addr;
|
||||
reg [2:0] rom_addr_sel;
|
||||
reg rom_en;
|
||||
|
||||
reg [3:0] jmpmsb;
|
||||
reg jmpmsb_load;
|
||||
|
||||
reg [5:0] cur_allo;
|
||||
reg [3:0] cur_cmd;
|
||||
|
||||
reg [3:0] cur_state;
|
||||
reg [3:0] next_state;
|
||||
|
||||
reg [5:0] data_in_buf;
|
||||
|
||||
reg amp1_load, amp2_load;
|
||||
reg period_load;
|
||||
reg dur_load;
|
||||
reg allo_load;
|
||||
reg load_cur_cmd;
|
||||
reg serve_pitch_data;
|
||||
reg set_ldq, reset_ldq;
|
||||
reg dur_cnt_clear;
|
||||
wire serve_next_allo_data;
|
||||
|
||||
reg [15:0] amp_tmp;
|
||||
reg [7:0] period_tmp;
|
||||
reg [7:0] dur_tmp;
|
||||
reg [7:0] duration;
|
||||
reg [7:0] dur_cnt;
|
||||
|
||||
reg [2:0] coeff_cnt;
|
||||
reg [1:0] coeff_cnt_update;
|
||||
|
||||
wire done;
|
||||
|
||||
CTRLROM u_ctrlrom (
|
||||
.clk (clk),
|
||||
.data (rom_data),
|
||||
.addr (rom_addr),
|
||||
.en (rom_en)
|
||||
);
|
||||
|
||||
parameter ROM_ADDR_ZERO = 3'b000, // zero the ROM address
|
||||
ROM_ADDR_INC = 3'b001, // increment the ROM address
|
||||
ROM_ADDR_JMP = 3'b010, // jump to code
|
||||
ROM_ADDR_ALLO = 3'b011, // read allophone jump address
|
||||
ROM_ADDR_NOP = 3'b100;
|
||||
|
||||
parameter COEFF_CNT_ZERO = 2'b00, // zero coefficient counter
|
||||
COEFF_CNT_NOP = 2'b01, // do nothing
|
||||
COEFF_CNT_INC = 2'b10; // increment coefficient counter
|
||||
|
||||
always @(posedge clk, negedge rst_an)
|
||||
begin
|
||||
if (rst_an == 0)
|
||||
begin
|
||||
// reset values
|
||||
amp_out <= 0;
|
||||
period_out <= 8'd1;
|
||||
rom_en <= 1;
|
||||
rom_addr <= 0;
|
||||
last_rom_addr <= 0;
|
||||
cur_state <= 0;
|
||||
cur_allo <= 0;
|
||||
cur_cmd <= 0;
|
||||
coeff_stb <= 0;
|
||||
coeff_out <= 0;
|
||||
coeff_cnt <= 0;
|
||||
jmpmsb <= 0;
|
||||
ldq <= 0;
|
||||
dur_cnt <= 0;
|
||||
duration <= 0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
// clocked process
|
||||
cur_state <= next_state;
|
||||
|
||||
case (coeff_cnt_update)
|
||||
COEFF_CNT_ZERO:
|
||||
coeff_cnt <= 0;
|
||||
COEFF_CNT_NOP:
|
||||
coeff_cnt <= coeff_cnt;
|
||||
COEFF_CNT_INC:
|
||||
coeff_cnt <= coeff_cnt + 1;
|
||||
default:
|
||||
coeff_cnt <= 0;
|
||||
endcase
|
||||
|
||||
if (jmpmsb_load)
|
||||
jmpmsb <= rom_data[3:0];
|
||||
|
||||
if (amp1_load)
|
||||
amp_tmp[7:0] <= rom_data;
|
||||
|
||||
if (amp2_load)
|
||||
amp_tmp[15:8] <= rom_data;
|
||||
|
||||
if (period_load)
|
||||
period_tmp <= rom_data;
|
||||
|
||||
if (dur_load)
|
||||
dur_tmp <= rom_data;
|
||||
|
||||
if (allo_load)
|
||||
cur_allo <= data_in;
|
||||
|
||||
if (load_cur_cmd)
|
||||
cur_cmd <= rom_data[3:0];
|
||||
|
||||
if (serve_pitch_data)
|
||||
begin
|
||||
duration <= dur_tmp;
|
||||
amp_out <= amp_tmp;
|
||||
period_out <= period_tmp;
|
||||
end
|
||||
|
||||
if (set_ldq == 1)
|
||||
ldq <= 1;
|
||||
else if (reset_ldq == 1)
|
||||
ldq <= 0;
|
||||
|
||||
if ((period_done_in == 1) && (!serve_next_allo_data))
|
||||
begin
|
||||
dur_cnt <= dur_cnt + 1;
|
||||
end
|
||||
|
||||
if (dur_cnt_clear)
|
||||
begin
|
||||
dur_cnt <= 0;
|
||||
end
|
||||
|
||||
last_rom_addr <= rom_addr;
|
||||
end
|
||||
end
|
||||
|
||||
assign serve_next_allo_data = (dur_cnt == duration) ? 1 : 0;
|
||||
|
||||
parameter S_IDLE = 4'd0,
|
||||
S_JMPADDR1 = 4'd1,
|
||||
S_JMPADDR2 = 4'd2,
|
||||
S_JMPADDR3 = 4'd3,
|
||||
S_CMDLOAD = 4'd4,
|
||||
S_CMDDECODE= 4'd5,
|
||||
S_LOADAMP1 = 4'd6,
|
||||
S_LOADAMP2 = 4'd7,
|
||||
S_LOADDUR = 4'd8,
|
||||
S_LOADPERIOD= 4'd9,
|
||||
S_SERVEGATE = 4'd10,
|
||||
S_LOADCOEF1 = 4'd11,
|
||||
S_LOADCOEF2 = 4'd12;
|
||||
|
||||
always @(*)
|
||||
begin
|
||||
// rom address multiplexer
|
||||
case (rom_addr_sel)
|
||||
ROM_ADDR_ZERO:
|
||||
rom_addr <= 0;
|
||||
ROM_ADDR_INC:
|
||||
rom_addr <= last_rom_addr + 1;
|
||||
ROM_ADDR_JMP:
|
||||
rom_addr <= {jmpmsb, rom_data[7:0]};
|
||||
ROM_ADDR_ALLO:
|
||||
rom_addr <= {5'b00000, cur_allo, 1'b0};
|
||||
ROM_ADDR_NOP:
|
||||
rom_addr <= last_rom_addr;
|
||||
default:
|
||||
rom_addr <= 0;
|
||||
endcase
|
||||
end
|
||||
|
||||
always @(*)
|
||||
begin
|
||||
// ---------------------------------------------
|
||||
// -------- MAIN FINITE STATE MACHINE ----------
|
||||
// ---------------------------------------------
|
||||
|
||||
// FSM defaults:
|
||||
rom_addr_sel <= ROM_ADDR_INC;
|
||||
coeff_cnt_update <= COEFF_CNT_NOP;
|
||||
|
||||
next_state <= cur_state;
|
||||
|
||||
coeff_stb <= 0;
|
||||
jmpmsb_load <= 0;
|
||||
amp1_load <= 0;
|
||||
amp2_load <= 0;
|
||||
period_load <= 0;
|
||||
dur_load <= 0;
|
||||
allo_load <= 0;
|
||||
load_cur_cmd <= 0;
|
||||
set_ldq <= 0;
|
||||
reset_ldq <= 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 ..
|
||||
end
|
||||
if (data_stb == 1)
|
||||
begin
|
||||
allo_load <= 1;
|
||||
next_state <= S_JMPADDR1;
|
||||
end
|
||||
rom_addr_sel <= ROM_ADDR_ZERO;
|
||||
end
|
||||
S_JMPADDR1:
|
||||
begin
|
||||
// get MSB of allophone address code
|
||||
rom_addr_sel <= ROM_ADDR_ALLO;
|
||||
next_state <= S_JMPADDR2;
|
||||
end
|
||||
S_JMPADDR2:
|
||||
begin
|
||||
// get LSB of allophone address code
|
||||
jmpmsb_load <= 1;
|
||||
rom_addr_sel <= ROM_ADDR_INC;
|
||||
next_state <= S_CMDLOAD;
|
||||
end
|
||||
S_JMPADDR3:
|
||||
begin
|
||||
next_state <= S_CMDLOAD;
|
||||
end
|
||||
S_CMDLOAD:
|
||||
begin
|
||||
// perform jmp
|
||||
rom_addr_sel <= ROM_ADDR_JMP;
|
||||
next_state <= S_CMDDECODE;
|
||||
reset_ldq <= 1;
|
||||
end
|
||||
S_CMDDECODE:
|
||||
begin
|
||||
// current command and
|
||||
// terminate sequencer if
|
||||
// CMD == 0xF
|
||||
if (rom_data == 4'hF)
|
||||
next_state <= S_IDLE; // end of command
|
||||
else
|
||||
begin
|
||||
rom_addr_sel <= ROM_ADDR_INC;
|
||||
next_state <= S_LOADAMP1;
|
||||
end
|
||||
load_cur_cmd <= 1;
|
||||
//cur_cmd <= rom_data;
|
||||
end
|
||||
S_LOADAMP1: // load 16-bit AMP
|
||||
begin
|
||||
amp1_load <= 1;
|
||||
rom_addr_sel <= ROM_ADDR_INC;
|
||||
next_state <= S_LOADAMP2;
|
||||
end
|
||||
S_LOADAMP2:
|
||||
begin
|
||||
amp2_load <= 1;
|
||||
rom_addr_sel <= ROM_ADDR_INC;
|
||||
next_state <= S_LOADDUR;
|
||||
end
|
||||
S_LOADDUR:
|
||||
begin
|
||||
dur_load <= 1;
|
||||
rom_addr_sel <= ROM_ADDR_INC;
|
||||
next_state <= S_LOADPERIOD;
|
||||
end
|
||||
S_LOADPERIOD:
|
||||
begin
|
||||
period_load <= 1;
|
||||
coeff_cnt_update <= COEFF_CNT_ZERO;
|
||||
rom_addr_sel <= ROM_ADDR_INC;
|
||||
next_state <= S_SERVEGATE;
|
||||
end
|
||||
S_SERVEGATE:
|
||||
begin
|
||||
rom_addr_sel <= ROM_ADDR_NOP;
|
||||
if (serve_next_allo_data == 1)
|
||||
begin
|
||||
serve_pitch_data <= 1;
|
||||
dur_cnt_clear <= 1;
|
||||
next_state <= (cur_cmd == 4'd2) ? S_LOADCOEF1 : S_CMDDECODE;
|
||||
end
|
||||
end
|
||||
S_LOADCOEF1:
|
||||
// send F coefficient
|
||||
begin
|
||||
coeff_stb <= 1;
|
||||
coeff_out <= rom_data;
|
||||
coeff_cnt_update <= COEFF_CNT_INC;
|
||||
rom_addr_sel <= ROM_ADDR_INC;
|
||||
next_state <= S_LOADCOEF2;
|
||||
end
|
||||
S_LOADCOEF2:
|
||||
// send B coefficient
|
||||
begin
|
||||
coeff_stb <= 1;
|
||||
coeff_out <= rom_data;
|
||||
if (coeff_cnt == 3'd6)
|
||||
next_state <= S_CMDDECODE; // load next section
|
||||
else
|
||||
next_state <= S_LOADCOEF1; // next command
|
||||
|
||||
rom_addr_sel <= ROM_ADDR_INC;
|
||||
end
|
||||
default:
|
||||
next_state <= S_IDLE;
|
||||
endcase
|
||||
end
|
||||
|
||||
endmodule
|
64
verilog/controller/controller_tb.v
Normal file
64
verilog/controller/controller_tb.v
Normal file
@ -0,0 +1,64 @@
|
||||
//
|
||||
// PWMDAC testbench
|
||||
//
|
||||
// Niels Moseley - Moseley Instruments 2017
|
||||
// http://www.moseleyinstruments.com
|
||||
//
|
||||
|
||||
module CONTROLLER_TB;
|
||||
reg clk, rst_an;
|
||||
|
||||
reg [5:0] data_in;
|
||||
reg data_stb, serve_next;
|
||||
reg period_done;
|
||||
|
||||
wire ldq;
|
||||
wire signed [7:0] coeff;
|
||||
wire coeff_load;
|
||||
wire [7:0] period;
|
||||
wire [15:0] amp;
|
||||
wire [7:0] dur;
|
||||
|
||||
CONTROLLER u_controller (
|
||||
.clk (clk),
|
||||
.rst_an (rst_an),
|
||||
.ldq (ldq),
|
||||
.data_in (data_in),
|
||||
.data_stb (data_stb),
|
||||
.period_out (period),
|
||||
.amp_out (amp),
|
||||
.coeff_out (coeff),
|
||||
.coeff_stb (coeff_load),
|
||||
.period_done_in (period_done)
|
||||
);
|
||||
|
||||
initial
|
||||
begin
|
||||
$dumpfile ("controller.vcd");
|
||||
$dumpvars;
|
||||
clk = 0;
|
||||
rst_an = 0;
|
||||
data_in = 6;
|
||||
data_stb = 0;
|
||||
period_done = 0;
|
||||
#5
|
||||
rst_an = 1;
|
||||
#5
|
||||
// load allophone
|
||||
data_stb = 1;
|
||||
#10
|
||||
data_stb = 0;
|
||||
serve_next = 1;
|
||||
#300000
|
||||
$finish;
|
||||
end
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
;
|
||||
end
|
||||
|
||||
always
|
||||
#5 clk = !clk;
|
||||
|
||||
endmodule
|
3995
verilog/controller/ctrlrom.hex
Normal file
3995
verilog/controller/ctrlrom.hex
Normal file
File diff suppressed because it is too large
Load Diff
4018
verilog/controller/ctrlrom.v
Normal file
4018
verilog/controller/ctrlrom.v
Normal file
File diff suppressed because it is too large
Load Diff
117
verilog/controller/genctrlrom.py
Normal file
117
verilog/controller/genctrlrom.py
Normal file
@ -0,0 +1,117 @@
|
||||
#
|
||||
# Generate control rom for Speech256 project
|
||||
#
|
||||
# Copyright N.A. Moseley 2017 / Moseley Instruments
|
||||
#
|
||||
# The control rom is in a slightly different format
|
||||
# than we need for the Verilog code, so in addition
|
||||
# to making a ROM directry, we massage it a bit...
|
||||
#
|
||||
|
||||
VerilogHeader = """
|
||||
// This file was auto-generated,
|
||||
// do not modify by hand!
|
||||
|
||||
module CTRLROM (
|
||||
clk,
|
||||
en,
|
||||
addr,
|
||||
data
|
||||
);
|
||||
input clk;
|
||||
input en;
|
||||
input [11:0] addr;
|
||||
output reg [7:0] data;
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
if (en)
|
||||
case(addr)
|
||||
"""
|
||||
|
||||
VerilogFooter = """ default: data <= 8'bXXXXXXXX;
|
||||
endcase
|
||||
end
|
||||
endmodule
|
||||
"""
|
||||
|
||||
RomAddress = 0;
|
||||
|
||||
def emitRomByte(b):
|
||||
global RomAddress
|
||||
global fout
|
||||
fout.write(" 12'd"+str(RomAddress)+": data <= 8'd" + str(b) + ";\n")
|
||||
RomAddress = RomAddress + 1;
|
||||
|
||||
def convertFilterCoeff(c):
|
||||
# turn c into negative 8-bit number
|
||||
# 1 -> 255
|
||||
# 2 -> 254
|
||||
# 255 -> 1
|
||||
# 254 -> 2
|
||||
# 128 -> xxx
|
||||
# 0 -> 0
|
||||
if (c == 0):
|
||||
return 0
|
||||
|
||||
return (256-c);
|
||||
|
||||
fout = open('ctrlrom.v','wt')
|
||||
|
||||
with open('ctrlrom.hex', 'r') as fp:
|
||||
hex_list = fp.readlines()
|
||||
|
||||
|
||||
cmd_list = [int(c,16) for c in hex_list];
|
||||
|
||||
# generate header
|
||||
fout.write(VerilogHeader)
|
||||
|
||||
# generate jump table
|
||||
for I in range(0,0x7E):
|
||||
emitRomByte(cmd_list[I])
|
||||
|
||||
counter = 0x7E
|
||||
while (counter < len(cmd_list)):
|
||||
cmd = cmd_list[counter];
|
||||
if (cmd == 0): # JUMP INSTRUCTION
|
||||
print("?")
|
||||
elif (cmd == 1): # SET AMP AND PITCH
|
||||
emitRomByte(cmd)
|
||||
emitRomByte(cmd_list[counter+1]) # AMP LSB
|
||||
emitRomByte(cmd_list[counter+2]) # AMP MSB
|
||||
emitRomByte(cmd_list[counter+3]) # DUR
|
||||
emitRomByte(cmd_list[counter+4]) # PITCH
|
||||
counter = counter + 4
|
||||
#print("SET AMP+PITCH")
|
||||
elif (cmd == 2): # SET COEFFICIENTS
|
||||
emitRomByte(cmd)
|
||||
emitRomByte(cmd_list[counter+1]) # AMP LSB
|
||||
emitRomByte(cmd_list[counter+2]) # AMP MSB
|
||||
emitRomByte(cmd_list[counter+3]) # DUR
|
||||
emitRomByte(cmd_list[counter+4]) # PITCH
|
||||
emitRomByte(convertFilterCoeff(cmd_list[counter+10])) # F6
|
||||
emitRomByte(convertFilterCoeff(cmd_list[counter+10+6])) # B6
|
||||
emitRomByte(convertFilterCoeff(cmd_list[counter+9])) # F5
|
||||
emitRomByte(convertFilterCoeff(cmd_list[counter+9+6])) # B5
|
||||
emitRomByte(convertFilterCoeff(cmd_list[counter+8])) # F4
|
||||
emitRomByte(convertFilterCoeff(cmd_list[counter+8+6])) # B4
|
||||
emitRomByte(convertFilterCoeff(cmd_list[counter+7])) # F3
|
||||
emitRomByte(convertFilterCoeff(cmd_list[counter+7+6])) # B3
|
||||
emitRomByte(convertFilterCoeff(cmd_list[counter+6])) # F2
|
||||
emitRomByte(convertFilterCoeff(cmd_list[counter+6+6])) # B2
|
||||
emitRomByte(convertFilterCoeff(cmd_list[counter+5])) # F1
|
||||
emitRomByte(convertFilterCoeff(cmd_list[counter+5+6])) # B1
|
||||
counter = counter + 4 + 12
|
||||
#print("SET COEFFS")
|
||||
elif (cmd == 15): # SET COEFFICIENTS: # END OF COMMAND / 15
|
||||
emitRomByte(cmd)
|
||||
else:
|
||||
print("*** ERROR ***")
|
||||
break
|
||||
counter = counter + 1
|
||||
|
||||
# generate footer
|
||||
fout.write(VerilogFooter)
|
||||
|
||||
fout.close()
|
7
verilog/controller/run_tb.bat
Normal file
7
verilog/controller/run_tb.bat
Normal file
@ -0,0 +1,7 @@
|
||||
python genctrlrom.py
|
||||
mkdir bin
|
||||
del bin\controller.vvp
|
||||
C:\iverilog\bin\iverilog -o bin\controller.vvp -m va_math -g2005 -s CONTROLLER_TB controller.v controller_tb.v ctrlrom.v
|
||||
cd bin
|
||||
C:\iverilog\bin\vvp controller.vvp -lxt2
|
||||
cd ..
|
@ -148,7 +148,7 @@ module FILTER (
|
||||
if (do_accu)
|
||||
begin
|
||||
if (double_mode)
|
||||
accu <= accu_in +{mul_result[14:0], 1'b0};
|
||||
accu <= accu_in + {mul_result[14:0], 1'b0};
|
||||
else
|
||||
accu <= accu_in + mul_result;
|
||||
end
|
||||
|
@ -12,9 +12,9 @@
|
||||
module PWMDAC (
|
||||
clk,
|
||||
rst_an,
|
||||
din,
|
||||
din_ack,
|
||||
dacout
|
||||
din, // 16 bit signed data input
|
||||
din_ack, // is high for 1 clock cycle after reading the din signal
|
||||
dacout // 1-bit PWM output signal
|
||||
);
|
||||
|
||||
//////////// CLOCK //////////
|
||||
|
@ -12,6 +12,7 @@ module SOURCE (
|
||||
period, // period in 10kHz samples
|
||||
amplitude, // unsigned 15-bit desired amplitude of source output
|
||||
strobe, // when strobe == '1' a new source_out will be generated
|
||||
period_done, // is set to '1' at the end of the period
|
||||
source_out // signed 16-bit source output
|
||||
);
|
||||
|
||||
@ -23,6 +24,7 @@ module SOURCE (
|
||||
|
||||
//////////// OUTPUTS //////////
|
||||
output reg signed [15:0] source_out;
|
||||
output reg period_done;
|
||||
|
||||
//////////// INPUTS //////////
|
||||
input [14:0] amplitude;
|
||||
@ -32,6 +34,7 @@ module SOURCE (
|
||||
// internal counter and data registers
|
||||
reg signed [7:0] periodcnt;
|
||||
reg [16:0] lfsr;
|
||||
reg last_strobe;
|
||||
|
||||
always @(posedge clk, negedge rst_an)
|
||||
begin
|
||||
@ -39,12 +42,17 @@ module SOURCE (
|
||||
begin
|
||||
// reset values
|
||||
periodcnt <= 0;
|
||||
period_done <= 1;
|
||||
source_out <= 0;
|
||||
last_strobe <= 0;
|
||||
lfsr <= 17'h1; //note: never reset the LFSR to zero!
|
||||
end
|
||||
else
|
||||
begin
|
||||
if (strobe == 1)
|
||||
// default value
|
||||
period_done <= 0;
|
||||
|
||||
if ((strobe == 1) && (last_strobe == 0))
|
||||
begin
|
||||
// if period == 0, we need to generate noise
|
||||
// else we generate a pulse wave
|
||||
@ -54,7 +62,10 @@ module SOURCE (
|
||||
// LFSR NOISE GENERATOR
|
||||
// ------------------------------------------------------------
|
||||
if (periodcnt == 64)
|
||||
begin
|
||||
periodcnt <= 0;
|
||||
period_done <= 1;
|
||||
end
|
||||
else
|
||||
periodcnt <= periodcnt + 1;
|
||||
|
||||
@ -69,7 +80,10 @@ module SOURCE (
|
||||
// ------------------------------------------------------------
|
||||
// make periodcnt count from 0 .. period-1
|
||||
if (periodcnt == period)
|
||||
begin
|
||||
periodcnt <= 0;
|
||||
period_done <= 1;
|
||||
end
|
||||
else
|
||||
periodcnt <= periodcnt + 1;
|
||||
|
||||
@ -79,6 +93,7 @@ module SOURCE (
|
||||
source_out <= 16'h0000;
|
||||
end
|
||||
end
|
||||
last_strobe <= strobe;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -13,6 +13,7 @@ module SOURCE_TB;
|
||||
reg [7:0] cnt;
|
||||
|
||||
wire signed [15:0] source_out;
|
||||
wire period_done;
|
||||
|
||||
SOURCE u_source (
|
||||
.clk (clk),
|
||||
@ -20,6 +21,7 @@ module SOURCE_TB;
|
||||
.period (period),
|
||||
.amplitude (amp),
|
||||
.strobe (strobe),
|
||||
.period_done (period_done)
|
||||
.source_out (source_out)
|
||||
);
|
||||
|
||||
|
6
verilog/speech256_top/run_tb.bat
Normal file
6
verilog/speech256_top/run_tb.bat
Normal file
@ -0,0 +1,6 @@
|
||||
mkdir bin
|
||||
del bin\speech256_top.vvp
|
||||
C:\iverilog\bin\iverilog -o bin\speech256_top.vvp -m va_math -g2005 -s SPEECH256_TOP_TB speech256_top.v speech256_top_tb.v ..\filter\filter.v ..\source\source.v ..\spmul\spmul.v ..\pwmdac\pwmdac.v ..\controller\controller.v ..\controller\ctrlrom.v
|
||||
cd bin
|
||||
C:\iverilog\bin\vvp speech256_top.vvp -lxt2
|
||||
cd ..
|
102
verilog/speech256_top/speech256_top.v
Normal file
102
verilog/speech256_top/speech256_top.v
Normal file
@ -0,0 +1,102 @@
|
||||
//
|
||||
// Speecht256 top level
|
||||
//
|
||||
// Niels Moseley - Moseley Instruments 2017
|
||||
// http://www.moseleyinstruments.com
|
||||
//
|
||||
//
|
||||
|
||||
module SPEECH256_TOP (
|
||||
clk, // global Speech256 clock
|
||||
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
|
||||
);
|
||||
|
||||
//////////// CLOCK //////////
|
||||
input clk;
|
||||
|
||||
//////////// RESET, ACTIVE LOW //////////
|
||||
input rst_an;
|
||||
|
||||
//////////// OUTPUTS //////////
|
||||
output dac_out;
|
||||
output ldq;
|
||||
|
||||
//////////// INPUTS //////////
|
||||
input [5:0] data_in;
|
||||
input data_stb;
|
||||
|
||||
|
||||
// internal counter and data registers
|
||||
wire pwmdac_ack, src_strobe;
|
||||
wire signed [15:0] sig_source;
|
||||
wire signed [15:0] sig_filter;
|
||||
wire period_done;
|
||||
|
||||
wire [7:0] period;
|
||||
wire [7:0] dur;
|
||||
wire [15:0] amp;
|
||||
|
||||
wire signed [7:0] coef_bus;
|
||||
wire coef_load;
|
||||
|
||||
wire done;
|
||||
|
||||
SOURCE u_source (
|
||||
.clk (clk),
|
||||
.rst_an (rst_an),
|
||||
.period (period),
|
||||
.amplitude (amp[14:0]),
|
||||
.strobe (src_strobe),
|
||||
.period_done (period_done),
|
||||
.source_out (sig_source)
|
||||
);
|
||||
|
||||
FILTER u_filter (
|
||||
.clk (clk),
|
||||
.rst_an (rst_an),
|
||||
.coef_in ({coef_bus, 1'b0}),
|
||||
.coef_load (coef_load),
|
||||
.sig_in (sig_source),
|
||||
.sig_out (sig_filter),
|
||||
.start (pwmdac_ack),
|
||||
.done (src_strobe)
|
||||
);
|
||||
|
||||
PWMDAC u_pwmdac (
|
||||
.clk (clk),
|
||||
.rst_an (rst_an),
|
||||
.din (sig_filter[15:8]),
|
||||
.din_ack (pwmdac_ack),
|
||||
.dacout (dac_out)
|
||||
);
|
||||
|
||||
CONTROLLER u_controller (
|
||||
.clk (clk),
|
||||
.rst_an (rst_an),
|
||||
.ldq (ldq),
|
||||
.data_in (data_in),
|
||||
.data_stb (data_stb),
|
||||
.period_out (period),
|
||||
.amp_out (amp),
|
||||
.coeff_out (coef_bus),
|
||||
.coeff_stb (coef_load),
|
||||
.period_done_in (period_done)
|
||||
);
|
||||
|
||||
always @(posedge clk, negedge rst_an)
|
||||
begin
|
||||
if (rst_an == 0)
|
||||
begin
|
||||
// reset values
|
||||
end
|
||||
else
|
||||
begin
|
||||
// clocked process
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
53
verilog/speech256_top/speech256_top_tb.v
Normal file
53
verilog/speech256_top/speech256_top_tb.v
Normal file
@ -0,0 +1,53 @@
|
||||
//
|
||||
// PWMDAC testbench
|
||||
//
|
||||
// Niels Moseley - Moseley Instruments 2017
|
||||
// http://www.moseleyinstruments.com
|
||||
//
|
||||
|
||||
module SPEECH256_TOP_TB;
|
||||
reg clk, rst_an;
|
||||
reg [5:0] data_in;
|
||||
reg data_stb;
|
||||
wire ldq,dac_out;
|
||||
|
||||
SPEECH256_TOP u_speech256_top (
|
||||
.clk (clk),
|
||||
.rst_an (rst_an),
|
||||
.ldq (ldq),
|
||||
.data_in (data_in),
|
||||
.data_stb (data_stb),
|
||||
.dac_out (dac_out)
|
||||
);
|
||||
|
||||
integer fd; // file descriptor
|
||||
|
||||
initial
|
||||
begin
|
||||
fd = $fopen("dacout.sw","wb");
|
||||
$dumpfile ("speech256_top.vcd");
|
||||
$dumpvars;
|
||||
clk = 0;
|
||||
rst_an = 0;
|
||||
data_stb = 0;
|
||||
#5
|
||||
rst_an = 1;
|
||||
#5
|
||||
data_in = 6;
|
||||
data_stb = 1;
|
||||
#5
|
||||
data_stb = 0;
|
||||
#300000
|
||||
//$fclose(fd);
|
||||
$finish;
|
||||
end
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
$fwrite(fd,"%u", {31'd0,dac_out});
|
||||
end
|
||||
|
||||
always
|
||||
#5 clk = !clk;
|
||||
|
||||
endmodule
|
Loading…
x
Reference in New Issue
Block a user