Z80-FPGA
Z80-FPGA copied to clipboard
Can't print OUT (0x10) to UART
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