Compare commits
No commits in common. "598ee8921ff7c22ca74cd4399ed3e2f799bd06ce" and "7cc9ee807ddf9739e4db5769b8875bc8906a9826" have entirely different histories.
598ee8921f
...
7cc9ee807d
10 changed files with 22 additions and 496 deletions
|
|
@ -9,13 +9,12 @@ The interrupt controller uses a single register at address: $980
|
||||||
|
|
||||||
|_bit_ |15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
|
|_bit_ |15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
|
||||||
|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
|
|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
|
||||||
|_Value_|t |t |t |t |t |t |t |t |- |- |- |- |- |p2 |p1 |p0 |
|
|_Value_|t |t |t |t |t |t |t |t |- |- |- |- |- |- |p1 |p0 |
|
||||||
|
|
||||||
|
|
||||||
|Bitfields|Description|
|
|Bitfields|Description|
|
||||||
|---------|-----------|
|
|---------|-----------|
|
||||||
| _t_ | unsigned 24 bit counter of timer ticks since reset
|
| _t_ | unsigned 24 bit counter of timer ticks since reset
|
||||||
| _p2_ | IRQ 2 (audio) interrupt pending if 1
|
|
||||||
| _p1_ | IRQ 1 (timer tick) interrupt pending if 1
|
| _p1_ | IRQ 1 (timer tick) interrupt pending if 1
|
||||||
| _p0_ | IRQ 0 (UART) interrupt pending if 1
|
| _p0_ | IRQ 0 (UART) interrupt pending if 1
|
||||||
|
|
||||||
|
|
|
||||||
104
doc/tdraudio.md
104
doc/tdraudio.md
|
|
@ -1,104 +0,0 @@
|
||||||
# Audio Controller
|
|
||||||
The audio controller provides four channels of 16-bit PCM audio playback.
|
|
||||||
|
|
||||||
It uses multiple registers starting at address $A00.
|
|
||||||
|
|
||||||
Each of the four channels has three registers.
|
|
||||||
|
|
||||||
For the first channel the register addresses are:
|
|
||||||
|
|
||||||
|Address|Description|
|
|
||||||
|-------|-----------|
|
|
||||||
| $A00 | Control Register |
|
|
||||||
| $A01 | Clock Divider Register |
|
|
||||||
| $A02 | Amplitude Register |
|
|
||||||
|
|
||||||
The register addresses for the second channel start at $A04,
|
|
||||||
the third channel at $A08
|
|
||||||
and the fourth channel at $A0C.
|
|
||||||
|
|
||||||
## Reading the control register
|
|
||||||
|
|
||||||
|_bit_ |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|
|
|
||||||
|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
|
|
||||||
|_Value_|- |- |- |- |- |- |- |- |- |-|- |- |- |- |- |- |
|
|
||||||
|
|
||||||
|_bit_ |15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
|
|
||||||
|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
|
|
||||||
|_Value_|- |- |- |- |- |- |- |- |- |- |- |i |f | e | p | c |
|
|
||||||
|
|
||||||
|
|
||||||
|Bitfields|Description|
|
|
||||||
|---------|-----------|
|
|
||||||
| _i_ | interrupt is enabled for this channel when 1 |
|
|
||||||
| _f_ | sample buffer is full when 1 |
|
|
||||||
| _e_ | sample buffer is empty when 1 |
|
|
||||||
| _p_ | changes from 0 to 1 and vice versa on each sample clock |
|
|
||||||
| _c_ | channel is enabled if 1 |
|
|
||||||
|
|
||||||
## Writing the control register
|
|
||||||
|
|
||||||
|_bit_ |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|
|
|
||||||
|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
|
|
||||||
|_Value_|- |- |- |- |- |- |- |- |- |-|- |- |- |- |- |- |
|
|
||||||
|
|
||||||
|_bit_ |15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
|
|
||||||
|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
|
|
||||||
|_Value_|- |- |- |- |- |- |- |- |- |- |- |i |- | - | - | c |
|
|
||||||
|
|
||||||
|
|
||||||
|Bitfields|Description|
|
|
||||||
|---------|-----------|
|
|
||||||
| _c_ | enable channel if 1, disable if 0 |
|
|
||||||
| _i_ | enable channel interrupt if 1, disable if 0 |
|
|
||||||
|
|
||||||
|
|
||||||
## Writing the clock divider register
|
|
||||||
|
|
||||||
|_bit_ |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|
|
|
||||||
|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
|
|
||||||
|_Value_|d |d |d |d |d |d |d |d |d |d|d |d |d |d |d |d |
|
|
||||||
|
|
||||||
|_bit_ |15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
|
|
||||||
|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
|
|
||||||
|_Value_|d |d |d |d |d |d |d |d |d |d|d |d |d |d |d |d |
|
|
||||||
|
|
||||||
|
|
||||||
|Bitfields|Description|
|
|
||||||
|---------|-----------|
|
|
||||||
| _d_ | an unsigned 32-bit value for the clock divider |
|
|
||||||
|
|
||||||
|
|
||||||
## Writing the amplitude register
|
|
||||||
|
|
||||||
|_bit_ |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|
|
|
||||||
|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
|
|
||||||
|_Value_|- |- |- |- |- |- |- |- |- |-|- |- |- |- |- |- |
|
|
||||||
|
|
||||||
|_bit_ |15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
|
|
||||||
|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
|
|
||||||
|_Value_|a |a |a |a |a |a |a |a |a |a |a |a |a | a | a | a |
|
|
||||||
|
|
||||||
|
|
||||||
|Bitfields|Description|
|
|
||||||
|---------|-----------|
|
|
||||||
| _a_ | an unsigned 16-bit value for the amplitude (sample) value with a bias of 32768 |
|
|
||||||
|
|
||||||
## Notes
|
|
||||||
The clock divider specifies the number of CPU clock ticks between two samples.
|
|
||||||
|
|
||||||
Writing to the amplitude register adds the sample value to the sample buffer. The sample buffer is organized as a FIFO with 16 elements.
|
|
||||||
|
|
||||||
Amplitude (sample) values are represented as unsigned, biased 16-bit numbers. The bias is 32768, so given an amplitude range of 1.0 to -1.0, a 1.0 is represented by 65535, 0.0 by 32768 and -1.0 by 0.
|
|
||||||
|
|
||||||
Interrupt processing needs to be enabled for each channel if required.
|
|
||||||
|
|
||||||
An interrupt on any channel will be signalled to the interrupt controller
|
|
||||||
as IRQ 2. The interrupt service routine should check all running channels
|
|
||||||
for an emtpy buffer.
|
|
||||||
|
|
||||||
If an audio interrupt has occured on a channel, the interrupt enable flag
|
|
||||||
is cleared for that channel. It needs to be re-enabled in the interrupt service routine.
|
|
||||||
|
|
||||||
Interrupts also need to be enabled on the interrupt controller,
|
|
||||||
and re-enabled there after each interrupt.
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
{$H1536}
|
|
||||||
program pcmtest;
|
|
||||||
uses pcmaudio;
|
|
||||||
|
|
||||||
var filename:string;
|
|
||||||
buf:SndBufPtr;
|
|
||||||
f:file;
|
|
||||||
size:integer;
|
|
||||||
i:integer;
|
|
||||||
c:char;
|
|
||||||
sampleRate:integer;
|
|
||||||
err:integer;
|
|
||||||
begin
|
|
||||||
if ParamCount > 0 then
|
|
||||||
filename := ParamStr(1)
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
write('Filename> ');
|
|
||||||
readln(filename);
|
|
||||||
end;
|
|
||||||
|
|
||||||
err := 1;
|
|
||||||
if ParamCount > 1 then
|
|
||||||
val(ParamStr(2),sampleRate, err);
|
|
||||||
|
|
||||||
if err <> 0 then
|
|
||||||
sampleRate := 16000;
|
|
||||||
|
|
||||||
open(f, filename, ModeReadOnly);
|
|
||||||
size := FileSize(f);
|
|
||||||
new(buf, size);
|
|
||||||
|
|
||||||
buf^ := '';
|
|
||||||
write('Reading ', size, ' bytes...');
|
|
||||||
for i := 1 to size do
|
|
||||||
begin
|
|
||||||
read(f,c);
|
|
||||||
AppendChar(buf^,c);
|
|
||||||
end;
|
|
||||||
writeln;
|
|
||||||
|
|
||||||
close(f);
|
|
||||||
|
|
||||||
PlaySample(buf, sampleRate);
|
|
||||||
|
|
||||||
dispose(buf);
|
|
||||||
end.
|
|
||||||
|
|
@ -1,60 +0,0 @@
|
||||||
{$H1536}
|
|
||||||
program pcmtest2;
|
|
||||||
uses pcmaudio;
|
|
||||||
|
|
||||||
var filename:string;
|
|
||||||
buf:SndBufPtr;
|
|
||||||
f:file;
|
|
||||||
size:integer;
|
|
||||||
i:integer;
|
|
||||||
c:char;
|
|
||||||
sampleRate:integer;
|
|
||||||
err:integer;
|
|
||||||
done:boolean;
|
|
||||||
begin
|
|
||||||
if ParamCount > 0 then
|
|
||||||
filename := ParamStr(1)
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
write('Filename> ');
|
|
||||||
readln(filename);
|
|
||||||
end;
|
|
||||||
|
|
||||||
err := 1;
|
|
||||||
if ParamCount > 1 then
|
|
||||||
val(ParamStr(2), sampleRate, err);
|
|
||||||
if err > 0 then
|
|
||||||
sampleRate := 16000;
|
|
||||||
|
|
||||||
open(f, filename, ModeReadOnly);
|
|
||||||
size := FileSize(f);
|
|
||||||
new(buf, size);
|
|
||||||
|
|
||||||
buf^ := '';
|
|
||||||
write('Reading ', size, ' bytes...');
|
|
||||||
for i := 1 to size do
|
|
||||||
begin
|
|
||||||
read(f,c);
|
|
||||||
AppendChar(buf^,c);
|
|
||||||
end;
|
|
||||||
writeln;
|
|
||||||
|
|
||||||
close(f);
|
|
||||||
|
|
||||||
SampleQStart(buf, sampleRate);
|
|
||||||
|
|
||||||
write('Press Q to stop> ');
|
|
||||||
done := false;
|
|
||||||
while not done do
|
|
||||||
begin
|
|
||||||
read(c);
|
|
||||||
if upcase(c) = 'Q' then
|
|
||||||
done := true
|
|
||||||
else
|
|
||||||
writeln('Queue size: ', SampleQSize);
|
|
||||||
end;
|
|
||||||
|
|
||||||
SampleQStop;
|
|
||||||
|
|
||||||
dispose(buf);
|
|
||||||
end.
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
type SndBuf = string[32768];
|
|
||||||
type SndBufPtr = ^SndBuf;
|
|
||||||
|
|
||||||
procedure PlaySample(buf:SndBufPtr;sampleRate:integer); external;
|
|
||||||
procedure SampleQStart(buf:SndBufPtr;sampleRate:integer); external;
|
|
||||||
procedure SampleQStop; external;
|
|
||||||
function SampleQSize:integer; external;
|
|
||||||
241
lib/pcmaudio.s
241
lib/pcmaudio.s
|
|
@ -1,241 +0,0 @@
|
||||||
.EQU AUDIO_BASE $A00
|
|
||||||
.EQU IRQC_REG $980
|
|
||||||
.EQU IRQC_EN $80
|
|
||||||
|
|
||||||
; args: sample rate
|
|
||||||
START_PCMAUDIO:
|
|
||||||
; calculate clock divider
|
|
||||||
LOADCP 77000000
|
|
||||||
SWAP
|
|
||||||
LOADCP _DIV
|
|
||||||
CALL
|
|
||||||
|
|
||||||
LOADC AUDIO_BASE + 1
|
|
||||||
SWAP ; put clock divider on ToS
|
|
||||||
; LOADCP 4812 ; clock divider for 16KHz sample rate
|
|
||||||
; LOADCP 2406 ; clock divider for 32KHz sample rate
|
|
||||||
STOREI 1
|
|
||||||
LOADCP 32768 ; set amplitude to biased 0
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
LOADC AUDIO_BASE
|
|
||||||
LOADC 17 ; enable channel, enable interrupt
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
RET
|
|
||||||
|
|
||||||
STOP_AUDIO:
|
|
||||||
LOADC AUDIO_BASE
|
|
||||||
LOADC 0
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
RET
|
|
||||||
|
|
||||||
; args: pointer to pascal string, sample rate
|
|
||||||
.EQU PS_PTR 0
|
|
||||||
.EQU PS_COUNT 4
|
|
||||||
.EQU PS_FS 12
|
|
||||||
PLAYSAMPLE:
|
|
||||||
FPADJ -PS_FS
|
|
||||||
|
|
||||||
LOADCP START_PCMAUDIO
|
|
||||||
CALL
|
|
||||||
|
|
||||||
DUP
|
|
||||||
LOADI ; get string size from header
|
|
||||||
SHR ; divide by 4 to get word count
|
|
||||||
SHR
|
|
||||||
|
|
||||||
STORE PS_COUNT
|
|
||||||
INC 8 ; skip rest of header
|
|
||||||
STORE PS_PTR ; store sample data pointer
|
|
||||||
|
|
||||||
PS_L0:
|
|
||||||
LOAD PS_PTR ; load pointer
|
|
||||||
INC.S1.X2Y 4 ; increment and keep old value
|
|
||||||
STORE PS_PTR ; store incremented value
|
|
||||||
|
|
||||||
LOADI ; load 32 bit word
|
|
||||||
DUP
|
|
||||||
BROT ; get upper 16 bit word
|
|
||||||
BROT
|
|
||||||
LOADCP $FFFF
|
|
||||||
AND
|
|
||||||
|
|
||||||
LOADCP PLAY_1SAMPLE
|
|
||||||
CALL
|
|
||||||
|
|
||||||
LOADCP $FFFF ; get lower 16 bit word
|
|
||||||
AND
|
|
||||||
LOADCP PLAY_1SAMPLE
|
|
||||||
CALL
|
|
||||||
|
|
||||||
LOAD PS_COUNT ; load word count
|
|
||||||
DEC 1 ; decrement
|
|
||||||
DUP
|
|
||||||
STORE PS_COUNT
|
|
||||||
CBRANCH.NZ PS_L0 ; loop if not zero
|
|
||||||
|
|
||||||
LOADCP STOP_AUDIO
|
|
||||||
CALL
|
|
||||||
|
|
||||||
FPADJ PS_FS
|
|
||||||
RET
|
|
||||||
|
|
||||||
; play one sample, waiting
|
|
||||||
; for the clock divider, which
|
|
||||||
; is visible via the phase flag
|
|
||||||
; args: 16-bit unsigned sample
|
|
||||||
PLAY_1SAMPLE:
|
|
||||||
|
|
||||||
PLAY1_L0:
|
|
||||||
LOADC AUDIO_BASE
|
|
||||||
LOADI
|
|
||||||
LOADC 8 ; get fifo_full flag
|
|
||||||
AND
|
|
||||||
CBRANCH.NZ PLAY1_L0 ; loop if fifo is full
|
|
||||||
|
|
||||||
LOADC AUDIO_BASE+2 ; store amplitude value
|
|
||||||
SWAP
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
RET
|
|
||||||
|
|
||||||
; start interrupt-driven sample playback
|
|
||||||
; args: pointer to pascal string, sample rate
|
|
||||||
SAMPLEQSTART:
|
|
||||||
LOADCP START_PCMAUDIO
|
|
||||||
CALL
|
|
||||||
|
|
||||||
LOADCP SMPLQ_COUNT
|
|
||||||
OVER
|
|
||||||
LOADI ; get string size from header
|
|
||||||
SHR ; divide by 4 to get word count
|
|
||||||
SHR
|
|
||||||
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
|
|
||||||
LOADCP SMPLQ_PTR
|
|
||||||
SWAP
|
|
||||||
INC 8 ; skip rest of header
|
|
||||||
STOREI ; store sample data pointer
|
|
||||||
DROP
|
|
||||||
|
|
||||||
LOADCP SMPLQ_ISR ; set interrupt handler
|
|
||||||
STOREREG IV
|
|
||||||
|
|
||||||
LOADC IRQC_REG ; enable irq
|
|
||||||
LOADC IRQC_EN
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
|
|
||||||
RET
|
|
||||||
|
|
||||||
SAMPLEQSTOP:
|
|
||||||
LOADCP SMPLQ_PTR
|
|
||||||
LOADC 0
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
|
|
||||||
LOADCP STOP_AUDIO
|
|
||||||
CALL
|
|
||||||
|
|
||||||
LOADC IRQC_REG ; disable irq
|
|
||||||
LOADC 0
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
RET
|
|
||||||
|
|
||||||
SAMPLEQSIZE:
|
|
||||||
LOADCP SMPLQ_COUNT
|
|
||||||
LOADI
|
|
||||||
RET
|
|
||||||
|
|
||||||
SMPLQ_PTR: .WORD 0
|
|
||||||
SMPLQ_COUNT: .WORD 0
|
|
||||||
|
|
||||||
SMPLQ_ISR:
|
|
||||||
LOADC IRQC_REG
|
|
||||||
LOADI
|
|
||||||
LOADC 4 ; check for audio interrupt
|
|
||||||
AND
|
|
||||||
CBRANCH.Z SMPLQ_I_XT ; if flag not set, exit
|
|
||||||
|
|
||||||
SMPLQ_I_L:
|
|
||||||
LOADCP SMPLQ_PTR
|
|
||||||
LOADI ; load word pointer
|
|
||||||
DUP
|
|
||||||
CBRANCH.NZ SMPLQ_I_B ; check for null pointer
|
|
||||||
DROP
|
|
||||||
BRANCH SMPLQ_I_XT ; if null, end interrupt routine
|
|
||||||
SMPLQ_I_B:
|
|
||||||
LOADI ; load next word
|
|
||||||
DUP
|
|
||||||
|
|
||||||
BROT ; get high half-word
|
|
||||||
BROT
|
|
||||||
LOADCP $FFFF
|
|
||||||
AND
|
|
||||||
|
|
||||||
LOADC AUDIO_BASE+2
|
|
||||||
SWAP
|
|
||||||
STOREI ; write sample, keep addr
|
|
||||||
|
|
||||||
SWAP ; addr to NoS, lower halfword on ToS
|
|
||||||
LOADCP $FFFF
|
|
||||||
AND
|
|
||||||
STOREI ; write sample
|
|
||||||
DROP
|
|
||||||
|
|
||||||
; decrement word count
|
|
||||||
LOADCP SMPLQ_COUNT
|
|
||||||
LOADI.S1.X2Y ; load counter, keep addr
|
|
||||||
DEC 1
|
|
||||||
DUP
|
|
||||||
CBRANCH.Z SMPLQ_I_END ; end if zero
|
|
||||||
|
|
||||||
STOREI ; store new counter value
|
|
||||||
DROP
|
|
||||||
|
|
||||||
; increment pointer
|
|
||||||
LOADCP SMPLQ_PTR
|
|
||||||
LOADI.S1.X2Y
|
|
||||||
INC 4
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
|
|
||||||
; check if fifo is full
|
|
||||||
LOADC AUDIO_BASE
|
|
||||||
LOADI
|
|
||||||
LOADC 8 ; fifo_full
|
|
||||||
AND
|
|
||||||
CBRANCH.Z SMPLQ_I_L ; next sample if not full
|
|
||||||
|
|
||||||
LOADC AUDIO_BASE
|
|
||||||
LOADC 17 ; re-enable channel interrupt
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
|
|
||||||
BRANCH SMPLQ_I_XT
|
|
||||||
|
|
||||||
; end playback, set ptr and counter to zero
|
|
||||||
SMPLQ_I_END:
|
|
||||||
DROP
|
|
||||||
DROP
|
|
||||||
LOADCP SMPLQ_PTR
|
|
||||||
LOADC 0
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
LOADCP SMPLQ_COUNT
|
|
||||||
LOADC 0
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
|
|
||||||
SMPLQ_I_XT:
|
|
||||||
LOADC IRQC_REG ; re-enable interrupts
|
|
||||||
LOADC IRQC_EN
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
LOADREG IR ; jump via interrupt return register
|
|
||||||
JUMP
|
|
||||||
|
|
@ -1931,12 +1931,6 @@ _CLEARESTACK_XT:
|
||||||
; Terminate program: clear estack and
|
; Terminate program: clear estack and
|
||||||
; jump to coreloader
|
; jump to coreloader
|
||||||
PTERM:
|
PTERM:
|
||||||
; just to be safe, disable interrupts
|
|
||||||
LOADC $980
|
|
||||||
LOADC 0
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
|
|
||||||
LOADCP _CLEARESTACK
|
LOADCP _CLEARESTACK
|
||||||
CALL
|
CALL
|
||||||
LOADCP LOADER_START
|
LOADCP LOADER_START
|
||||||
|
|
|
||||||
|
|
@ -1844,8 +1844,6 @@ end;
|
||||||
|
|
||||||
function filesize(var fil:file):integer;
|
function filesize(var fil:file):integer;
|
||||||
begin
|
begin
|
||||||
checkerror(fil);
|
|
||||||
|
|
||||||
if fil.typ = IOChannel then
|
if fil.typ = IOChannel then
|
||||||
filesize := -1
|
filesize := -1
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -42,12 +42,12 @@ module wavegen #(DATA_WIDTH=32, CLOCK_DIV_WIDTH=22,
|
||||||
assign fifo_rd_en = (div_count == 0) && channel_enable && ~fifo_empty;
|
assign fifo_rd_en = (div_count == 0) && channel_enable && ~fifo_empty;
|
||||||
assign fifo_wr_en = wr_en && (reg_sel == TDRAU_REG_AMP);
|
assign fifo_wr_en = wr_en && (reg_sel == TDRAU_REG_AMP);
|
||||||
|
|
||||||
reg irq_buf, irq_enable;
|
reg irq_buf, irq_done;
|
||||||
assign irq = channel_enable && irq_buf;
|
assign irq = irq_buf;
|
||||||
|
|
||||||
reg [DATA_WIDTH-1:0] rd_data_buf;
|
reg [DATA_WIDTH-1:0] rd_data_buf;
|
||||||
assign rd_data = rd_data_buf;
|
assign rd_data = rd_data_buf;
|
||||||
|
// assign rd_data = {{DATA_WIDTH-8{1'b0}}, {4{1'b0}}, fifo_full, fifo_empty, amp_phase, channel_enable};
|
||||||
assign amp_val = amp_out;
|
assign amp_val = amp_out;
|
||||||
assign running = channel_enable;
|
assign running = channel_enable;
|
||||||
|
|
||||||
|
|
@ -56,8 +56,7 @@ module wavegen #(DATA_WIDTH=32, CLOCK_DIV_WIDTH=22,
|
||||||
/* update read data buffer */
|
/* update read data buffer */
|
||||||
always @(posedge clk)
|
always @(posedge clk)
|
||||||
begin
|
begin
|
||||||
rd_data_buf <= {{DATA_WIDTH-8{1'b0}},
|
rd_data_buf <= {{DATA_WIDTH-8{1'b0}}, {4{1'b0}}, fifo_full, fifo_empty, amp_phase, channel_enable};
|
||||||
{3{1'b0}}, irq_enable, fifo_full, fifo_empty, amp_phase, channel_enable};
|
|
||||||
end
|
end
|
||||||
|
|
||||||
/* irq signal to interrupt controller */
|
/* irq signal to interrupt controller */
|
||||||
|
|
@ -66,23 +65,23 @@ module wavegen #(DATA_WIDTH=32, CLOCK_DIV_WIDTH=22,
|
||||||
if(reset)
|
if(reset)
|
||||||
irq_buf <= 0;
|
irq_buf <= 0;
|
||||||
else
|
else
|
||||||
if(fifo_empty && irq_enable)
|
if(fifo_empty && ~irq_done)
|
||||||
irq_buf <= 1;
|
irq_buf <= 1;
|
||||||
else
|
else
|
||||||
irq_buf <= 0;
|
irq_buf <= 0;
|
||||||
end
|
end
|
||||||
|
|
||||||
/* interrupt enable flag */
|
/* interrupt done flag, used to ensure the irq signal is set for just one clock tick */
|
||||||
always @(posedge clk)
|
always @(posedge clk)
|
||||||
begin
|
begin
|
||||||
if(reset)
|
if(reset)
|
||||||
irq_enable <= 0;
|
irq_done <= 0;
|
||||||
else
|
else
|
||||||
if(ctl_reg_write)
|
if(rd_en) // reset irq done flag on any register read
|
||||||
irq_enable <= wr_data[4];
|
irq_done <= 0;
|
||||||
else
|
else
|
||||||
if(irq_buf)
|
if(irq_buf)
|
||||||
irq_enable <= 0; // disable interrupts after an interrupt
|
irq_done <= 1;
|
||||||
end
|
end
|
||||||
|
|
||||||
/* channel enable flag */
|
/* channel enable flag */
|
||||||
|
|
@ -140,8 +139,8 @@ module wavegen #(DATA_WIDTH=32, CLOCK_DIV_WIDTH=22,
|
||||||
amp_out <= AMP_BIAS;
|
amp_out <= AMP_BIAS;
|
||||||
|
|
||||||
// reset phase bit when enabling the channel
|
// reset phase bit when enabling the channel
|
||||||
if (ctl_reg_write && wr_data[0] && ~channel_enable)
|
if (ctl_reg_write && wr_data[0])
|
||||||
// when channel is being enabled, phase will be flipped on next tick
|
// when channel is enabled, phase will be flipped on next tick
|
||||||
// because div_count will become zero
|
// because div_count will become zero
|
||||||
amp_phase <= 1;
|
amp_phase <= 1;
|
||||||
end
|
end
|
||||||
|
|
@ -233,6 +232,9 @@ module tdraudio #(DATA_WIDTH=32) (
|
||||||
chan3_amp,
|
chan3_amp,
|
||||||
chan3_running, chan3_irq);
|
chan3_running, chan3_irq);
|
||||||
|
|
||||||
|
reg irq_out_buf;
|
||||||
|
assign irq_out = irq_out_buf;
|
||||||
|
|
||||||
reg [DAC_WIDTH:0] deltasigma_acc; // one extra bit
|
reg [DAC_WIDTH:0] deltasigma_acc; // one extra bit
|
||||||
wire [DAC_WIDTH:0] amp_sum = chan0_amp + chan1_amp + chan2_amp + chan3_amp; // also one overflow bit here
|
wire [DAC_WIDTH:0] amp_sum = chan0_amp + chan1_amp + chan2_amp + chan3_amp; // also one overflow bit here
|
||||||
assign gain_sel = 1; // gain select: 0 -> 12dB, 1 -> 6dB
|
assign gain_sel = 1; // gain select: 0 -> 12dB, 1 -> 6dB
|
||||||
|
|
@ -240,9 +242,6 @@ module tdraudio #(DATA_WIDTH=32) (
|
||||||
// assign shutdown_n = running;
|
// assign shutdown_n = running;
|
||||||
assign shutdown_n = 1; /* don't enable shutdown mode, it creates a mains hum */
|
assign shutdown_n = 1; /* don't enable shutdown mode, it creates a mains hum */
|
||||||
|
|
||||||
reg irq_out_buf;
|
|
||||||
assign irq_out = irq_out_buf;
|
|
||||||
|
|
||||||
always @(posedge clk) irq_out_buf <= chan0_irq || chan1_irq || chan2_irq || chan3_irq;
|
always @(posedge clk) irq_out_buf <= chan0_irq || chan1_irq || chan2_irq || chan3_irq;
|
||||||
|
|
||||||
/* delta-sigma DAC */
|
/* delta-sigma DAC */
|
||||||
|
|
|
||||||
|
|
@ -378,18 +378,16 @@
|
||||||
<Report Name="ROUTE_DESIGN.REPORT_METHODOLOGY" Enabled="1"/>
|
<Report Name="ROUTE_DESIGN.REPORT_METHODOLOGY" Enabled="1"/>
|
||||||
<RQSFiles/>
|
<RQSFiles/>
|
||||||
</Run>
|
</Run>
|
||||||
<Run Id="impl_1" Type="Ft2:EntireDesign" Part="xc7a35ticsg324-1L" ConstrsSet="constrs_1" Description="Similar to Performance_ExplorePostRoutePhysOpt, but enables logic optimization step (opt_design) with the ExploreWithRemap directive." AutoIncrementalCheckpoint="false" WriteIncrSynthDcp="false" State="current" Dir="$PRUNDIR/impl_1" SynthRun="synth_1" IncludeInArchive="true" IsChild="false" GenFullBitstream="true" AutoIncrementalDir="$PSRCDIR/utils_1/imports/impl_1" LaunchOptions="-jobs 6 " AutoRQSDir="$PSRCDIR/utils_1/imports/impl_1" ParallelReportGen="true">
|
<Run Id="impl_1" Type="Ft2:EntireDesign" Part="xc7a35ticsg324-1L" ConstrsSet="constrs_1" Description="Includes alternate algorithms for timing-driven optimization" AutoIncrementalCheckpoint="false" WriteIncrSynthDcp="false" State="current" Dir="$PRUNDIR/impl_1" SynthRun="synth_1" IncludeInArchive="true" IsChild="false" GenFullBitstream="true" AutoIncrementalDir="$PSRCDIR/utils_1/imports/impl_1" LaunchOptions="-jobs 6 " AutoRQSDir="$PSRCDIR/utils_1/imports/impl_1" ParallelReportGen="true">
|
||||||
<Strategy Version="1" Minor="2">
|
<Strategy Version="1" Minor="2">
|
||||||
<StratHandle Name="Performance_ExploreWithRemap" Flow="Vivado Implementation 2024">
|
<StratHandle Name="Performance_ExtraTimingOpt" Flow="Vivado Implementation 2024">
|
||||||
<Desc>Similar to Performance_ExplorePostRoutePhysOpt, but enables logic optimization step (opt_design) with the ExploreWithRemap directive.</Desc>
|
<Desc>Includes alternate algorithms for timing-driven optimization</Desc>
|
||||||
</StratHandle>
|
</StratHandle>
|
||||||
<Step Id="init_design"/>
|
<Step Id="init_design"/>
|
||||||
<Step Id="opt_design">
|
<Step Id="opt_design"/>
|
||||||
<Option Id="Directive">6</Option>
|
|
||||||
</Step>
|
|
||||||
<Step Id="power_opt_design"/>
|
<Step Id="power_opt_design"/>
|
||||||
<Step Id="place_design">
|
<Step Id="place_design">
|
||||||
<Option Id="Directive">0</Option>
|
<Option Id="Directive">8</Option>
|
||||||
</Step>
|
</Step>
|
||||||
<Step Id="post_place_power_opt_design"/>
|
<Step Id="post_place_power_opt_design"/>
|
||||||
<Step Id="phys_opt_design">
|
<Step Id="phys_opt_design">
|
||||||
|
|
@ -397,11 +395,8 @@
|
||||||
</Step>
|
</Step>
|
||||||
<Step Id="route_design">
|
<Step Id="route_design">
|
||||||
<Option Id="Directive">1</Option>
|
<Option Id="Directive">1</Option>
|
||||||
<Option Id="MoreOptsStr"><![CDATA[-tns_cleanup]]></Option>
|
|
||||||
</Step>
|
|
||||||
<Step Id="post_route_phys_opt_design" EnableStepBool="1">
|
|
||||||
<Option Id="Directive">0</Option>
|
|
||||||
</Step>
|
</Step>
|
||||||
|
<Step Id="post_route_phys_opt_design"/>
|
||||||
<Step Id="write_bitstream">
|
<Step Id="write_bitstream">
|
||||||
<Option Id="BinFile">1</Option>
|
<Option Id="BinFile">1</Option>
|
||||||
</Step>
|
</Step>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue