diff --git a/README.md b/README.md
index 758c36b..fe930a7 100644
--- a/README.md
+++ b/README.md
@@ -81,7 +81,7 @@ on the emulator image.
- the [Hackaday project](https://hackaday.io/project/198324-tridora-cpu) (mostly copy-paste from this README)
- the [YouTube channel](https://www.youtube.com/@tridoracpu/videos) with some demo videos
- the [emulator](https://git.insignificance.de/slederer/-/packages/generic/tridoraemu/0.0.5/files/12) (source and windows binary)
-- the [FPGA bitstream](https://git.insignificance.de/slederer/-/packages/generic/tdr-bitstream/0.0.3/files/15) for the Arty-A7-35T board
+- the [FPGA bitstream](https://git.insignificance.de/slederer/-/packages/generic/tdr-bitstream/0.0.4/files/16) for the Arty-A7-35T board
- an [SD-card image](https://git.insignificance.de/slederer/-/packages/generic/tdr-cardimage/0.0.4/files/13)
Contact the author here: tridoracpu [at] insignificance.de
diff --git a/examples/fastfire.inc b/examples/fastfire.inc
new file mode 100644
index 0000000..bf0dce6
--- /dev/null
+++ b/examples/fastfire.inc
@@ -0,0 +1,5 @@
+const FIREWIDTH = 319; FIREHEIGHT = 79; (* keep in sync with fastfire.s! *)
+type FireBuf = array [0..FIREHEIGHT, 0..FIREWIDTH] of integer;
+
+procedure FastFireUpdate(var f:FireBuf); external;
+procedure FastFireDraw(var f:FireBuf;screenx, screeny:integer); external;
diff --git a/examples/fastfire.s b/examples/fastfire.s
new file mode 100644
index 0000000..f0e10e4
--- /dev/null
+++ b/examples/fastfire.s
@@ -0,0 +1,326 @@
+ ; width and height of the fire cell matrix
+ ; Be sure to sync this with fastfire.inc!
+ .EQU FIREWIDTH 319
+ .EQU FIREHEIGHT 79
+
+ ;
+ ; The cell matrix actually has one column
+ ; and one row more than FIREWIDTH and
+ ; FIREHEIGHT to handle the negative
+ ; X offsets when calculating new
+ ; cell values.
+ ; Likewise, there is one more row.
+ ; So rows are processed from 0 to FIREHEIGHT - 2
+ ; and columms from 1 to FIREWIDTH - 1.
+
+ ; cells considered for calculating new
+ ; value for cell O (reference cells):
+ ; .....O......
+ ; ....123.....
+ ; .....4......
+
+; args: pointer to fire cell buffer
+ .EQU FF_ROW_COUNT 0
+ .EQU FF_COL_COUNT 4
+ .EQU FF_ROW_OFFS 8
+ .EQU FF_OFFS1 12
+ .EQU FF_OFFS2 16
+ .EQU FF_OFFS3 20
+ .EQU FF_OFFS4 24
+ .EQU FF_CELL_PTR 28
+ .EQU FF_FS 32
+FASTFIREUPDATE:
+ FPADJ -FF_FS
+ STORE FF_CELL_PTR
+ LOADC FIREHEIGHT-1
+ STORE FF_ROW_COUNT
+
+ ; calculate offsets for reference cells
+ LOADC FIREWIDTH+1
+ SHL 2
+ DUP
+ STORE FF_ROW_OFFS ; offset to next row: WIDTH*4
+ DEC 4 ; offset to cell 1: row offset - 4
+ DUP
+ STORE FF_OFFS1
+ INC 4
+ DUP
+ STORE FF_OFFS2 ; offset to cell 2: + 4
+ INC 4
+ STORE FF_OFFS3 ; offset to cell 3: + 4
+ LOAD FF_ROW_OFFS
+ SHL 1 ; offset to cell 4: row offset * 2
+ STORE FF_OFFS4
+
+ ; start at column 1
+ LOAD FF_CELL_PTR
+ INC 4
+ STORE FF_CELL_PTR
+FF_ROW:
+ LOADC FIREWIDTH-1
+ STORE FF_COL_COUNT
+
+FF_COL:
+ LOAD FF_CELL_PTR
+ LOAD FF_OFFS1
+ ADD
+ LOADI
+
+ LOAD FF_CELL_PTR
+ LOAD FF_OFFS2
+ ADD
+ LOADI
+
+ LOAD FF_CELL_PTR
+ LOAD FF_OFFS3
+ ADD
+ LOADI
+
+ LOAD FF_CELL_PTR
+ LOAD FF_OFFS4
+ ADD
+ LOADI
+
+ ADD
+ ADD
+ ADD
+
+ SHR
+ SHR
+
+ ; if new cell value > 0, subtract 1 to cool down
+ DUP
+ CBRANCH.Z FF_SKIP
+ DEC 1
+FF_SKIP:
+ LOAD FF_CELL_PTR ; load cell ptr
+ SWAP ; swap with new value
+ STOREI 4 ; store with postincrement
+ STORE FF_CELL_PTR ; save new ptr value
+
+ LOAD FF_COL_COUNT ; decrement column count
+ DEC 1
+ DUP
+ STORE FF_COL_COUNT
+ CBRANCH.NZ FF_COL ; loop if col count <> 0
+
+ ; at the end of a row, go to next row
+ ; by adding 8 to the cell pointer,
+ ; skipping the first cell of the next row
+ LOAD FF_CELL_PTR
+ INC 8
+ STORE FF_CELL_PTR
+
+ LOAD FF_ROW_COUNT ; decrement row count
+ DEC 1
+ DUP
+ STORE FF_ROW_COUNT
+ CBRANCH.NZ FF_ROW ; loop if row count <> 0
+
+FF_EXIT:
+ FPADJ FF_FS
+ RET
+
+; framebuffer controller registers
+ .EQU FB_RA $900
+ .EQU FB_WA $901
+ .EQU FB_IO $902
+ .EQU FB_PS $903
+ .EQU FB_PD $904
+ .EQU FB_CTL $905
+ .EQU WORDS_PER_LINE 80
+
+; fire width in vmem words (strict left-to-right evaluation)
+ .EQU FFD_ROW_WORDS 1 + FIREWIDTH / 8
+
+; draw all fire cells
+; args: pointer to fire cell buffer, screen x, screen y
+ .EQU FFD_CELL_PTR 0
+ .EQU FFD_X 4
+ .EQU FFD_Y 8
+ .EQU FFD_ROW_COUNT 12
+ .EQU FFD_ROW_WORDCOUNT 16
+ .EQU FFD_VMEM_PTR 20
+ .EQU FFD_FS 24
+FASTFIREDRAW:
+ FPADJ -FFD_FS
+ STORE FFD_Y
+ STORE FFD_X
+ STORE FFD_CELL_PTR
+
+ ; calculate video memory addr
+ ; addr = y * 80 + X / 8
+ LOAD FFD_Y
+ SHL 2 ; y * 16
+ SHL 2
+ DUP
+ SHL 2 ; + y * 64
+ ADD ; = y * 80
+
+ LOAD FFD_X
+ SHR
+ SHR
+ SHR
+ ADD ; + x / 8
+
+ DUP
+ STORE FFD_VMEM_PTR
+ LOADC FB_WA ; set vmem write address
+ SWAP
+ STOREI
+ DROP
+
+ LOADC FIREHEIGHT + 1
+ STORE FFD_ROW_COUNT
+FFD_ROW:
+ LOADC FFD_ROW_WORDS
+ STORE FFD_ROW_WORDCOUNT
+
+ LOADC FB_WA ; set vmem write address
+ LOAD FFD_VMEM_PTR
+ STOREI
+ DROP
+
+FFD_WORD:
+ LOAD FFD_CELL_PTR ; load cell ptr
+ LOADC 0 ; vmem word, start with 0
+
+ ; leftmost pixel (0)
+ OVER ; [ cptr, vmemw, cptr ]
+ LOADI ; load cell value [ cptr, vmemw, cellval ]
+ SHR ; scale it down (from 7 bits to 4)
+ SHR
+ SHR ; [ cptr, vmemw, cellval shr 3 ]
+ OR ; [ cptr, vmemw ]
+ SWAP ; [ vmemw, cptr ]
+ INC 4 ; increment cell ptr on stack [ vmemw, cptr + 4 ]
+ SWAP ; [ cptr + 4, vmemw ]
+
+ SHL 2 ; move bits to left for next pixel
+ SHL 2
+
+ ; pixel 1
+ OVER
+ LOADI ; load cell value
+ SHR ; scale it down (from 7 bits to 4)
+ SHR
+ SHR
+ OR
+ SWAP
+ INC 4 ; increment cell ptr on stack
+ SWAP
+
+ SHL 2 ; move bits to left for next pixel
+ SHL 2
+
+ ; pixel 2
+ OVER
+ LOADI ; load cell value
+ SHR ; scale it down (from 7 bits to 4)
+ SHR
+ SHR
+ OR
+ SWAP
+ INC 4 ; increment cell ptr on stack
+ SWAP
+
+ SHL 2 ; move bits to left for next pixel
+ SHL 2
+
+ ; pixel 3
+ OVER
+ LOADI ; load cell value
+ SHR ; scale it down (from 7 bits to 4)
+ SHR
+ SHR
+ OR
+ SWAP
+ INC 4 ; increment cell ptr on stack
+ SWAP
+
+ SHL 2 ; move bits to left for next pixel
+ SHL 2
+
+ ; pixel 4
+ OVER
+ LOADI ; load cell value
+ SHR ; scale it down (from 7 bits to 4)
+ SHR
+ SHR
+ OR
+ SWAP
+ INC 4 ; increment cell ptr on stack
+ SWAP
+
+ SHL 2 ; move bits to left for next pixel
+ SHL 2
+
+ ; pixel 5
+ OVER
+ LOADI ; load cell value
+ SHR ; scale it down (from 7 bits to 4)
+ SHR
+ SHR
+ OR
+ SWAP
+ INC 4 ; increment cell ptr on stack
+ SWAP
+
+ SHL 2 ; move bits to left for next pixel
+ SHL 2
+
+ ; pixel 6
+ OVER
+ LOADI ; load cell value
+ SHR ; scale it down (from 7 bits to 4)
+ SHR
+ SHR
+ OR
+ SWAP
+ INC 4 ; increment cell ptr on stack
+ SWAP
+
+ SHL 2 ; move bits to left for next pixel
+ SHL 2
+
+ ; pixel 7
+ OVER
+ LOADI ; load cell value
+ SHR ; scale it down (from 7 bits to 4)
+ SHR
+ SHR
+ OR
+ SWAP
+ INC 4 ; increment cell ptr on stack
+ SWAP
+
+ ; store word to vmem
+ ; vmem write addr will autoincrement
+ LOADC FB_IO
+ SWAP
+ STOREI
+ DROP
+
+ STORE FFD_CELL_PTR
+
+ ; prepare for next word
+ LOAD FFD_ROW_WORDCOUNT
+ DEC 1
+ DUP
+ STORE FFD_ROW_WORDCOUNT
+ CBRANCH.NZ FFD_WORD
+
+ ; prepare for next row
+ LOAD FFD_VMEM_PTR
+ LOADC WORDS_PER_LINE
+ ADD
+ STORE FFD_VMEM_PTR
+
+ LOAD FFD_ROW_COUNT
+ DEC 1
+ DUP
+ STORE FFD_ROW_COUNT
+ CBRANCH.NZ FFD_ROW
+FFD_EXIT:
+ FPADJ FFD_FS
+ RET
diff --git a/examples/fire.pas b/examples/fire.pas
new file mode 100644
index 0000000..22f0217
--- /dev/null
+++ b/examples/fire.pas
@@ -0,0 +1,76 @@
+{$H1}
+{$S2}
+program fire;
+const MAXX = 30;
+ MAXY = 50;
+var firebuf: array [0..MAXY, 0..MAXX] of integer;
+
+ firepalette: array [0..15] of integer =
+ ( $FFA, $FF8, $FF4, $FF0, $FE0, $FD0, $FA0, $F90,
+ $F00, $E00, $D00, $A00, $800, $600, $300, $000);
+ x,y:integer;
+
+procedure createPalette;
+var i:integer;
+begin
+ for i := 15 downto 0 do
+ setpalette(15 - i, firepalette[i]);
+end;
+
+procedure fireItUp;
+var x,y:integer;
+begin
+ y := MAXY - 1;
+ for x := 1 to MAXX - 1 do
+ firebuf[y, x] := random and 127;
+end;
+
+procedure updateFire;
+var i,x,y:integer;
+begin
+ for y := 0 to MAXY - 2 do
+ for x := 1 to MAXX - 1 do
+ begin
+ i :=
+ ((firebuf[y + 1, x - 1]
+ + firebuf[y + 1, x]
+ + firebuf[y + 1, x + 1]
+ + firebuf[y + 2, x])
+ ) shr 2;
+ if i > 0 then
+ i := i - 1;
+ firebuf[y, x] := i;
+ end;
+end;
+
+procedure drawFire;
+var x, y, col:integer;
+begin
+ for y := 0 to MAXY - 1 do
+ begin
+ x := 0;
+ for col in firebuf[y] do
+ begin
+ putpixel(300 + x, 150 + y, col shr 3);
+ x := x + 1;
+ end;
+ end;
+end;
+
+begin
+ randomize;
+ initgraphics;
+ createPalette;
+ while not conavail do
+ begin
+ fireItUp;
+ updateFire;
+ drawFire;
+ end;
+
+ for y := 0 to MAXY do
+ begin
+ x := firebuf[y, 10];
+ drawline(0, y, x, y, 1);
+ end;
+end.
diff --git a/examples/fire2.pas b/examples/fire2.pas
new file mode 100644
index 0000000..72fb254
--- /dev/null
+++ b/examples/fire2.pas
@@ -0,0 +1,84 @@
+{$H1}
+{$S1}
+program fire2;
+uses fastfire;
+
+const MAXX = FIREWIDTH;
+ MAXY = FIREHEIGHT;
+
+var firecells: FireBuf;
+
+ firepalette: array [0..15] of integer =
+ { ( $FFA, $FF8, $FF4, $FF0, $FE0, $FD0, $FA0, $F90,
+ $F00, $E00, $D00, $A00, $800, $600, $300, $000); }
+ ( $FFA, $FFA, $FFA, $FFA, $FF0, $FF0, $FF0, $FF0,
+ $FF0, $FD0, $FA0, $C00, $A00, $700, $400, $000);
+ x,y:integer;
+
+procedure createPalette;
+var i:integer;
+begin
+ for i := 15 downto 0 do
+ setpalette(15 - i, firepalette[i]);
+end;
+
+procedure fireItUp;
+var x,y:integer;
+begin
+ y := MAXY - 1;
+ for x := 1 to MAXX - 1 do
+ firecells[y, x] := random and 127;
+end;
+
+
+procedure updateFire;
+var i,x,y:integer;
+begin
+ for y := 0 to MAXY - 2 do
+ for x := 1 to MAXX - 1 do
+ begin
+ i :=
+ ((firecells[y + 1, x - 1]
+ + firecells[y + 1, x]
+ + firecells[y + 1, x + 1]
+ + firecells[y + 2, x])
+ ) shr 2;
+ if i > 0 then
+ i := i - 1;
+ firecells[y, x] := i;
+ end;
+end;
+
+procedure drawFire;
+var x, y, col:integer;
+begin
+ for y := 0 to MAXY - 1 do
+ begin
+ x := 0;
+ for col in firecells[y] do
+ begin
+ putpixel(100 + x, 150 + y, col shr 3);
+ x := x + 1;
+ end;
+ end;
+end;
+
+begin
+ randomize;
+ initgraphics;
+ createPalette;
+ while not conavail do
+ begin
+ fireItUp;
+ FastFireUpdate(firecells);
+ { updateFire; }
+ FastFireDraw(firecells, 160, 100);
+ { drawFire; }
+ end;
+
+ for y := 0 to MAXY do
+ begin
+ x := firecells[y, 10];
+ drawline(0, y, x, y, 1);
+ end;
+end.
diff --git a/pcomp/emit.pas b/pcomp/emit.pas
index a201714..d440951 100644
--- a/pcomp/emit.pas
+++ b/pcomp/emit.pas
@@ -324,7 +324,9 @@ begin
rewindStringList(usedUnits);
while nextStringListItem(usedUnits, unitName) do
emitInclude(unitName + UnitSuffix2);
-
+ (* _END label needs to be word-aligned because
+ it is used as the start of the heap *)
+ emitIns('.ALIGN');
emitLabelRaw('_END');
end;
diff --git a/pcomp/sasm.pas b/pcomp/sasm.pas
index 1858f11..d032748 100644
--- a/pcomp/sasm.pas
+++ b/pcomp/sasm.pas
@@ -2056,6 +2056,9 @@ begin
operandValue := 0;
emitBlock(count, operandValue);
end
+ else
+ if lastToken.tokenText = '.ALIGN' then
+ alignOutput(wordSize)
else
errorExit2('Unrecognized directive', lastToken.tokenText);
end;
diff --git a/progs/xfer.pas b/progs/xfer.pas
index 13a7cc2..0d871d2 100644
--- a/progs/xfer.pas
+++ b/progs/xfer.pas
@@ -226,6 +226,7 @@ begin
if not invalid then
begin
open(xferFile, filename, ModeOverwrite);
+ blockNo := 0;
done := false;
repeat
serReadBlock(ok);
diff --git a/tridoracpu/tridoracpu.srcs/Arty-A7-35-Master.xdc b/tridoracpu/tridoracpu.srcs/Arty-A7-35-Master.xdc
index 2a33ae0..d2c3160 100644
--- a/tridoracpu/tridoracpu.srcs/Arty-A7-35-Master.xdc
+++ b/tridoracpu/tridoracpu.srcs/Arty-A7-35-Master.xdc
@@ -8,8 +8,8 @@ set_property -dict {PACKAGE_PIN E3 IOSTANDARD LVCMOS33} [get_ports clk]
create_clock -period 10.000 -name sys_clk_pin -waveform {0.000 5.000} -add [get_ports clk]
## Switches
-set_property -dict {PACKAGE_PIN A8 IOSTANDARD LVCMOS33} [get_ports sw0]
-set_property -dict {PACKAGE_PIN C11 IOSTANDARD LVCMOS33} [get_ports sw1]
+#set_property -dict {PACKAGE_PIN A8 IOSTANDARD LVCMOS33} [get_ports sw0]
+#set_property -dict {PACKAGE_PIN C11 IOSTANDARD LVCMOS33} [get_ports sw1]
#set_property -dict { PACKAGE_PIN C10 IOSTANDARD LVCMOS33 } [get_ports { sw[2] }]; #IO_L13N_T2_MRCC_16 Sch=sw[2]
#set_property -dict { PACKAGE_PIN A10 IOSTANDARD LVCMOS33 } [get_ports { sw[3] }]; #IO_L14P_T2_SRCC_16 Sch=sw[3]
@@ -34,7 +34,7 @@ set_property -dict {PACKAGE_PIN T9 IOSTANDARD LVCMOS33} [get_ports led2]
set_property -dict {PACKAGE_PIN T10 IOSTANDARD LVCMOS33} [get_ports led3]
## Buttons
-set_property -dict {PACKAGE_PIN D9 IOSTANDARD LVCMOS33} [get_ports btn0]
+#set_property -dict {PACKAGE_PIN D9 IOSTANDARD LVCMOS33} [get_ports btn0]
#set_property -dict { PACKAGE_PIN C9 IOSTANDARD LVCMOS33 } [get_ports { btn1 }]; #IO_L11P_T1_SRCC_16 Sch=btn[1]
#set_property -dict { PACKAGE_PIN B9 IOSTANDARD LVCMOS33 } [get_ports { btn[2] }]; #IO_L11N_T1_SRCC_16 Sch=btn[2]
#set_property -dict { PACKAGE_PIN B8 IOSTANDARD LVCMOS33 } [get_ports { btn[3] }]; #IO_L12P_T1_MRCC_16 Sch=btn[3]
diff --git a/tridoracpu/tridoracpu.srcs/stackcpu.v b/tridoracpu/tridoracpu.srcs/stackcpu.v
index 33b58ec..1d929f7 100644
--- a/tridoracpu/tridoracpu.srcs/stackcpu.v
+++ b/tridoracpu/tridoracpu.srcs/stackcpu.v
@@ -16,11 +16,11 @@ module stackcpu #(parameter ADDR_WIDTH = 32, WIDTH = 32,
output wire write_enable,
input wire mem_wait,
- output wire led1,
- output wire led2,
- output wire led3
+ output wire debug1,
+ output wire debug2,
+ output wire debug3
);
-
+
localparam EVAL_STACK_INDEX_WIDTH = 6;
wire reset = !rst;
@@ -90,7 +90,6 @@ module stackcpu #(parameter ADDR_WIDTH = 32, WIDTH = 32,
wire mem_write;
wire x_is_zero;
- // wire [WIDTH-1:0] y_plus_operand = Y + operand;
wire x_equals_y = X == Y;
wire y_lessthan_x = $signed(Y) < $signed(X);
@@ -105,16 +104,10 @@ module stackcpu #(parameter ADDR_WIDTH = 32, WIDTH = 32,
assign write_enable = mem_write_enable;
// debug output ------------------------------------------------------------------------------------
- assign led1 = reset;
- assign led2 = ins_loadc;
- assign led3 = ins_branch;
-// assign debug_out1 = { mem_read_enable, mem_write_enable, x_is_zero,
-// ins_branch, ins_aluop, y_lessthan_x, x_equals_y, {7{1'b0}}, seq_state};
-// assign debug_out2 = data_in;
-// assign debug_out3 = nX;
-// assign debug_out4 = nPC;
-// assign debug_out5 = ins;
-// assign debug_out6 = IV;
+ assign debug1 = reset;
+ assign debug2 = ins_loadc;
+ assign debug3 = ins_branch;
+
//--------------------------------------------------------------------------------------------------
// instruction decoding
diff --git a/tridoracpu/tridoracpu.srcs/tdraudio.v b/tridoracpu/tridoracpu.srcs/tdraudio.v
index 0cc055e..1629e31 100644
--- a/tridoracpu/tridoracpu.srcs/tdraudio.v
+++ b/tridoracpu/tridoracpu.srcs/tdraudio.v
@@ -7,7 +7,7 @@ module wavegen #(DATA_WIDTH=32, CLOCK_DIV_WIDTH=22,
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 [AMP_WIDTH-1:0] wr_data,
input wire rd_en,
input wire wr_en,
@@ -20,6 +20,9 @@ module wavegen #(DATA_WIDTH=32, CLOCK_DIV_WIDTH=22,
localparam TDRAU_REG_CLK = 1; /* clock divider register */
localparam TDRAU_REG_AMP = 2; /* amplitude (volume) register */
+ /* avoid warning about unconnected port */
+ (* keep="soft" *) wire _unused = rd_en;
+
reg channel_enable;
reg [CLOCK_DIV_WIDTH-1:0] clock_div;
reg [CLOCK_DIV_WIDTH-1:0] div_count;
@@ -29,12 +32,12 @@ module wavegen #(DATA_WIDTH=32, CLOCK_DIV_WIDTH=22,
wire fifo_wr_en;
wire fifo_rd_en, fifo_full, fifo_empty;
- wire [DATA_WIDTH-1:0] fifo_rd_data;
+ wire [AMP_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,
+ wr_data[AMP_WIDTH-1:0], fifo_rd_data,
fifo_full,
fifo_empty
);
@@ -166,9 +169,14 @@ module tdraudio #(DATA_WIDTH=32) (
localparam AMP_BIAS = 32768;
localparam DAC_WIDTH = 18;
+ /* avoid warning about unconnected port */
+ (* keep="soft" *) wire [DATA_WIDTH-1:AMP_WIDTH] _unused = wr_data[DATA_WIDTH-1:AMP_WIDTH];
+
wire [4:0] chan_sel = io_addr[6:2];
wire [1:0] reg_sel = io_addr[1:0];
+ wire [AMP_WIDTH-1:0] amp_wr_data = wr_data[AMP_WIDTH-1:0];
+
wire [AMP_WIDTH-1:0] chan0_amp;
wire [DATA_WIDTH-1:0] chan0_rd_data;
wire chan0_running;
@@ -210,25 +218,25 @@ module tdraudio #(DATA_WIDTH=32) (
{DATA_WIDTH{1'b1}};
wavegen chan0(clk, reset, reg_sel,
- chan0_rd_data, wr_data,
+ chan0_rd_data, amp_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_data, amp_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_data, amp_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_data, amp_wr_data,
chan3_rd_en, chan3_wr_en,
chan3_amp,
chan3_running, chan3_irq);
diff --git a/tridoracpu/tridoracpu.srcs/top.v b/tridoracpu/tridoracpu.srcs/top.v
index 6a70ef0..a4533d2 100644
--- a/tridoracpu/tridoracpu.srcs/top.v
+++ b/tridoracpu/tridoracpu.srcs/top.v
@@ -15,9 +15,6 @@
module top(
input wire clk,
input wire rst,
- input wire btn0,
- input wire sw0,
- input wire sw1,
output wire led0,
output wire led1,
output wire led2,
@@ -229,6 +226,15 @@ module top(
assign uart_rd_data = { {WIDTH-10{1'b1}}, uart_rx_avail, uart_tx_busy, uart_rx_data };
wire audio_irq;
+
+ buart #(.CLKFREQ(`clkfreq)) uart0(`clock, rst,
+ uart_baud,
+ uart_txd_in, uart_rxd_out,
+ uart_rx_clear, uart_tx_en,
+ uart_rx_avail, uart_tx_busy,
+ uart_tx_data, uart_rx_data);
+
+ // audio controller
`ifdef ENABLE_TDRAUDIO
wire [WIDTH-1:0] tdraudio_wr_data;
wire [WIDTH-1:0] tdraudio_rd_data;
@@ -273,13 +279,6 @@ module top(
`endif
-1;
- buart #(.CLKFREQ(`clkfreq)) uart0(`clock, rst,
- uart_baud,
- uart_txd_in, uart_rxd_out,
- uart_rx_clear, uart_tx_en,
- uart_rx_avail, uart_tx_busy,
- uart_tx_data, uart_rx_data);
-
// CPU -----------------------------------------------------------------
stackcpu cpu0(.clk(`clock), .rst(rst), .irq(irq),
.addr(mem_addr),
@@ -287,7 +286,7 @@ module top(
.read_ins(dram_read_ins),
.data_out(mem_write_data), .write_enable(mem_write_enable),
.mem_wait(mem_wait),
- .led1(led1), .led2(led2), .led3(led3));
+ .debug1(led1), .debug2(led2), .debug3(led3));
// Interrupt Controller
irqctrl irqctrl0(`clock, irq_in, irqc_cs, mem_write_enable,
diff --git a/tridoracpu/tridoracpu.xpr b/tridoracpu/tridoracpu.xpr
index 3767063..a9dc20f 100644
--- a/tridoracpu/tridoracpu.xpr
+++ b/tridoracpu/tridoracpu.xpr
@@ -378,30 +378,19 @@
-
+
-
- Similar to Performance_ExplorePostRoutePhysOpt, but enables logic optimization step (opt_design) with the ExploreWithRemap directive.
+
+ Default settings for Implementation.
-
-
-
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
+
+
+
diff --git a/utils/serload.py b/utils/serload.py
index 6ccc4a6..e69837f 100644
--- a/utils/serload.py
+++ b/utils/serload.py
@@ -16,6 +16,7 @@
# limitations under the License.
import sys
+import os
import serial
import time
import random
@@ -41,30 +42,6 @@ def get_default_device():
return '/dev/ttyUSB1'
-def serwrite_slow(databytes, ser):
- total = len(data)
- count = 1
- for d in data:
- sys.stdout.write("writing {0:02x} {1:04d}/{2:04d}\r".format(ord(d), count, total))
- ser.write(bytes(d,"utf8"))
- count += 1
- time.sleep(0.020)
- print()
-
-
-def serwrite(datafile, ser):
- with open(datafile) as f:
- data = f.read()
- total = len(data)
- count = 1
- for d in data:
- sys.stdout.write("writing {0:02x} {1:04d}/{2:04d}\r".format(ord(d), count, total))
- ser.write(bytes(d,"utf8"))
- count += 1
- time.sleep(0.020)
- print()
-
-
def checksum(databytes):
i = 0
cksum = 0
@@ -85,10 +62,26 @@ def sendchar(char, ser):
ser.write(char.to_bytes(1, 'big'))
-def sendcommand(ser, cmd=b'L'):
+def sendcommand(ser, cmd=b'L', verbose=False):
+ verbose = True
ser.write(cmd)
resp = ser.read_until()
- print(cmd,"sent, response:", str(resp))
+ if verbose:
+ print(cmd,"sent, response:", str(resp))
+ return resp
+
+
+# send command and wait for echo
+def commandwait(ser, cmd):
+ resp = sendcommand(ser, cmd, verbose=False)
+ if len(resp) == 0:
+ print("timeout sending '{}' command".format(cmd))
+ return None
+
+ if resp != bytearray(cmd + b"\r\n"):
+ print("invalid response to '{}' command".format(cmd))
+ return None
+
return resp
@@ -153,6 +146,8 @@ def serload_bin(datafile, ser):
data += bytearray(pad)
+ print("{} total blocks".format((len(data) + blocksize - 1) // blocksize))
+
if not send_size_header(ser, filesize):
print("Error sending size header.")
return
@@ -279,18 +274,8 @@ def serdownload(fname, ser):
def mput(filenames, ser):
for f in filenames:
- f_encoded = f.encode('utf8')
- print("Setting filename", f)
- resp = sendcommand(ser, b'S')
- if len(resp) == 0:
- print("timeout sending 'S' command")
- return
- if resp != b'S\r\n' and resp != b'> S\r\n':
- print("unrecognized response to 'S' command, aborting")
- return
- resp = sendcommand(ser, f_encoded + b'\r')
- if not f_encoded in resp:
- print("unrecognized response to filename, aborting")
+ resp = set_filename(f, ser)
+ if resp is None:
return
serload_bin(f, ser)
@@ -299,12 +284,92 @@ def mput(filenames, ser):
time.sleep(2)
+def set_filename(f, ser):
+ f_encoded = f.encode('utf8')
+ print("Setting filename", f)
+ resp = commandwait(ser, b'S')
+ if resp is None:
+ return None
+ resp = sendcommand(ser, f_encoded + b'\r')
+ if not f_encoded in resp:
+ print("unrecognized response to filename, aborting")
+ return None
+ return resp
+
+
+def getnamedfile(filename, ser):
+ resp = set_filename(filename, ser)
+ if resp is None:
+ return None
+ serdownload(filename, ser)
+
+
+def putnamedfile(filename, ser):
+ resp = set_filename(filename, ser)
+ if resp is None:
+ return None
+ serload_bin(filename, ser)
+ print("Remote status:")
+ showdata(ser)
+
+
+def showdata(ser):
+
+ promptseen = False
+
+ while not promptseen:
+ c = ser.read(1)
+ if c == b'>':
+ promptseen = True
+ else:
+ print(c.decode('utf8'), end='')
+ rest = ser.read(1)
+
+
+def localdir():
+ result = os.walk(".")
+ for dirpath, dirnames, filenames in os.walk("."):
+ for f in filenames:
+ print(f)
+ break
+
+
+def interactive(ser):
+ done = False
+ while not done:
+ args = input("> ").strip().split()
+ if len(args) > 0:
+ cmd = args[0]
+ args.pop(0)
+ if cmd == 'dir':
+ if commandwait(ser, b'Y') is None:
+ return
+ showdata(ser)
+ elif cmd == 'get':
+ if len(args) > 1:
+ print("exactly one argument required (filename)")
+ else:
+ getnamedfile(args[0], ser)
+ elif cmd == 'put':
+ if len(args) > 1:
+ print("exactly one argument required (filename)")
+ else:
+ putnamedfile(args[0], ser)
+ elif cmd == 'ldir':
+ if len(args) > 0:
+ print("superfluous argument")
+ else:
+ localdir()
+ else:
+ print("Unknown command. Valid commands are: dir get ldir put")
+
+
if __name__ == "__main__":
argparser = argparse.ArgumentParser(
description='transfer files from/to the Tridora-CPU')
argparser.add_argument('-d', '--device', help='serial device', default=get_default_device())
- argparser.add_argument('command', choices=['get', 'put', 'mput'])
- argparser.add_argument('filename', nargs='+')
+ argparser.add_argument('command', choices=['get', 'put', 'mput', 'interactive'])
+ argparser.add_argument('filename', nargs='*')
args = argparser.parse_args()
cmd = args.command
@@ -319,8 +384,10 @@ if __name__ == "__main__":
serload_bin(filenames[0], ser)
elif cmd == 'mput':
mput(filenames, ser)
+ elif cmd == 'interactive':
+ interactive(ser)
else:
print("should not get here")
- if cmd is not None:
- ser.close()
+ #if cmd is not None:
+ # ser.close()