Skip to content

Commit

Permalink
Made output mux asynchronous (non-clocked) and driven by excternal input
Browse files Browse the repository at this point in the history
  • Loading branch information
rejunity committed Jun 1, 2024
1 parent ca60ed6 commit 7f155e9
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 39 deletions.
56 changes: 33 additions & 23 deletions src/tt_um_rejunity_z80.v
Original file line number Diff line number Diff line change
Expand Up @@ -18,35 +18,42 @@ module tt_um_rejunity_z80 (

// We have to multiplex the 16 bits of (A) address bus and 8 control signals into
// the 8 output pins that are available in TinyTapeout.
//
// 1) TinyTapeout clock has to be divided by 4 to get the Z80 clock and
// 2) Output pins see the following sequence:
// 1st cycle --- control signals {m1_n, mreq_n, iorq_n, rd_n, wr_n, rfsh_n, halt_n, busak_n}
// 2nd cycle --- {A0 - A7}
// 3rd cycle --- repeated control signals
// 4th cycle --- {A8 - A15}

reg [1:0] clk_counter;
always @(posedge clk)
clk_counter <= (rst_n) ? clk_counter + 1 : 0;
wire z80_clk = (rst_n) ? clk_counter[1:0] == 0: clk; // Z80 clock is pulsed once every 4 TinyTapeout clock cycles

wire [7:0] ctrl_signals;
wire [15:0] addr_bus;
assign uo_out = (clk_counter[0] == 0) ? ctrl_signals :
(clk_counter[1] == 0) ? addr_bus[7:0] :

// Use mux_control to select between the address bus and control signals
// [00] --- {A0 - A7}
// [01] --- {A8 - A15}
// [1?] --- control signals {m1_n, mreq_n, iorq_n, rd_n, wr_n, rfsh_n, halt_n, busak_n}

// reg [1:0] clk_counter;
// always @(posedge clk)
// clk_counter <= (rst_n) ? clk_counter + 1 : 0;
// wire z80_clk = (rst_n) ? clk_counter[1:0] == 0: clk; // Z80 clock is pulsed once every 4 TinyTapeout clock cycles

// assign uo_out = (clk_counter[0] == 0) ? ctrl_signals :
// (clk_counter[1] == 0) ? addr_bus[7:0] :
// addr_bus[15:8];

wire z80_clk = clk;
wire [1:0] mux_control = ui_in[7:6];
assign uo_out = (mux_control[1] == 1) ? ctrl_signals :
(mux_control[0] == 0) ? addr_bus[7:0] :
addr_bus[15:8];

// reg [7:0] mux_out;
// assign uo_out = mux_out;
// always @(*) begin
// case(clk_counter[1:0])
// 2'd0: assign uo_out = ctrl_signals;
// 2'd1: assign uo_out = addr_bus[7:0];
// 2'd2: assign uo_out = ctrl_signals;
// 2'd3: assign uo_out = addr_bus[15:8];
// case(ui_in[7:6])
// 2'd0: mux_out = addr_bus[7:0];
// 2'd1: mux_out = addr_bus[15:8];
// 2'd2: mux_out = ctrl_signals;
// 2'd3: mux_out = ctrl_signals;
// endcase
// end

wire wr = ~ctrl_signals[4];
assign uio_oe = {8{wr}}; // (active high: 0=input, 1=output)
wire doe; // Data Output Enable
assign uio_oe = {8{doe}}; // (active high: 0=input, 1=output)

z80 z80 (
.clk (z80_clk),
Expand All @@ -58,6 +65,7 @@ module tt_um_rejunity_z80 (
.busrq_n (ui_in[3]),
.di (uio_in),
.dout (uio_out),
.doe (doe),
.A (addr_bus),
.m1_n (ctrl_signals[0]),
.mreq_n (ctrl_signals[1]),
Expand All @@ -81,6 +89,7 @@ module z80 (

input wire [7:0] di,
output wire [7:0] dout,
output wire doe,

output wire [15:0] A,
output wire m1_n,
Expand Down Expand Up @@ -115,7 +124,8 @@ module z80 (
.busak_n (busak_n),
.A (A),
.di (di),
.dout (dout)
.dout (dout),
.write (doe)
);

endmodule
4 changes: 2 additions & 2 deletions src/tv80/tv80s.v
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

module tv80s (/*AUTOARG*/
// Outputs
m1_n, mreq_n, iorq_n, rd_n, wr_n, rfsh_n, halt_n, busak_n, A, dout,
m1_n, mreq_n, iorq_n, rd_n, wr_n, rfsh_n, halt_n, busak_n, A, dout, write,
// Inputs
reset_n, clk, wait_n, int_n, nmi_n, busrq_n, di, cen
);
Expand Down Expand Up @@ -60,7 +60,7 @@ module tv80s (/*AUTOARG*/

wire intcycle_n;
wire no_read;
wire write;
output wire write;
wire iorq;
reg [7:0] di_reg;
wire [6:0] mcycle;
Expand Down
85 changes: 71 additions & 14 deletions test/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,18 @@ async def test__NOP(dut):
for i in range(32):
controls, addr = await z80_step(dut, z80_cycle, verbose=True)

if (z80_cycle-1) % cycles_per_instr == 0 or \
(z80_cycle-1) % cycles_per_instr == 1:
if z80_cycle % cycles_per_instr == 0 or \
z80_cycle % cycles_per_instr == 1:
assert controls['m1'] == 1
if (z80_cycle-1) % cycles_per_instr == 1:
if z80_cycle % cycles_per_instr == 1:
assert controls['mreq'] == 1
assert controls['rd'] == 1
assert controls['wr'] == 0
assert controls['ioreq'] == 0
assert controls['halt'] == 0
assert controls['busak'] == 0
if z80_cycle > 1:
assert addr == (z80_cycle - 1) // 4 # Running NOPs, every 4 cycles address increases
if z80_cycle < cycles_per_instr-1:
assert addr == z80_cycle // 4 # Running NOPs, every 4 cycles address increases
z80_cycle += 1


Expand All @@ -54,12 +54,12 @@ async def test__LD_HL2121(dut):
for i in range(32):
controls, addr = await z80_step(dut, z80_cycle, verbose=True)

if (z80_cycle-1) % cycles_per_instr == 0 or \
(z80_cycle-1) % cycles_per_instr == 1:
if z80_cycle % cycles_per_instr == 0 or \
z80_cycle % cycles_per_instr == 1:
assert controls['m1'] == 1
if (z80_cycle-1) % cycles_per_instr == 1 or \
(z80_cycle-1) % cycles_per_instr == 5 or \
(z80_cycle-1) % cycles_per_instr == 8:
if z80_cycle % cycles_per_instr == 1 or \
z80_cycle % cycles_per_instr == 5 or \
z80_cycle % cycles_per_instr == 8:
assert controls['mreq'] == 1
assert controls['rd'] == 1
assert controls['wr'] == 0
Expand All @@ -81,22 +81,79 @@ async def start_and_reset(dut):
dut.ui_in.value = 0
dut.uio_in.value = 0
dut.rst_n.value = 0
await ClockCycles(dut.clk, 8)
await ClockCycles(dut.clk, 16)
dut.rst_n.value = 1
await ClockCycles(dut.clk, 1)

async def z80_step(z80, cycle, verbose=False):
# 1st cycle --- control signals {m1_n, mreq_n, iorq_n, rd_n, wr_n, rfsh_n, halt_n, busak_n}
# 2nd cycle --- {A0 - A7}
# 3rd cycle --- repeated control signals
# 4th cycle --- {A8 - A15}
# z80.ena.value = 1
# z80.ui_in.value = BUS_READY | 0b0000_0000
# await ClockCycles(z80.clk, 1)
# addr = z80.uo_out.value

# z80.ena.value = 0
# z80.ui_in.value = BUS_READY | 0b0100_0000
# await ClockCycles(z80.clk, 1)
# addr = addr | z80.uo_out.value << 8






z80.ui_in.value = BUS_READY | 0b1000_0000
await ClockCycles(z80.clk, 1)
controls = z80.uo_out.value
controls = [int(not bit(controls, n)) for n in range(8)]
controls = dict(zip(['m1', 'mreq', 'ioreq', 'rd', 'wr', 'rfsh', 'halt', 'busak'], controls))
z80.ena.value = 0
z80.ui_in.value = BUS_READY | 0b0000_0000
await ClockCycles(z80.clk, 1)
addr = z80.uo_out.value
await ClockCycles(z80.clk, 2)
z80.ui_in.value = BUS_READY | 0b0100_0000
await ClockCycles(z80.clk, 1)
addr = addr | z80.uo_out.value << 8
z80.ena.value = 1


# z80.ui_in.value = BUS_READY | 0b0000_0000
# await ClockCycles(z80.clk, 1)
# addr = z80.uo_out.value
# z80.ena.value = 0
# z80.ui_in.value = BUS_READY | 0b1000_0000
# await ClockCycles(z80.clk, 1)
# controls = z80.uo_out.value
# z80.ui_in.value = BUS_READY | 0b0100_0000
# await ClockCycles(z80.clk, 1)
# addr = addr | z80.uo_out.value << 8
# z80.ena.value = 1






# z80.ena.value = 1
# z80.ui_in.value = BUS_READY | 0b0000_0000
# await ClockCycles(z80.clk, 1)
# addr = z80.uo_out.value

# z80.ena.value = 0
# z80.ui_in.value = BUS_READY | 0b0100_0000
# await ClockCycles(z80.clk, 1)
# addr = addr | z80.uo_out.value << 8

# z80.ui_in.value = BUS_READY | 0b1000_0000
# await ClockCycles(z80.clk, 1)
# controls = z80.uo_out.value
# controls = [int(not bit(controls, n)) for n in range(8)]
# controls = dict(zip(['m1', 'mreq', 'ioreq', 'rd', 'wr', 'rfsh', 'halt', 'busak'], controls))
# z80.ena.value = 1

controls = [int(not bit(controls, n)) for n in range(8)]
controls = dict(zip(['m1', 'mreq', 'ioreq', 'rd', 'wr', 'rfsh', 'halt', 'busak'], controls))

if (verbose):
print (f"clk: {cycle:3d} {controls} addr:0x{addr:04X}".replace("'", "") \
Expand Down

0 comments on commit 7f155e9

Please sign in to comment.