3
module DataMux ( CLK, DL_Control1, DL_Control2, DataBus, DL, Res, DataOut, DV, RD_hack, WR_hack);
6
input DL_Control1; // 1: Bus disable (External Test1 aka BUS_DISABLE)
7
input DL_Control2; // x37. ALU Result -> DL; Gekkio: s3_oe_alu_to_pbus
8
inout [7:0] DataBus; // External databus
9
/* verilator lint_off UNOPTFLAT */
10
inout [7:0] DL; // Internal databus
11
input [7:0] Res; // ALU Result (always driven)
12
input DataOut; // x15. DV -> DL; Gekkio: s3_oe_rbus_to_pbus
13
input [7:0] DV; // ALU Operand2
15
// HACK: These signals are not present in the original circuit, but are
16
// need when simulating it without resorting to driving strength.
20
data_mux_bit dmux [7:0] (
22
.Test1({8{DL_Control1}}),
23
.Res_to_DL({8{DL_Control2}}),
27
.DataOut({8{DataOut}}),
34
// A combined schematic that combines the two bits of what used to be called DataLatch and DataBridge.
35
module data_mux_bit ( clk, Test1, Res_to_DL, Res, Int_bus, Ext_bus, DataOut, dv_bit, RD_hack, WR_hack);
37
input clk; // CLK2; All buses are precharged when clk=0.
38
input Test1; // External (1: disconnect core databus)
39
input Res_to_DL; // ALU result -> internal databus (from decoder3); Gekkio: s3_oe_alu_to_pbus
40
input Res; // ALU result
41
inout Int_bus; // DL[n] (internal databus)
42
inout Ext_bus; // D[n] (external databus)
44
input DataOut; // Gekkio: s3_oe_rbus_to_pbus
48
wire int_to_ext_q; // transparent latch to keep DL bus
49
wire ext_to_int_q; // transparent latch to keep external databus
50
wire res_q; // transparent latch to keep ALU result; is not required at all, because the bus Res is always output, but let it be
51
wire dv_q; // transparent latch to keep DV bus
53
BusKeeper int_to_ext ( .d(Int_bus), .q(int_to_ext_q) );
54
BusKeeper ext_to_int ( .d(Ext_bus), .q(ext_to_int_q) );
55
BusKeeper res_latch ( .d(Res), .q(res_q) );
56
BusKeeper dv_latch ( .d(dv_bit), .q(dv_q) );
58
// ⚠️This implementation is an approximation of the real circuit, so it is
59
// not a die-perfect approach.
61
// An analysis of the real circuit reveals that the buses may be driven by
62
// multiple sources at the same time, causing conflicts. The mechanism
63
// that resolves these conflicts in the real circuit is unclear, but
64
// making all external buses have a stronger driving strength than
65
// internal buses seems to work.
67
// We also assume that the `clk` signal, which appears to pre-charge the
68
// buses, has a stronger driving strength than the other signals
69
// (otherwise there will also be internal conflicts).
71
// And to simulate the pre-charge effect, we have a weak pull-up on the
72
// buses, that makes it resolve to 1 when no other signal is driving the
76
// assign Ext_bus = (clk || Test1) ? 1'bz : 1;
77
// assign(pull0, pull1) Ext_bus = clk && ~(int_to_ext_q || Test1) ? 0 : 1'bz;
79
// assign Int_bus = clk ? 1'bz : 1;
80
// assign(pull0, pull1) Int_bus = clk && ~(Test1 || ext_to_int_q) ? 0 : 1'bz;
81
// assign(pull0, pull1) Int_bus = (Res_to_DL && ~Res) ? 0 : 1'bz;
83
// // DataBridge logic
84
// assign(pull0, pull1) Int_bus = (~dv_q) ? (DataOut ? 0 : 1'bz) : 1'bz;
86
// // Drive DL and D buses up with weak strength to simulate the pre-charge.
87
// assign (weak0, weak1) Ext_bus = 1;
88
// assign (weak0, weak1) Int_bus = 1;
90
// The logic above can also be expressed, in a higher level, as:
92
assign Ext_bus = ~clk ? 1
93
: RD_hack && ~WR_hack ? 1'bz
94
: ~RD_hack && WR_hack ? int_to_ext_q
97
assign Int_bus = ~clk ? 1
98
: RD_hack && ~WR_hack ? ext_to_int_q
99
: ~RD_hack && WR_hack && DataOut ? dv_q
100
: ~RD_hack && WR_hack ? 1'bz
104
endmodule // data_mux_bit