Z80-FPGA icon indicating copy to clipboard operation
Z80-FPGA copied to clipboard

Can't print OUT (0x10) to UART

Open mkhudyakov opened this issue 10 months ago • 0 comments

Makefile.txt top.pcf.txt top.v.txt uart_tx.v.txt

I'm desperately trying to execute set of instructions by CPU and print OUT to UART.

module top (
    input clk,           // 12 MHz clock input
    output tx,           // UART TX to host
    output reg dbg_led   // LED reflects CPU address activity
);

    // --- Power-on Reset ---
    reg [15:0] reset_cnt = 0;
    wire reset_n = &reset_cnt;
    always @(posedge clk)
        if (!reset_n)
            reset_cnt <= reset_cnt + 1;

    // --- Z80 Bus ---
    wire [15:0] address;
    wire [7:0] dout;
    wire iorq, write;
    wire m1_n;

    // --- ROM ---
    reg [7:0] rom[0:255];
    initial begin
        rom[0]  = 8'h3E; rom[1]  = 8'h41;   // LD A, 'A'
        rom[2]  = 8'hD3; rom[3]  = 8'h10;   // OUT (0x10), A
        rom[4]  = 8'h3E; rom[5]  = 8'h42;   // LD A, 'B'
        rom[6]  = 8'hD3; rom[7]  = 8'h10;   // OUT (0x10), A
        rom[8]  = 8'h3E; rom[9]  = 8'h43;   // LD A, 'C'
        rom[10] = 8'hD3; rom[11] = 8'h10;   // OUT (0x10), A
        rom[12] = 8'hC3; rom[13] = 8'h00; rom[14] = 8'h00; // JP 0000h (loop forever)
    end

    // --- Z80 Core ---
    tv80_core #(
	.Mode(0),
	.IOWait(1)
    ) cpu (
        .clk(clk),
        .reset_n(reset_n),
        .cen(1'b1),
        .wait_n(1'b1),
        .int_n(1'b1),
        .nmi_n(1'b1),
        .busrq_n(1'b1),
        .A(address),
        .di(rom[address]),
        .dout(dout),
        .dinst(rom[address]),
        .iorq(iorq),
        .write(write),
        .m1_n(m1_n), .rfsh_n(), .halt_n(), .busak_n(),
        .no_read(), .mc(), .ts(), .intcycle_n(), .IntE(), .stop()
    );

    // --- UART TX ---
    reg [7:0] tx_data;
    reg tx_start = 0;
    wire tx_busy;
    wire uart_tx;

    uart_tx #(.CLKS_PER_BIT(1250)) uart (
        .clk(clk),
        .rst(1'b0),
        .tx_start(tx_start),
        .data_in(tx_data),
        .tx(uart_tx),
        .busy(tx_busy)
    );
    assign tx = uart_tx;

    always @(posedge clk) begin
        tx_start <= 0;
    
        if (iorq && write && address[7:0] == 8'h10) begin
            tx_data <= dout;
            tx_start <= 1;
            dbg_led <= ~dbg_led;
        end
    end

endmodule

The above example gives

admin@raspberrypi:~/workspace/Z80-FPGA/build $ make flash && picocom -b 9600 /dev/ttyACM0
cp top.bin /media/admin/iCELink/
picocom v3.1

port is        : /dev/ttyACM0
flowcontrol    : none
baudrate is    : 9600
parity is      : none
databits are   : 8
stopbits are   : 1
escape is      : C-a
local echo is  : no
noinit is      : no
noreset is     : no
hangup is      : no
nolock is      : no
send_cmd is    : sz -vv
receive_cmd is : rz -vv -E
imap is        :
omap is        :
emap is        : crcrlf,delbs,
logfile is     : none
initstring     : none
exit_after is  : not set
exit is        : no

Type [C-a] [C-h] to see available commands
Terminal ready
<iCELink:Overflow>
                  @start
@cdone:1
?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
Terminating...
Thanks for using picocom

If I replace tx_data <= dout; with tx_data <= 8'h41; // ASCII 'A' then I get AAAAAAA... through UART, which means that CPU executed instructions.

Testing is done by deploying and immediately connecting to device iCESugar v1.5 FPGA (Lattice iCE40UP5K)

make flash && picocom -b 9600 /dev/ttyACM0

What do I do wrong? I wonder how CP/M or Tinybasic can be run if I can't do the simple output through UART... Please help!

__ For the reference __

Makefile

# Makefile for building Z80 FPGA project

SRC = top.v tv80_core.v tv80_reg.v tv80_alu.v tv80_mcode.v uart_tx.v

all: top.bin

top.json: $(SRC)
	yosys -p "read_verilog $(SRC); hierarchy -top top; synth_ice40 -top top -json top.json"

top.asc: top.json top.pcf
	nextpnr-ice40 --up5k --package sg48 --json top.json --pcf top.pcf --asc top.asc

top.bin: top.asc
	icepack top.asc top.bin

flash: top.bin
	cp top.bin /media/admin/iCELink/

clean:
	rm -f top.json top.asc top.bin

PCF file (correct for iCESugar v1.5 FPGA (Lattice iCE40UP5K))

set_io clk 35     # 12 MHz clock

set_io --warn-no-port rx 4
set_io --warn-no-port tx 6

set_io dbg_led 39

mkhudyakov avatar May 20 '25 15:05 mkhudyakov