|
@@ -0,0 +1,321 @@
|
|
|
+//
|
|
|
+// 7474 flip flop emulation using a fast clock to emulate asynchronous logic
|
|
|
+//
|
|
|
+module ff_7474s
|
|
|
+ #(
|
|
|
+ parameter logic init = 1'b1
|
|
|
+ )
|
|
|
+ (
|
|
|
+ input fast_clk,
|
|
|
+
|
|
|
+ input d,
|
|
|
+ input c,
|
|
|
+ input s_n,
|
|
|
+ input r_n,
|
|
|
+
|
|
|
+ output q_p,
|
|
|
+ output q_n
|
|
|
+ );
|
|
|
+
|
|
|
+ reg c_q = 1'b1;
|
|
|
+ wire strobe = c & ~c_q;
|
|
|
+
|
|
|
+ // Handle the transient state, too (R# = S# = 0 => Q = Q# = 1)
|
|
|
+ reg q;
|
|
|
+ wire transient = ~r_n & ~s_n;
|
|
|
+ assign q_p = q | transient;
|
|
|
+ assign q_n = ~q | transient;
|
|
|
+
|
|
|
+ always @(posedge fast_clk)
|
|
|
+ begin
|
|
|
+ // Clock edge detect
|
|
|
+ c_q <= c;
|
|
|
+
|
|
|
+ if (~r_n)
|
|
|
+ q <= 1'b0;
|
|
|
+ else if (~s_n)
|
|
|
+ q <= 1'b1;
|
|
|
+ else if (strobe)
|
|
|
+ q <= d;
|
|
|
+ end
|
|
|
+endmodule // ff_7474s
|
|
|
+
|
|
|
+//
|
|
|
+// 74393 counter emulation using a fast clock to emulate a gated ripple clock
|
|
|
+//
|
|
|
+module ctr_74393s
|
|
|
+ #(
|
|
|
+ parameter bits = 4
|
|
|
+ )
|
|
|
+ (
|
|
|
+ input fast_clk,
|
|
|
+
|
|
|
+ input cp_n,
|
|
|
+ input mr,
|
|
|
+ output reg [bits-1:0] q
|
|
|
+ );
|
|
|
+
|
|
|
+ reg cp_n_q = 1'b0; // Edge detect
|
|
|
+ wire strobe = cp_n_q & ~cp_n;
|
|
|
+
|
|
|
+ always @(posedge fast_clk)
|
|
|
+ begin
|
|
|
+ cp_n_q <= cp_n;
|
|
|
+ if (mr) // Asynchronous reset
|
|
|
+ q <= 'b0;
|
|
|
+ else
|
|
|
+ q <= q + strobe;
|
|
|
+ end
|
|
|
+endmodule // ctr_74393s
|
|
|
+
|
|
|
+
|
|
|
+//
|
|
|
+// 74155 decoder emulation
|
|
|
+//
|
|
|
+module dc_74155 #(
|
|
|
+ parameter bits = 2,
|
|
|
+ parameter outs = 1 << bits
|
|
|
+ ) (
|
|
|
+ input e,
|
|
|
+ input [bits-1:0] a,
|
|
|
+ output reg [outs-1:0] q_n
|
|
|
+ );
|
|
|
+
|
|
|
+ always_comb
|
|
|
+ begin
|
|
|
+ for (int i = 0; i < outs; i++)
|
|
|
+ begin
|
|
|
+ logic [bits-1:0] ii;
|
|
|
+ ii = i;
|
|
|
+ q_n[i] = ~(e && a == ii);
|
|
|
+ ii++;
|
|
|
+ end
|
|
|
+ end
|
|
|
+endmodule // dc_74155
|
|
|
+
|
|
|
+//
|
|
|
+// Smartaid Magnum asynchronous ROM
|
|
|
+// Open-coded to allow synthesis as random logic
|
|
|
+//
|
|
|
+module samu15 (
|
|
|
+ input [8:0] a,
|
|
|
+ output reg [3:0] q
|
|
|
+ );
|
|
|
+
|
|
|
+ always_comb
|
|
|
+ casez (a[5:0])
|
|
|
+ 6'b0100_00: q = { 2'b11, ~a[6], 1'b1 }; // F, D
|
|
|
+ 6'b0100_?1: q = 4'b1001; // 9
|
|
|
+ 6'b0100_10: q = { 3'b100, a[8:7] == 2'b10 }; // 8, 9
|
|
|
+ 6'b0101_0?: q = 4'b1110; // E
|
|
|
+ 6'b0110_00: q = ~a[6] ? 4'hD : 4'h4; // D, 4
|
|
|
+ 6'b0111_10: q = { 3'b110, a[8:7] != 2'b10 }; // D, C
|
|
|
+ default: q = 4'b0100; // 4
|
|
|
+ endcase // casez (a[5:0])
|
|
|
+endmodule // samu15
|
|
|
+
|
|
|
+//
|
|
|
+// Smartaid Magnum; SRAM not included
|
|
|
+//
|
|
|
+module samagnum (
|
|
|
+ input fast_clk,
|
|
|
+ input stb_50us, // ~50 us fast_clk strobe
|
|
|
+ input clk,
|
|
|
+ input xmemwr_n,
|
|
|
+ input xmemfl_n,
|
|
|
+ output xmemfl_out_n,
|
|
|
+ output resin_n,
|
|
|
+ input [15:0] a, // Address from ABC-bus
|
|
|
+ output reg [15:0] a_out, // Possibly modified address
|
|
|
+ output a_map, // Use this map
|
|
|
+ output [7:0] dout,
|
|
|
+ output dout_oe // Use the data from dout
|
|
|
+ );
|
|
|
+
|
|
|
+ wire out_dir; // "Real life" bus switch (0 = out)
|
|
|
+
|
|
|
+ wire sram_we = xmemwr_n;
|
|
|
+ wire sram_oe;
|
|
|
+ wire sram_ce;
|
|
|
+ wire pwrgood_n = 1'b0; // From Q1/Q2
|
|
|
+
|
|
|
+ wire [1:0] eprom_ce;
|
|
|
+ wire eprom_oe;
|
|
|
+
|
|
|
+ wire [8:0] prom_a;
|
|
|
+ wire [3:0] prom_q;
|
|
|
+
|
|
|
+ assign prom_a[5:0] = a[15:10];
|
|
|
+ wire bank_sel;
|
|
|
+ wire [1:0] bank;
|
|
|
+
|
|
|
+ // Memory address translation (the actual memory is external)
|
|
|
+ assign a_map = (~xmemfl_n & ~out_dir) | (~sram_ce & ~sram_oe);
|
|
|
+
|
|
|
+ always_comb
|
|
|
+ begin
|
|
|
+ a_out = a;
|
|
|
+ if (a_map)
|
|
|
+ begin
|
|
|
+ a_out[15:14] = bank;
|
|
|
+ if (~eprom_ce[1])
|
|
|
+ a_out[13:10] = 4'b1110;
|
|
|
+ else if (~sram_ce)
|
|
|
+ a_out[13:11] = 3'b010;
|
|
|
+ else if (~eprom_ce[0])
|
|
|
+ a_out[13:12] = 2'b00;
|
|
|
+ end
|
|
|
+ end // always_comb
|
|
|
+
|
|
|
+ wire [7:0] u5_q;
|
|
|
+ wire [3:0] u7a_qn;
|
|
|
+ wire [3:0] u7b_qn;
|
|
|
+
|
|
|
+ wire nor_in_9_2;
|
|
|
+ wire nor_in_10_2;
|
|
|
+ wire nor_in_12_1;
|
|
|
+
|
|
|
+ wire u6d5a_q, u6d5a_qn;
|
|
|
+ wire u6d5b_q, u6d5b_qn;
|
|
|
+ wire u9e2l1a_q, u9e2l1a_qn;
|
|
|
+ wire u9e2l1b_q, u9e2l1b_qn;
|
|
|
+ wire u9e2h1a_q, u9e2h1a_qn;
|
|
|
+ wire u9e2h1b_q, u9e2h1b_qn;
|
|
|
+ wire u9e3a_q, u9e3a_qn;
|
|
|
+ wire u9e3b_q, u9e3b_qn;
|
|
|
+
|
|
|
+ // U3 74LS245
|
|
|
+ // Emulated using an output enable
|
|
|
+ assign dout_oe = ~out_dir & (~&eprom_ce | eprom_oe) & (~sram_ce | sram_oe);
|
|
|
+
|
|
|
+ // U4 74LS126
|
|
|
+ // Emulated by using OR with the tristate component
|
|
|
+ assign dout[7:5] = 3'b111;
|
|
|
+ assign dout[4] = ~nor_out2 | u5_q[2]; // U4A
|
|
|
+ assign dout[3] = ~nor_out2 | u5_q[3]; // U4C
|
|
|
+ assign dout[2] = ~nor_out2 | u5_q[1]; // U4B
|
|
|
+ assign dout[1] = 1'b1;
|
|
|
+ assign dout[0] = ~nor_out2 | u5_q[4]; // U4D
|
|
|
+
|
|
|
+
|
|
|
+ // U5 74LS393
|
|
|
+ ctr_74393s u5a(.fast_clk(fast_clk),
|
|
|
+ .cp_n(clk), .mr(u9e3a_q), .q(u5_q[3:0]));
|
|
|
+
|
|
|
+ ctr_74393s u5b(.fast_clk(fast_clk),
|
|
|
+ .cp_n(u5_q[3]), .mr(u10c), .q(u5_q[7:4]));
|
|
|
+
|
|
|
+ // U7 74LS155
|
|
|
+ dc_74155 u7a(.e(prom_q[3]), .a(prom_q[1:0]), .q_n(u7a_qn));
|
|
|
+ dc_74155 u7b(.e(~sram_we), .a(prom_q[1:0]), .q_n(u7b_qn));
|
|
|
+ assign eprom_ce[1] = u7a_qn[0]; // 64 kbit
|
|
|
+ assign eprom_ce[0] = u7a_qn[1]; // 128 kbit
|
|
|
+ assign bank_sel = u7b_qn[3];
|
|
|
+
|
|
|
+ // U9 74LS260
|
|
|
+ wire u9a = ~(a[5] | a[7] | a[8] | a[9] | nor_in_12_1);
|
|
|
+ wire u9b = ~(xmemfl_n | nor_in_9_2 | nor_in_10_2 | prom_q[2]);
|
|
|
+ wire nor_out2 = u9b;
|
|
|
+
|
|
|
+ // U10 74LS00
|
|
|
+ wire u10a = ~prom_q[3];
|
|
|
+ wire u10b = ~(u5_q[2] & u5_q[4]);
|
|
|
+ wire u10c = ~(u9e3b_qn & u9e3a_qn);
|
|
|
+ wire u10d = ~(a[6] & u9a);
|
|
|
+ assign prom_a[6] = u10d;
|
|
|
+
|
|
|
+ // U11 74LS32
|
|
|
+ wire u11a = prom_q[3] | xmemfl_n;
|
|
|
+ wire u11b = nor_out2 | xmemfl_n;
|
|
|
+ wire u11c = xmemfl_n | u10a;
|
|
|
+ wire u11d = prom_q[2] | xmemfl_n;
|
|
|
+ assign xmemfl_out_n = u11a;
|
|
|
+ assign eprom_oe = u11b;
|
|
|
+
|
|
|
+ // U12 74LS08
|
|
|
+
|
|
|
+ // This is an RC delay in the original; emulated here using
|
|
|
+ // an up/down counter
|
|
|
+ reg [2:0] u12b_rc_ctr = 3'd7;
|
|
|
+ reg u12b_rc = 1'b1;
|
|
|
+ wire u12b_rc_in = u9e2l1b_q;
|
|
|
+
|
|
|
+ always @(posedge fast_clk)
|
|
|
+ if (stb_50us)
|
|
|
+ begin
|
|
|
+ if (u12b_rc_in & ~u12b_rc)
|
|
|
+ begin
|
|
|
+ if (&u12b_rc_ctr)
|
|
|
+ u12b_rc <= 1'b1;
|
|
|
+ else
|
|
|
+ u12b_rc_ctr <= u12b_rc_ctr + 1'b1;
|
|
|
+ end
|
|
|
+ else if (~u12b_rc_in & u12b_rc)
|
|
|
+ begin
|
|
|
+ if (~|u12b_rc_ctr)
|
|
|
+ u12b_rc <= 1'b0;
|
|
|
+ else
|
|
|
+ u12b_rc_ctr <= u12b_rc_ctr - 1'b1;
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ //wire u12a = xmemfl_n & xmemfl_out_n; // Dead
|
|
|
+ wire u12b = u12b_rc & u9e3b_q;
|
|
|
+ wire u12c = u11c;
|
|
|
+ //wire u12d = 1'bx; // Unconnected
|
|
|
+ assign out_dir = u12c;
|
|
|
+
|
|
|
+ // U13 74HC32 (HC!)
|
|
|
+ wire u13a = pwrgood_n | u7a_qn[2];
|
|
|
+ //wire u13b = sram_we; // Dead
|
|
|
+ //wire u13c = pwrgood_n; // Dead
|
|
|
+ wire u13d = pwrgood_n | xmemfl_n;
|
|
|
+ assign sram_ce = u13a;
|
|
|
+ assign sram_oe = u13d;
|
|
|
+
|
|
|
+ // U15 82S131 decode PROM
|
|
|
+ assign prom_a[8:7] = bank;
|
|
|
+ samu15 u15 (.a(prom_a), .q(prom_q));
|
|
|
+
|
|
|
+ // U6_D5 74LS74
|
|
|
+ ff_7474s u6d5a(.fast_clk (fast_clk),
|
|
|
+ .d (xmemfl_n), .c (clk), .s_n (u9e3b_q), .r_n (1'b1),
|
|
|
+ .q_p(u6d5a_q), .q_n ());
|
|
|
+ assign nor_in_10_2 = u6d5a_q;
|
|
|
+
|
|
|
+ ff_7474s u6d5b(.fast_clk (fast_clk),
|
|
|
+ .d (nor_in_10_2), .c (clk), .s_n (u9e3b_q), .r_n (1'b1),
|
|
|
+ .q_p (u6d5b_q), .q_n());
|
|
|
+ assign nor_in_9_2 = u6d5b_q;
|
|
|
+
|
|
|
+ wire reset_bank = 1'b1;
|
|
|
+
|
|
|
+ // U9_E2_L1 74LS74
|
|
|
+ ff_7474s u9e2l1a(.fast_clk (fast_clk),
|
|
|
+ .d(a[1]), .c(bank_sel), .s_n(1'b1), .r_n(reset_bank),
|
|
|
+ .q_p(u9e2l1a_q), .q_n());
|
|
|
+ assign bank[0] = u9e2l1a_q;
|
|
|
+
|
|
|
+ ff_7474s u9e2l1b(.fast_clk (fast_clk),
|
|
|
+ .d(clk), .c(u11d), .s_n(u12b), .r_n(1'b1),
|
|
|
+ .q_p(u9e2l1b_q), .q_n(u9e2l1b_qn));
|
|
|
+
|
|
|
+ assign resin_n = ~u9e2l1b_qn;
|
|
|
+
|
|
|
+ // U9_E2_H1 74LS74
|
|
|
+ ff_7474s u9e2h1a(.fast_clk (fast_clk),
|
|
|
+ .d(a[0]), .c(bank_sel), .s_n(1'b1), .r_n(reset_bank),
|
|
|
+ .q_p(u9e2h1a_q), .q_n());
|
|
|
+ assign bank[1] = u9e2h1a_q;
|
|
|
+ // U9_E2_H1B unconnected
|
|
|
+
|
|
|
+ // U9_E3 74LS74
|
|
|
+ ff_7474s u9e3a(.fast_clk (fast_clk),
|
|
|
+ .d(clk), .c(u11d), .s_n(1'b1), .r_n(clk),
|
|
|
+ .q_p(u9e3a_q), .q_n(u9e3a_qn));
|
|
|
+
|
|
|
+ ff_7474s u9e3b(.fast_clk (fast_clk),
|
|
|
+ .d(1'b0), .c(u9e3a_q), .s_n(u10b), .r_n(1'b1),
|
|
|
+ .q_p(u9e3b_q), .q_n(u9e3b_qn));
|
|
|
+ assign nor_in_12_1 = u9e3b_qn;
|
|
|
+endmodule // samagnum
|