Merge pull request 'tdraudio-pcm' (#3) from tdraudio-pcm into main
Reviewed-on: #3
This commit is contained in:
commit
e295a774d7
15 changed files with 858 additions and 34 deletions
|
|
@ -9,12 +9,13 @@ 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 |- |- |- |- |- |- |p1 |p0 |
|
|_Value_|t |t |t |t |t |t |t |t |- |- |- |- |- |p2 |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
Normal file
104
doc/tdraudio.md
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
# 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.
|
||||||
|
|
@ -97,7 +97,7 @@ Running benchmarks.prog
|
||||||
Arty-A7-35T
|
Arty-A7-35T
|
||||||
76.92MHz, 64KB SRAM, 256MB DRAM,
|
76.92MHz, 64KB SRAM, 256MB DRAM,
|
||||||
16B instruction cache, 16B wt data cache
|
16B instruction cache, 16B wt data cache
|
||||||
running in DRAM (except corelib, stdlib, runtime)
|
running in SRAM
|
||||||
|
|
||||||
Running benchmarks.prog
|
Running benchmarks.prog
|
||||||
empty loop 10M 00:00:07
|
empty loop 10M 00:00:07
|
||||||
|
|
@ -124,7 +124,7 @@ Running benchmarks.prog
|
||||||
Arty-A7-35T
|
Arty-A7-35T
|
||||||
76.92MHz, 64KB SRAM, 256MB DRAM,
|
76.92MHz, 64KB SRAM, 256MB DRAM,
|
||||||
16B instruction cache, 16B wb data cache
|
16B instruction cache, 16B wb data cache
|
||||||
running in DRAM (except corelib, stdlib, runtime)
|
running in SRAM
|
||||||
|
|
||||||
Running benchmarks.prog
|
Running benchmarks.prog
|
||||||
empty loop 10M 00:00:04
|
empty loop 10M 00:00:04
|
||||||
|
|
@ -149,7 +149,7 @@ Running benchmarks.prog
|
||||||
Arty-A7-35T
|
Arty-A7-35T
|
||||||
76.92MHz, 32KB SRAM, 256MB DRAM,
|
76.92MHz, 32KB SRAM, 256MB DRAM,
|
||||||
16B instruction cache, 16B wb data cache
|
16B instruction cache, 16B wb data cache
|
||||||
running in DRAM (except corelib, stdlib, runtime)
|
running in SRAM
|
||||||
|
|
||||||
Running benchmarks.prog
|
Running benchmarks.prog
|
||||||
empty loop 10M 00:00:04
|
empty loop 10M 00:00:04
|
||||||
|
|
@ -169,3 +169,28 @@ Running benchmarks.prog
|
||||||
array copy 128k 1K 00:00:39
|
array copy 128k 1K 00:00:39
|
||||||
exp() 10K 00:00:25
|
exp() 10K 00:00:25
|
||||||
cos() 10K 00:00:05
|
cos() 10K 00:00:05
|
||||||
|
|
||||||
|
--------------------------------------------
|
||||||
|
Arty-A7-35T
|
||||||
|
76.92MHz, 64KB SRAM, 256MB DRAM,
|
||||||
|
16B instruction cache, 16B wb data cache
|
||||||
|
running in DRAM (except corelib, stdlib, runtime)
|
||||||
|
|
||||||
|
Running benchmarks.prog
|
||||||
|
empty loop 10M 00:00:10
|
||||||
|
write variable 10M 00:00:11
|
||||||
|
read variable 10M 00:00:11
|
||||||
|
integer addition 10M 00:00:13
|
||||||
|
real addition 1M 00:00:27
|
||||||
|
integer multiplication 1M 00:00:35
|
||||||
|
real multiplication 1M 00:00:43
|
||||||
|
integer division 1M 00:01:05
|
||||||
|
real division 1M 00:00:51
|
||||||
|
string indexing 1M 00:00:36
|
||||||
|
string iteration 1M 00:00:20
|
||||||
|
new/dispose 1k 1M 00:00:23
|
||||||
|
new/dispose 128k 1M 00:00:23
|
||||||
|
array copy 1k 10K 00:00:03
|
||||||
|
array copy 128k 1K 00:00:48
|
||||||
|
exp() 10K 00:00:28
|
||||||
|
cos() 10K 00:00:04
|
||||||
|
|
|
||||||
47
examples/pcmtest.pas
Normal file
47
examples/pcmtest.pas
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
{$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.
|
||||||
74
examples/pcmtest2.pas
Normal file
74
examples/pcmtest2.pas
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
{$H2560}
|
||||||
|
program pcmtest2;
|
||||||
|
uses pcmaudio;
|
||||||
|
|
||||||
|
var filename:string;
|
||||||
|
buf:SndBufPtr;
|
||||||
|
sampleRate:integer;
|
||||||
|
err:integer;
|
||||||
|
done:boolean;
|
||||||
|
c:char;
|
||||||
|
|
||||||
|
function readAudioFile(fname:string):SndBufPtr;
|
||||||
|
var i,size:integer;
|
||||||
|
c:char;
|
||||||
|
buf:SndBufPtr;
|
||||||
|
f:file;
|
||||||
|
begin
|
||||||
|
open(f, fname, 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);
|
||||||
|
|
||||||
|
readAudioFile := buf;
|
||||||
|
end;
|
||||||
|
|
||||||
|
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 := 32000;
|
||||||
|
|
||||||
|
buf := readAudioFile(filename);
|
||||||
|
|
||||||
|
SampleQStart(buf, sampleRate);
|
||||||
|
|
||||||
|
write('Press ESC to stop> ');
|
||||||
|
done := false;
|
||||||
|
while not done do
|
||||||
|
begin
|
||||||
|
read(c);
|
||||||
|
if c = #27 then
|
||||||
|
begin
|
||||||
|
done := true; writeln(';');
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if c = '?' then
|
||||||
|
begin
|
||||||
|
writeln; writeln('Queue: ', SampleQSize);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
SampleQStop;
|
||||||
|
|
||||||
|
dispose(buf);
|
||||||
|
end.
|
||||||
7
lib/pcmaudio.inc
Normal file
7
lib/pcmaudio.inc
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
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;
|
||||||
247
lib/pcmaudio.s
Normal file
247
lib/pcmaudio.s
Normal file
|
|
@ -0,0 +1,247 @@
|
||||||
|
.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
|
||||||
|
|
||||||
|
; set amplitude out to zero (biased)
|
||||||
|
LOADC AUDIO_BASE+2
|
||||||
|
LOADCP 32768
|
||||||
|
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,6 +1931,12 @@ _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,6 +1844,8 @@ 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
|
||||||
|
|
|
||||||
|
|
@ -70,10 +70,10 @@ set_property -dict {PACKAGE_PIN V14 IOSTANDARD LVCMOS33} [get_ports VGA_VS_O]
|
||||||
#set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { jc[7] }]; #IO_L23N_T3_A02_D18_14 Sch=jc_n[4]
|
#set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { jc[7] }]; #IO_L23N_T3_A02_D18_14 Sch=jc_n[4]
|
||||||
|
|
||||||
## Pmod Header JD
|
## Pmod Header JD
|
||||||
#set_property -dict { PACKAGE_PIN D4 IOSTANDARD LVCMOS33 } [get_ports { jd[0] }]; #IO_L11N_T1_SRCC_35 Sch=jd[1]
|
set_property -dict { PACKAGE_PIN D4 IOSTANDARD LVCMOS33 } [get_ports { amp2_ain }]; #IO_L11N_T1_SRCC_35 Sch=jd[1]
|
||||||
#set_property -dict { PACKAGE_PIN D3 IOSTANDARD LVCMOS33 } [get_ports { jd[1] }]; #IO_L12N_T1_MRCC_35 Sch=jd[2]
|
set_property -dict { PACKAGE_PIN D3 IOSTANDARD LVCMOS33 } [get_ports { amp2_gain }]; #IO_L12N_T1_MRCC_35 Sch=jd[2]
|
||||||
#set_property -dict { PACKAGE_PIN F4 IOSTANDARD LVCMOS33 } [get_ports { jd[2] }]; #IO_L13P_T2_MRCC_35 Sch=jd[3]
|
#set_property -dict { PACKAGE_PIN F4 IOSTANDARD LVCMOS33 } [get_ports { jd[2] }]; #IO_L13P_T2_MRCC_35 Sch=jd[3]
|
||||||
#set_property -dict { PACKAGE_PIN F3 IOSTANDARD LVCMOS33 } [get_ports { jd[3] }]; #IO_L13N_T2_MRCC_35 Sch=jd[4]
|
set_property -dict { PACKAGE_PIN F3 IOSTANDARD LVCMOS33 } [get_ports { amp2_shutdown_n }]; #IO_L13N_T2_MRCC_35 Sch=jd[4]
|
||||||
#set_property -dict { PACKAGE_PIN E2 IOSTANDARD LVCMOS33 } [get_ports { jd[4] }]; #IO_L14P_T2_SRCC_35 Sch=jd[7]
|
#set_property -dict { PACKAGE_PIN E2 IOSTANDARD LVCMOS33 } [get_ports { jd[4] }]; #IO_L14P_T2_SRCC_35 Sch=jd[7]
|
||||||
#set_property -dict { PACKAGE_PIN D2 IOSTANDARD LVCMOS33 } [get_ports { jd[5] }]; #IO_L14N_T2_SRCC_35 Sch=jd[8]
|
#set_property -dict { PACKAGE_PIN D2 IOSTANDARD LVCMOS33 } [get_ports { jd[5] }]; #IO_L14N_T2_SRCC_35 Sch=jd[8]
|
||||||
#set_property -dict { PACKAGE_PIN H2 IOSTANDARD LVCMOS33 } [get_ports { jd[6] }]; #IO_L15P_T2_DQS_35 Sch=jd[9]
|
#set_property -dict { PACKAGE_PIN H2 IOSTANDARD LVCMOS33 } [get_ports { jd[6] }]; #IO_L15P_T2_DQS_35 Sch=jd[9]
|
||||||
|
|
|
||||||
|
|
@ -165,7 +165,7 @@ module dram_bridge #(ADDR_WIDTH = 32, WIDTH = 32)
|
||||||
assign app_wdf_data = { {4{mem_write_data}} };
|
assign app_wdf_data = { {4{mem_write_data}} };
|
||||||
|
|
||||||
assign mem_wait = (dram_read_enable & ~read_inprogress) |
|
assign mem_wait = (dram_read_enable & ~read_inprogress) |
|
||||||
(mem_write_enable & ~dcache_hit & (~app_wdf_rdy | ~app_rdy)) |
|
(mem_write_enable & (~app_wdf_rdy | ~app_rdy)) |
|
||||||
(read_inprogress & ~app_rd_data_valid);
|
(read_inprogress & ~app_rd_data_valid);
|
||||||
|
|
||||||
assign app_en = (dram_read_enable & ~read_inprogress) |
|
assign app_en = (dram_read_enable & ~read_inprogress) |
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
`timescale 1ns / 1ps
|
`timescale 1ns / 1ps
|
||||||
|
|
||||||
module irqctrl #(IRQ_LINES = 2, IRQ_DELAY_WIDTH = 4) (
|
module irqctrl #(IRQ_LINES = 3, IRQ_DELAY_WIDTH = 4) (
|
||||||
input wire clk,
|
input wire clk,
|
||||||
input wire [IRQ_LINES-1:0] irq_in,
|
input wire [IRQ_LINES-1:0] irq_in,
|
||||||
input wire cs,
|
input wire cs,
|
||||||
|
|
|
||||||
262
tridoracpu/tridoracpu.srcs/tdraudio.v
Normal file
262
tridoracpu/tridoracpu.srcs/tdraudio.v
Normal file
|
|
@ -0,0 +1,262 @@
|
||||||
|
`timescale 1ns / 1ps
|
||||||
|
|
||||||
|
// waveform generator module (PCM)
|
||||||
|
module wavegen #(DATA_WIDTH=32, CLOCK_DIV_WIDTH=22,
|
||||||
|
AMP_WIDTH=16, AMP_BIAS=32768) (
|
||||||
|
input wire clk,
|
||||||
|
input wire reset,
|
||||||
|
input wire [1:0] reg_sel,
|
||||||
|
output wire [DATA_WIDTH-1:0] rd_data,
|
||||||
|
input wire [DATA_WIDTH-1:0] wr_data,
|
||||||
|
input wire rd_en,
|
||||||
|
input wire wr_en,
|
||||||
|
|
||||||
|
output wire [AMP_WIDTH-1:0] amp_val,
|
||||||
|
output wire running,
|
||||||
|
output wire irq
|
||||||
|
);
|
||||||
|
|
||||||
|
localparam TDRAU_REG_CTL = 0; /* control register */
|
||||||
|
localparam TDRAU_REG_CLK = 1; /* clock divider register */
|
||||||
|
localparam TDRAU_REG_AMP = 2; /* amplitude (volume) register */
|
||||||
|
|
||||||
|
reg channel_enable;
|
||||||
|
reg [CLOCK_DIV_WIDTH-1:0] clock_div;
|
||||||
|
reg [CLOCK_DIV_WIDTH-1:0] div_count;
|
||||||
|
reg amp_phase;
|
||||||
|
reg [AMP_WIDTH-1:0] amp_out;
|
||||||
|
|
||||||
|
|
||||||
|
wire fifo_wr_en;
|
||||||
|
wire fifo_rd_en, fifo_full, fifo_empty;
|
||||||
|
wire [DATA_WIDTH-1:0] fifo_rd_data;
|
||||||
|
|
||||||
|
fifo #(.ADDR_WIDTH(4), .DATA_WIDTH(16)) sample_buf(
|
||||||
|
clk, reset,
|
||||||
|
fifo_wr_en, fifo_rd_en,
|
||||||
|
wr_data, fifo_rd_data,
|
||||||
|
fifo_full,
|
||||||
|
fifo_empty
|
||||||
|
);
|
||||||
|
|
||||||
|
assign fifo_rd_en = (div_count == 0) && channel_enable && ~fifo_empty;
|
||||||
|
assign fifo_wr_en = wr_en && (reg_sel == TDRAU_REG_AMP);
|
||||||
|
|
||||||
|
reg irq_buf, irq_enable;
|
||||||
|
assign irq = channel_enable && irq_buf;
|
||||||
|
|
||||||
|
reg [DATA_WIDTH-1:0] rd_data_buf;
|
||||||
|
assign rd_data = rd_data_buf;
|
||||||
|
|
||||||
|
assign amp_val = amp_out;
|
||||||
|
assign running = channel_enable;
|
||||||
|
|
||||||
|
wire ctl_reg_write = wr_en && (reg_sel == TDRAU_REG_CTL);
|
||||||
|
|
||||||
|
/* update read data buffer */
|
||||||
|
always @(posedge clk)
|
||||||
|
begin
|
||||||
|
rd_data_buf <= {{DATA_WIDTH-8{1'b0}},
|
||||||
|
{3{1'b0}}, irq_enable, fifo_full, fifo_empty, amp_phase, channel_enable};
|
||||||
|
end
|
||||||
|
|
||||||
|
/* irq signal to interrupt controller */
|
||||||
|
always @(posedge clk)
|
||||||
|
begin
|
||||||
|
if(reset)
|
||||||
|
irq_buf <= 0;
|
||||||
|
else
|
||||||
|
if(fifo_empty && irq_enable)
|
||||||
|
irq_buf <= 1;
|
||||||
|
else
|
||||||
|
irq_buf <= 0;
|
||||||
|
end
|
||||||
|
|
||||||
|
/* interrupt enable flag */
|
||||||
|
always @(posedge clk)
|
||||||
|
begin
|
||||||
|
if(reset)
|
||||||
|
irq_enable <= 0;
|
||||||
|
else
|
||||||
|
if(ctl_reg_write)
|
||||||
|
irq_enable <= wr_data[4];
|
||||||
|
else
|
||||||
|
if(irq_buf)
|
||||||
|
irq_enable <= 0; // disable interrupts after an interrupt
|
||||||
|
end
|
||||||
|
|
||||||
|
/* channel enable flag */
|
||||||
|
always @(posedge clk)
|
||||||
|
begin
|
||||||
|
if(reset)
|
||||||
|
channel_enable <= 0;
|
||||||
|
else if (ctl_reg_write)
|
||||||
|
channel_enable <= wr_data[0];
|
||||||
|
end
|
||||||
|
|
||||||
|
/* clock divider register */
|
||||||
|
always @(posedge clk)
|
||||||
|
begin
|
||||||
|
if(reset)
|
||||||
|
clock_div <= 0;
|
||||||
|
else
|
||||||
|
if (wr_en && (reg_sel == TDRAU_REG_CLK))
|
||||||
|
clock_div <= wr_data;
|
||||||
|
end
|
||||||
|
|
||||||
|
/* divider counter */
|
||||||
|
always @(posedge clk)
|
||||||
|
begin
|
||||||
|
if(channel_enable)
|
||||||
|
begin
|
||||||
|
if(div_count == 0) // reset counter if it reaches zero
|
||||||
|
div_count <= clock_div;
|
||||||
|
else
|
||||||
|
div_count <= div_count - 1; // else just decrement it
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if (wr_en && (reg_sel == TDRAU_REG_CLK)) // when setting divider,
|
||||||
|
div_count <= 1; // start cycle on next clock tick
|
||||||
|
end
|
||||||
|
|
||||||
|
/* amplitude out */
|
||||||
|
always @(posedge clk)
|
||||||
|
begin
|
||||||
|
if (reset)
|
||||||
|
begin
|
||||||
|
amp_out <= AMP_BIAS;
|
||||||
|
amp_phase <= 1;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if (channel_enable)
|
||||||
|
begin
|
||||||
|
if (div_count == 0) // invert amplitude on clock tick
|
||||||
|
begin
|
||||||
|
amp_out <= fifo_rd_data;
|
||||||
|
amp_phase <= ~amp_phase;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
amp_out <= AMP_BIAS;
|
||||||
|
|
||||||
|
// reset phase bit when enabling the channel
|
||||||
|
if (ctl_reg_write && wr_data[0] && ~channel_enable)
|
||||||
|
// when channel is being enabled, phase will be flipped on next tick
|
||||||
|
// because div_count will become zero
|
||||||
|
amp_phase <= 1;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module tdraudio #(DATA_WIDTH=32) (
|
||||||
|
input wire clk,
|
||||||
|
input wire reset,
|
||||||
|
input wire [6:0] io_addr,
|
||||||
|
output wire [DATA_WIDTH-1:0] rd_data,
|
||||||
|
input wire [DATA_WIDTH-1:0] wr_data,
|
||||||
|
input wire rd_en,
|
||||||
|
input wire wr_en,
|
||||||
|
output wire irq_out,
|
||||||
|
output wire pdm_out,
|
||||||
|
output wire gain_sel,
|
||||||
|
output wire shutdown_n
|
||||||
|
);
|
||||||
|
|
||||||
|
localparam CLOCK_DIV_WIDTH = 22;
|
||||||
|
localparam AMP_WIDTH = 16;
|
||||||
|
localparam AMP_BIAS = 32768;
|
||||||
|
localparam DAC_WIDTH = 18;
|
||||||
|
|
||||||
|
wire [4:0] chan_sel = io_addr[6:2];
|
||||||
|
wire [1:0] reg_sel = io_addr[1:0];
|
||||||
|
|
||||||
|
wire [AMP_WIDTH-1:0] chan0_amp;
|
||||||
|
wire [DATA_WIDTH-1:0] chan0_rd_data;
|
||||||
|
wire chan0_running;
|
||||||
|
wire chan0_irq;
|
||||||
|
wire chan0_sel = chan_sel == 5'd0;
|
||||||
|
wire chan0_rd_en = chan0_sel && rd_en;
|
||||||
|
wire chan0_wr_en = chan0_sel && wr_en;
|
||||||
|
|
||||||
|
wire [AMP_WIDTH-1:0] chan1_amp;
|
||||||
|
wire [DATA_WIDTH-1:0] chan1_rd_data;
|
||||||
|
wire chan1_running;
|
||||||
|
wire chan1_irq;
|
||||||
|
wire chan1_sel = chan_sel == 5'd1;
|
||||||
|
wire chan1_rd_en = chan1_sel && rd_en;
|
||||||
|
wire chan1_wr_en = chan1_sel && wr_en;
|
||||||
|
|
||||||
|
wire [AMP_WIDTH-1:0] chan2_amp;
|
||||||
|
wire [DATA_WIDTH-1:0] chan2_rd_data;
|
||||||
|
wire chan2_running;
|
||||||
|
wire chan2_irq;
|
||||||
|
wire chan2_sel = chan_sel == 5'd2;
|
||||||
|
wire chan2_rd_en = chan2_sel && rd_en;
|
||||||
|
wire chan2_wr_en = chan2_sel && wr_en;
|
||||||
|
|
||||||
|
wire [AMP_WIDTH-1:0] chan3_amp;
|
||||||
|
wire [DATA_WIDTH-1:0] chan3_rd_data;
|
||||||
|
wire chan3_running;
|
||||||
|
wire chan3_irq;
|
||||||
|
wire chan3_sel = chan_sel == 5'd3;
|
||||||
|
wire chan3_rd_en = chan3_sel && rd_en;
|
||||||
|
wire chan3_wr_en = chan3_sel && wr_en;
|
||||||
|
|
||||||
|
wire running = chan0_running || chan1_running || chan2_running || chan3_running;
|
||||||
|
|
||||||
|
assign rd_data = chan0_sel ? chan0_rd_data :
|
||||||
|
chan1_sel ? chan1_rd_data :
|
||||||
|
chan2_sel ? chan2_rd_data :
|
||||||
|
chan3_sel ? chan3_rd_data :
|
||||||
|
{DATA_WIDTH{1'b1}};
|
||||||
|
|
||||||
|
wavegen chan0(clk, reset, reg_sel,
|
||||||
|
chan0_rd_data, wr_data,
|
||||||
|
chan0_rd_en, chan0_wr_en,
|
||||||
|
chan0_amp,
|
||||||
|
chan0_running, chan0_irq);
|
||||||
|
|
||||||
|
wavegen chan1(clk, reset, reg_sel,
|
||||||
|
chan1_rd_data, wr_data,
|
||||||
|
chan1_rd_en, chan1_wr_en,
|
||||||
|
chan1_amp,
|
||||||
|
chan1_running, chan1_irq);
|
||||||
|
|
||||||
|
wavegen chan2(clk, reset, reg_sel,
|
||||||
|
chan2_rd_data, wr_data,
|
||||||
|
chan2_rd_en, chan2_wr_en,
|
||||||
|
chan2_amp,
|
||||||
|
chan2_irq, chan2_running);
|
||||||
|
|
||||||
|
wavegen chan3(clk, reset, reg_sel,
|
||||||
|
chan3_rd_data, wr_data,
|
||||||
|
chan3_rd_en, chan3_wr_en,
|
||||||
|
chan3_amp,
|
||||||
|
chan3_running, chan3_irq);
|
||||||
|
|
||||||
|
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
|
||||||
|
assign gain_sel = 1; // gain select: 0 -> 12dB, 1 -> 6dB
|
||||||
|
|
||||||
|
// assign shutdown_n = running;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/* delta-sigma DAC */
|
||||||
|
always @(posedge clk)
|
||||||
|
begin
|
||||||
|
if(reset)
|
||||||
|
deltasigma_acc <= 0;
|
||||||
|
else
|
||||||
|
// if (running)
|
||||||
|
deltasigma_acc <= deltasigma_acc[DAC_WIDTH-1:0] + amp_sum;
|
||||||
|
// else
|
||||||
|
// deltasigma_acc <= deltasigma_acc[DAC_WIDTH-1:0] + (4*AMP_BIAS);
|
||||||
|
end
|
||||||
|
|
||||||
|
/* 1-bit audio output */
|
||||||
|
assign pdm_out = deltasigma_acc[DAC_WIDTH];
|
||||||
|
endmodule
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
//`define clock clk_1hz
|
//`define clock clk_1hz
|
||||||
`define ENABLE_VGAFB
|
`define ENABLE_VGAFB
|
||||||
`define ENABLE_MICROSD
|
`define ENABLE_MICROSD
|
||||||
|
`define ENABLE_TDRAUDIO
|
||||||
|
|
||||||
module top(
|
module top(
|
||||||
input wire clk,
|
input wire clk,
|
||||||
|
|
@ -60,6 +61,13 @@ module top(
|
||||||
output wire sd_sck,
|
output wire sd_sck,
|
||||||
input wire sd_cd
|
input wire sd_cd
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
|
`ifdef ENABLE_TDRAUDIO
|
||||||
|
,
|
||||||
|
output wire amp2_ain,
|
||||||
|
output wire amp2_gain,
|
||||||
|
output wire amp2_shutdown_n
|
||||||
|
`endif
|
||||||
);
|
);
|
||||||
|
|
||||||
reg clk_1hz;
|
reg clk_1hz;
|
||||||
|
|
@ -220,11 +228,35 @@ module top(
|
||||||
assign uart_tx_data = mem_write_data[7:0];
|
assign uart_tx_data = mem_write_data[7:0];
|
||||||
assign uart_rd_data = { {WIDTH-10{1'b1}}, uart_rx_avail, uart_tx_busy, uart_rx_data };
|
assign uart_rd_data = { {WIDTH-10{1'b1}}, uart_rx_avail, uart_tx_busy, uart_rx_data };
|
||||||
|
|
||||||
|
wire audio_irq;
|
||||||
|
`ifdef ENABLE_TDRAUDIO
|
||||||
|
wire [WIDTH-1:0] tdraudio_wr_data;
|
||||||
|
wire [WIDTH-1:0] tdraudio_rd_data;
|
||||||
|
wire tdraudio_rd_en, tdraudio_wr_en;
|
||||||
|
wire tdraudio_irq;
|
||||||
|
|
||||||
|
wire tdraudio_cs_en = io_enable && (io_slot == 4);
|
||||||
|
assign tdraudio_rd_en = tdraudio_cs_en && mem_read_enable;
|
||||||
|
assign tdraudio_wr_en = tdraudio_cs_en && mem_write_enable;
|
||||||
|
assign tdraudio_wr_data = mem_write_data;
|
||||||
|
|
||||||
|
tdraudio tdraudio0(`clock, ~rst,
|
||||||
|
mem_addr[6:0],
|
||||||
|
tdraudio_rd_data,
|
||||||
|
tdraudio_wr_data,
|
||||||
|
tdraudio_rd_en,
|
||||||
|
tdraudio_wr_en,
|
||||||
|
tdraudio_irq,
|
||||||
|
amp2_ain, amp2_gain, amp2_shutdown_n);
|
||||||
|
assign audio_irq = tdraudio_irq;
|
||||||
|
`endif
|
||||||
|
|
||||||
|
// interrupt controller
|
||||||
reg timer_tick;
|
reg timer_tick;
|
||||||
reg[23:0] tick_count;
|
reg[23:0] tick_count;
|
||||||
wire [1:0] irq_in = { timer_tick, uart_rx_avail };
|
wire [2:0] irq_in = { audio_irq, timer_tick, uart_rx_avail };
|
||||||
wire [1:0] irqc_rd_data0;
|
wire [2:0] irqc_rd_data0;
|
||||||
wire [WIDTH-1:0] irqc_rd_data = { tick_count, 6'b0, irqc_rd_data0 };
|
wire [WIDTH-1:0] irqc_rd_data = { tick_count, 5'b0, irqc_rd_data0 };
|
||||||
wire irqc_seten = mem_write_data[7];
|
wire irqc_seten = mem_write_data[7];
|
||||||
wire irqc_cs = io_enable && (io_slot == 3);
|
wire irqc_cs = io_enable && (io_slot == 3);
|
||||||
|
|
||||||
|
|
@ -236,7 +268,9 @@ module top(
|
||||||
(io_slot == 2) ? fb_rd_data :
|
(io_slot == 2) ? fb_rd_data :
|
||||||
`endif
|
`endif
|
||||||
(io_slot == 3) ? irqc_rd_data:
|
(io_slot == 3) ? irqc_rd_data:
|
||||||
|
`ifdef ENABLE_TDRAUDIO
|
||||||
|
(io_slot == 4) ? tdraudio_rd_data:
|
||||||
|
`endif
|
||||||
-1;
|
-1;
|
||||||
|
|
||||||
buart #(.CLKFREQ(`clkfreq)) uart0(`clock, rst,
|
buart #(.CLKFREQ(`clkfreq)) uart0(`clock, rst,
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@
|
||||||
<Attr Name="UsedIn" Val="implementation"/>
|
<Attr Name="UsedIn" Val="implementation"/>
|
||||||
</FileInfo>
|
</FileInfo>
|
||||||
</File>
|
</File>
|
||||||
<File Path="$PSRCDIR/stack.v">
|
<File Path="$PSRCDIR/stack.v" Mode="RelativeOnly">
|
||||||
<FileInfo>
|
<FileInfo>
|
||||||
<Attr Name="UsedIn" Val="synthesis"/>
|
<Attr Name="UsedIn" Val="synthesis"/>
|
||||||
<Attr Name="UsedIn" Val="implementation"/>
|
<Attr Name="UsedIn" Val="implementation"/>
|
||||||
|
|
@ -142,7 +142,7 @@
|
||||||
</FileInfo>
|
</FileInfo>
|
||||||
</File>
|
</File>
|
||||||
<File Path="$PSRCDIR/testbench.v"/>
|
<File Path="$PSRCDIR/testbench.v"/>
|
||||||
<File Path="$PPRDIR/rom.mem">
|
<File Path="$PPRDIR/rom.mem" Mode="RelativeOnly">
|
||||||
<FileInfo>
|
<FileInfo>
|
||||||
<Attr Name="UsedIn" Val="synthesis"/>
|
<Attr Name="UsedIn" Val="synthesis"/>
|
||||||
<Attr Name="UsedIn" Val="simulation"/>
|
<Attr Name="UsedIn" Val="simulation"/>
|
||||||
|
|
@ -173,14 +173,14 @@
|
||||||
<Attr Name="UsedIn" Val="simulation"/>
|
<Attr Name="UsedIn" Val="simulation"/>
|
||||||
</FileInfo>
|
</FileInfo>
|
||||||
</File>
|
</File>
|
||||||
<File Path="$PSRCDIR/bram_tdp.v">
|
<File Path="$PSRCDIR/bram_tdp.v" Mode="RelativeOnly">
|
||||||
<FileInfo>
|
<FileInfo>
|
||||||
<Attr Name="UsedIn" Val="synthesis"/>
|
<Attr Name="UsedIn" Val="synthesis"/>
|
||||||
<Attr Name="UsedIn" Val="implementation"/>
|
<Attr Name="UsedIn" Val="implementation"/>
|
||||||
<Attr Name="UsedIn" Val="simulation"/>
|
<Attr Name="UsedIn" Val="simulation"/>
|
||||||
</FileInfo>
|
</FileInfo>
|
||||||
</File>
|
</File>
|
||||||
<File Path="$PSRCDIR/palette.v">
|
<File Path="$PSRCDIR/palette.v" Mode="RelativeOnly">
|
||||||
<FileInfo>
|
<FileInfo>
|
||||||
<Attr Name="UsedIn" Val="synthesis"/>
|
<Attr Name="UsedIn" Val="synthesis"/>
|
||||||
<Attr Name="UsedIn" Val="implementation"/>
|
<Attr Name="UsedIn" Val="implementation"/>
|
||||||
|
|
@ -205,6 +205,13 @@
|
||||||
<Attr Name="UsedIn" Val="simulation"/>
|
<Attr Name="UsedIn" Val="simulation"/>
|
||||||
</FileInfo>
|
</FileInfo>
|
||||||
</File>
|
</File>
|
||||||
|
<File Path="$PSRCDIR/tdraudio.v">
|
||||||
|
<FileInfo>
|
||||||
|
<Attr Name="UsedIn" Val="synthesis"/>
|
||||||
|
<Attr Name="UsedIn" Val="implementation"/>
|
||||||
|
<Attr Name="UsedIn" Val="simulation"/>
|
||||||
|
</FileInfo>
|
||||||
|
</File>
|
||||||
<Config>
|
<Config>
|
||||||
<Option Name="DesignMode" Val="RTL"/>
|
<Option Name="DesignMode" Val="RTL"/>
|
||||||
<Option Name="TopModule" Val="top"/>
|
<Option Name="TopModule" Val="top"/>
|
||||||
|
|
@ -349,17 +356,12 @@
|
||||||
</Simulator>
|
</Simulator>
|
||||||
</Simulators>
|
</Simulators>
|
||||||
<Runs Version="1" Minor="22">
|
<Runs Version="1" Minor="22">
|
||||||
<Run Id="synth_1" Type="Ft3:Synth" SrcSet="sources_1" Part="xc7a35ticsg324-1L" ConstrsSet="constrs_1" Description="Higher performance designs, resource sharing is turned off, the global fanout guide is set to a lower number, FSM extraction forced to one-hot, LUT combining is disabled, equivalent registers are preserved, SRL are inferred with a larger threshold" AutoIncrementalCheckpoint="false" WriteIncrSynthDcp="false" State="current" Dir="$PRUNDIR/synth_1" IncludeInArchive="true" IsChild="false" AutoIncrementalDir="$PSRCDIR/utils_1/imports/synth_1" AutoRQSDir="$PSRCDIR/utils_1/imports/synth_1" ParallelReportGen="true">
|
<Run Id="synth_1" Type="Ft3:Synth" SrcSet="sources_1" Part="xc7a35ticsg324-1L" ConstrsSet="constrs_1" Description="Vivado Synthesis Defaults" AutoIncrementalCheckpoint="false" WriteIncrSynthDcp="false" State="current" Dir="$PRUNDIR/synth_1" IncludeInArchive="true" IsChild="false" AutoIncrementalDir="$PSRCDIR/utils_1/imports/synth_1" AutoRQSDir="$PSRCDIR/utils_1/imports/synth_1" ParallelReportGen="true">
|
||||||
<Strategy Version="1" Minor="2">
|
<Strategy Version="1" Minor="2">
|
||||||
<StratHandle Name="Flow_PerfOptimized_high" Flow="Vivado Synthesis 2024"/>
|
<StratHandle Name="Vivado Synthesis Defaults" Flow="Vivado Synthesis 2024">
|
||||||
<Step Id="synth_design">
|
<Desc>Vivado Synthesis Defaults</Desc>
|
||||||
<Option Id="Directive">7</Option>
|
</StratHandle>
|
||||||
<Option Id="FsmExtraction">1</Option>
|
<Step Id="synth_design"/>
|
||||||
<Option Id="KeepEquivalentRegisters">1</Option>
|
|
||||||
<Option Id="NoCombineLuts">1</Option>
|
|
||||||
<Option Id="ResourceSharing">2</Option>
|
|
||||||
<Option Id="ShregMinSize">5</Option>
|
|
||||||
</Step>
|
|
||||||
</Strategy>
|
</Strategy>
|
||||||
<GeneratedRun Dir="$PRUNDIR" File="gen_run.xml"/>
|
<GeneratedRun Dir="$PRUNDIR" File="gen_run.xml"/>
|
||||||
<ReportStrategy Name="Vivado Synthesis Default Reports" Flow="Vivado Synthesis 2024"/>
|
<ReportStrategy Name="Vivado Synthesis Default Reports" Flow="Vivado Synthesis 2024"/>
|
||||||
|
|
@ -376,17 +378,30 @@
|
||||||
<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="Default settings for Implementation." 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="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">
|
||||||
<Strategy Version="1" Minor="2">
|
<Strategy Version="1" Minor="2">
|
||||||
<StratHandle Name="Vivado Implementation Defaults" Flow="Vivado Implementation 2024"/>
|
<StratHandle Name="Performance_ExploreWithRemap" Flow="Vivado Implementation 2024">
|
||||||
|
<Desc>Similar to Performance_ExplorePostRoutePhysOpt, but enables logic optimization step (opt_design) with the ExploreWithRemap directive.</Desc>
|
||||||
|
</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>
|
||||||
|
</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">
|
||||||
<Step Id="route_design"/>
|
<Option Id="Directive">0</Option>
|
||||||
<Step Id="post_route_phys_opt_design"/>
|
</Step>
|
||||||
|
<Step Id="route_design">
|
||||||
|
<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 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