Compare commits

..

5 commits

Author SHA1 Message Date
slederer
d2f3b09e72 tridoracpu: cleaned up top a bit, removed some warnings 2025-12-15 00:53:36 +01:00
slederer
0016d4ea25 utils/serload: add interactive mode
xfer: reset block count on transfer start
2025-12-05 00:58:15 +01:00
slederer
8f4d017668 sasm: fix typo error; examples: add fire demo 2025-11-30 23:49:44 +01:00
slederer
87ec71bd6d align _END label, add ALIGN directive to assembler
- fixes failing memory allocator when _END label is not aligned
2025-11-05 00:30:49 +01:00
slederer
0f72080c56 tridoracpu: experimented with synthesis options again
- workaround for an apparent bug with LOAD address
  generation at offsets >= 3584
- updated bitstream URL
2025-10-26 00:27:34 +02:00
14 changed files with 652 additions and 99 deletions

View file

@ -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 [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 [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 [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) - 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 Contact the author here: tridoracpu [at] insignificance.de

5
examples/fastfire.inc Normal file
View file

@ -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;

326
examples/fastfire.s Normal file
View file

@ -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

76
examples/fire.pas Normal file
View file

@ -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.

84
examples/fire2.pas Normal file
View file

@ -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.

View file

@ -324,7 +324,9 @@ begin
rewindStringList(usedUnits); rewindStringList(usedUnits);
while nextStringListItem(usedUnits, unitName) do while nextStringListItem(usedUnits, unitName) do
emitInclude(unitName + UnitSuffix2); emitInclude(unitName + UnitSuffix2);
(* _END label needs to be word-aligned because
it is used as the start of the heap *)
emitIns('.ALIGN');
emitLabelRaw('_END'); emitLabelRaw('_END');
end; end;

View file

@ -2056,6 +2056,9 @@ begin
operandValue := 0; operandValue := 0;
emitBlock(count, operandValue); emitBlock(count, operandValue);
end end
else
if lastToken.tokenText = '.ALIGN' then
alignOutput(wordSize)
else else
errorExit2('Unrecognized directive', lastToken.tokenText); errorExit2('Unrecognized directive', lastToken.tokenText);
end; end;

View file

@ -226,6 +226,7 @@ begin
if not invalid then if not invalid then
begin begin
open(xferFile, filename, ModeOverwrite); open(xferFile, filename, ModeOverwrite);
blockNo := 0;
done := false; done := false;
repeat repeat
serReadBlock(ok); serReadBlock(ok);

View file

@ -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] create_clock -period 10.000 -name sys_clk_pin -waveform {0.000 5.000} -add [get_ports clk]
## Switches ## Switches
set_property -dict {PACKAGE_PIN A8 IOSTANDARD LVCMOS33} [get_ports sw0] #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 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 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] #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] set_property -dict {PACKAGE_PIN T10 IOSTANDARD LVCMOS33} [get_ports led3]
## Buttons ## 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 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 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] #set_property -dict { PACKAGE_PIN B8 IOSTANDARD LVCMOS33 } [get_ports { btn[3] }]; #IO_L12P_T1_MRCC_16 Sch=btn[3]

View file

@ -16,9 +16,9 @@ module stackcpu #(parameter ADDR_WIDTH = 32, WIDTH = 32,
output wire write_enable, output wire write_enable,
input wire mem_wait, input wire mem_wait,
output wire led1, output wire debug1,
output wire led2, output wire debug2,
output wire led3 output wire debug3
); );
localparam EVAL_STACK_INDEX_WIDTH = 6; localparam EVAL_STACK_INDEX_WIDTH = 6;
@ -90,7 +90,6 @@ module stackcpu #(parameter ADDR_WIDTH = 32, WIDTH = 32,
wire mem_write; wire mem_write;
wire x_is_zero; wire x_is_zero;
// wire [WIDTH-1:0] y_plus_operand = Y + operand;
wire x_equals_y = X == Y; wire x_equals_y = X == Y;
wire y_lessthan_x = $signed(Y) < $signed(X); 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; assign write_enable = mem_write_enable;
// debug output ------------------------------------------------------------------------------------ // debug output ------------------------------------------------------------------------------------
assign led1 = reset; assign debug1 = reset;
assign led2 = ins_loadc; assign debug2 = ins_loadc;
assign led3 = ins_branch; assign debug3 = 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;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// instruction decoding // instruction decoding

View file

@ -7,7 +7,7 @@ module wavegen #(DATA_WIDTH=32, CLOCK_DIV_WIDTH=22,
input wire reset, input wire reset,
input wire [1:0] reg_sel, input wire [1:0] reg_sel,
output wire [DATA_WIDTH-1:0] rd_data, 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 rd_en,
input wire wr_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_CLK = 1; /* clock divider register */
localparam TDRAU_REG_AMP = 2; /* amplitude (volume) register */ localparam TDRAU_REG_AMP = 2; /* amplitude (volume) register */
/* avoid warning about unconnected port */
(* keep="soft" *) wire _unused = rd_en;
reg channel_enable; reg channel_enable;
reg [CLOCK_DIV_WIDTH-1:0] clock_div; reg [CLOCK_DIV_WIDTH-1:0] clock_div;
reg [CLOCK_DIV_WIDTH-1:0] div_count; 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_wr_en;
wire fifo_rd_en, fifo_full, fifo_empty; 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( fifo #(.ADDR_WIDTH(4), .DATA_WIDTH(16)) sample_buf(
clk, reset, clk, reset,
fifo_wr_en, fifo_rd_en, fifo_wr_en, fifo_rd_en,
wr_data, fifo_rd_data, wr_data[AMP_WIDTH-1:0], fifo_rd_data,
fifo_full, fifo_full,
fifo_empty fifo_empty
); );
@ -166,9 +169,14 @@ module tdraudio #(DATA_WIDTH=32) (
localparam AMP_BIAS = 32768; localparam AMP_BIAS = 32768;
localparam DAC_WIDTH = 18; 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 [4:0] chan_sel = io_addr[6:2];
wire [1:0] reg_sel = io_addr[1:0]; 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 [AMP_WIDTH-1:0] chan0_amp;
wire [DATA_WIDTH-1:0] chan0_rd_data; wire [DATA_WIDTH-1:0] chan0_rd_data;
wire chan0_running; wire chan0_running;
@ -210,25 +218,25 @@ module tdraudio #(DATA_WIDTH=32) (
{DATA_WIDTH{1'b1}}; {DATA_WIDTH{1'b1}};
wavegen chan0(clk, reset, reg_sel, wavegen chan0(clk, reset, reg_sel,
chan0_rd_data, wr_data, chan0_rd_data, amp_wr_data,
chan0_rd_en, chan0_wr_en, chan0_rd_en, chan0_wr_en,
chan0_amp, chan0_amp,
chan0_running, chan0_irq); chan0_running, chan0_irq);
wavegen chan1(clk, reset, reg_sel, wavegen chan1(clk, reset, reg_sel,
chan1_rd_data, wr_data, chan1_rd_data, amp_wr_data,
chan1_rd_en, chan1_wr_en, chan1_rd_en, chan1_wr_en,
chan1_amp, chan1_amp,
chan1_running, chan1_irq); chan1_running, chan1_irq);
wavegen chan2(clk, reset, reg_sel, wavegen chan2(clk, reset, reg_sel,
chan2_rd_data, wr_data, chan2_rd_data, amp_wr_data,
chan2_rd_en, chan2_wr_en, chan2_rd_en, chan2_wr_en,
chan2_amp, chan2_amp,
chan2_irq, chan2_running); chan2_irq, chan2_running);
wavegen chan3(clk, reset, reg_sel, wavegen chan3(clk, reset, reg_sel,
chan3_rd_data, wr_data, chan3_rd_data, amp_wr_data,
chan3_rd_en, chan3_wr_en, chan3_rd_en, chan3_wr_en,
chan3_amp, chan3_amp,
chan3_running, chan3_irq); chan3_running, chan3_irq);

View file

@ -15,9 +15,6 @@
module top( module top(
input wire clk, input wire clk,
input wire rst, input wire rst,
input wire btn0,
input wire sw0,
input wire sw1,
output wire led0, output wire led0,
output wire led1, output wire led1,
output wire led2, 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 }; assign uart_rd_data = { {WIDTH-10{1'b1}}, uart_rx_avail, uart_tx_busy, uart_rx_data };
wire audio_irq; 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 `ifdef ENABLE_TDRAUDIO
wire [WIDTH-1:0] tdraudio_wr_data; wire [WIDTH-1:0] tdraudio_wr_data;
wire [WIDTH-1:0] tdraudio_rd_data; wire [WIDTH-1:0] tdraudio_rd_data;
@ -273,13 +279,6 @@ module top(
`endif `endif
-1; -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 ----------------------------------------------------------------- // CPU -----------------------------------------------------------------
stackcpu cpu0(.clk(`clock), .rst(rst), .irq(irq), stackcpu cpu0(.clk(`clock), .rst(rst), .irq(irq),
.addr(mem_addr), .addr(mem_addr),
@ -287,7 +286,7 @@ module top(
.read_ins(dram_read_ins), .read_ins(dram_read_ins),
.data_out(mem_write_data), .write_enable(mem_write_enable), .data_out(mem_write_data), .write_enable(mem_write_enable),
.mem_wait(mem_wait), .mem_wait(mem_wait),
.led1(led1), .led2(led2), .led3(led3)); .debug1(led1), .debug2(led2), .debug3(led3));
// Interrupt Controller // Interrupt Controller
irqctrl irqctrl0(`clock, irq_in, irqc_cs, mem_write_enable, irqctrl irqctrl0(`clock, irq_in, irqc_cs, mem_write_enable,

View file

@ -378,30 +378,19 @@
<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="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">
<Strategy Version="1" Minor="2"> <Strategy Version="1" Minor="2">
<StratHandle Name="Performance_ExploreWithRemap" Flow="Vivado Implementation 2024"> <StratHandle Name="Vivado Implementation Defaults" Flow="Vivado Implementation 2024">
<Desc>Similar to Performance_ExplorePostRoutePhysOpt, but enables logic optimization step (opt_design) with the ExploreWithRemap directive.</Desc> <Desc>Default settings for Implementation.</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>
</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"/>
<Option Id="Directive">0</Option> <Step Id="route_design"/>
</Step> <Step Id="post_route_phys_opt_design"/>
<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>

View file

@ -16,6 +16,7 @@
# limitations under the License. # limitations under the License.
import sys import sys
import os
import serial import serial
import time import time
import random import random
@ -41,30 +42,6 @@ def get_default_device():
return '/dev/ttyUSB1' 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): def checksum(databytes):
i = 0 i = 0
cksum = 0 cksum = 0
@ -85,10 +62,26 @@ def sendchar(char, ser):
ser.write(char.to_bytes(1, 'big')) 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) ser.write(cmd)
resp = ser.read_until() 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 return resp
@ -153,6 +146,8 @@ def serload_bin(datafile, ser):
data += bytearray(pad) data += bytearray(pad)
print("{} total blocks".format((len(data) + blocksize - 1) // blocksize))
if not send_size_header(ser, filesize): if not send_size_header(ser, filesize):
print("Error sending size header.") print("Error sending size header.")
return return
@ -279,18 +274,8 @@ def serdownload(fname, ser):
def mput(filenames, ser): def mput(filenames, ser):
for f in filenames: for f in filenames:
f_encoded = f.encode('utf8') resp = set_filename(f, ser)
print("Setting filename", f) if resp is None:
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")
return return
serload_bin(f, ser) serload_bin(f, ser)
@ -299,12 +284,92 @@ def mput(filenames, ser):
time.sleep(2) 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__": if __name__ == "__main__":
argparser = argparse.ArgumentParser( argparser = argparse.ArgumentParser(
description='transfer files from/to the Tridora-CPU') description='transfer files from/to the Tridora-CPU')
argparser.add_argument('-d', '--device', help='serial device', default=get_default_device()) argparser.add_argument('-d', '--device', help='serial device', default=get_default_device())
argparser.add_argument('command', choices=['get', 'put', 'mput']) argparser.add_argument('command', choices=['get', 'put', 'mput', 'interactive'])
argparser.add_argument('filename', nargs='+') argparser.add_argument('filename', nargs='*')
args = argparser.parse_args() args = argparser.parse_args()
cmd = args.command cmd = args.command
@ -319,8 +384,10 @@ if __name__ == "__main__":
serload_bin(filenames[0], ser) serload_bin(filenames[0], ser)
elif cmd == 'mput': elif cmd == 'mput':
mput(filenames, ser) mput(filenames, ser)
elif cmd == 'interactive':
interactive(ser)
else: else:
print("should not get here") print("should not get here")
if cmd is not None: #if cmd is not None:
ser.close() # ser.close()