// $$$ : g2lanadp8019.v -- RTL8019AS lan adaptor for G2 bus. // // used circuit: lanadp8019.gif // used device: XC9572XL-VQ44 (Xilinx) // last update: 2007/3/15 // // device mapping: (byte access only) // base address + 0x00 .. 0x3e: RTL8019AS registers {even address} (lower byte mapping) // base address + 1: ID code 1 register '0x80' {read only} (upper byte mapping) // base address + 3: ID code 2 register '0x19' {read only} (upper byte mapping) // base address + 0x3f: control register {read/write} (upper byte mapping) // bit[7] : interrupt enable {active high} (read/write) // bit[6] : interrupt status {active high} (read only) // bit[5:1] : not use {read always '00000'} // bit[0] : reset {active high} (read/write) // // // date 2007/1/21 designed by jj1odm `timescale 1ns / 1ps module g2lanadp8019( input clk, // G2 bus system clock (25MHz) input aen, // G2 bus address enable (active low) input lben, // G2 bus direction and lower byte enable (active low) [change name: dir => lben] input uben, // G2 bus upper byte enable (active low) [change name: den => uben] inout [15:0] ad, // G2 bus address/data multiplexed bus (16 bit) output btan, // G2 bus bus termination A (active low) output btbn, // G2 bus bus termination B (active low) output irqn, // G2 bus interrupt (open drain active low) input resetn, // G2 bus reset (active low) output [4:0] sa, // RTL8019AS SA4 .. SA0: register address output iorn, // RTL8019AS IORB: I/O read strobe (active low) output iown, // RTL8019AS IOWB: I/O write strobe (active low) input int0, // RTL8019AS INT0: interrupt (active high) input iochrdy, // RTL8019AS IOCHRDY: bus wait ccontrol (active low) output rstdrv // RTL8019AS RSTDRV: chip reset (active high) ); parameter IOBASE_HIGH = 13'h1400; // I/O base high word address parameter IOBASE_LOW = 10'b0000000001; // I/O base low word address parameter ID_CODE_1 = 8'h80; // this adaptor ID code 1 (RTL'80'19AS) parameter ID_CODE_2 = 8'h19; // this adaptor ID code 2 (RTL80'19'AS) parameter G2_IDLE = 2'b00; // G2 bus idle state parameter G2_HI_ADDRESS = 2'b01; // G2 bus high address state parameter G2_DATA = 2'b11; // G2 bus data state parameter G2_END = 2'b10; // G2 bus end state parameter ACCESS_WIDTH = 3; // bus access width (ACCESS_WIDTH * 40nSEC) + 160nSEC reg int_enable = 1'b0; // interrupt enable flipflop (init 0) reg reset_ff = 1'b0; // reset flipflop (init 0) reg [1:0] g2bus_state = G2_IDLE; // G2 bus state machine register (init G2_IDLE state) reg aen_old = 1'b1; // G2 bus cycle detect register (init '1') reg [3:0] wait_cnt = 4'b0000; // G2 bus wait counter (init 0) reg bus_end = 1'b1; // bus end flag (active low) reg [15:0] g2reg; // for g2 bus tri-state logic reg [4:0] adrs; // SA[4:0] address latch register (5bit) reg direction; // direction latch register wire bus_valid; // bus cycle valid flag node wire [7:0] status_node; // status node // 'irqn' siganl assign assign irqn = (int_enable & int0) ? 1'b0 : 1'bz; // assign 'irqn' // 'rstdrv' siganl assign assign rstdrv = ~resetn | reset_ff; // assign 'rstdrv' // status node assign (control register) assign status_node[7] = int_enable; assign status_node[6] = int0; assign status_node[5:1] = 5'b00000; assign status_node[0] = reset_ff; // G2 bus termination control A/B (for byte access) assign btan = g2bus_state == G2_END ? bus_end : 1'bz; assign btbn = g2bus_state == G2_END ? bus_end : 1'bz; // RTL8019AS interface node (lower byte access) assign bus_valid = g2bus_state == G2_DATA | g2bus_state == G2_END; // bus valid flag assign sa = adrs; // RTL8019AS 'SA[4:0]' assign iorn = ~(direction & ~lben & uben & bus_valid); // RTL8019AS 'iorn' assign iown = ~(~direction & ~lben & uben & bus_valid); // RTL8019AS 'iown' // G2 bus tri-state buffer & ID code & control register logic (upper byte access) assign ad = g2reg; always @(resetn or bus_valid or uben or lben or direction or adrs or ad or status_node) begin if (resetn) begin if (bus_valid & ~uben & lben) begin // upper byte access if (adrs[4:1] == 4'b0000) begin // ID register 1/2 if (direction) begin // read g2reg[7:0] <= 8'hzz; g2reg[15:8] <= adrs[0] == 1'b0 ? ID_CODE_1 : ID_CODE_2; // read ID code 1/2 end else begin // write g2reg <= 16'hzzzz; end end else begin // control register if (direction) begin // read g2reg[7:0] <= 8'hzz; g2reg[15:8] <= status_node; // read control register (status_node) end else begin // write g2reg <= 16'hzzzz; int_enable <= ad[15]; // write interrupt enable f/f reset_ff <= ad[8]; // write reset f/f end end end else g2reg <= 16'hzzzz; end else begin // resetn == 0 then g2reg <= 16'hzzzz; reset_ff <= 1'b0; // init reset_ff (reset bit off) int_enable <= 1'b0; // init int_enable (interrupt disable) end end // G2 bus state machine (ignore: not this device or long word access) always @(posedge clk or negedge resetn) begin if (~resetn) begin g2bus_state <= G2_IDLE; // init 'g2bus_state' aen_old <= 1'b1; // init 'aen_old' bus_end <= 1'b1; // init 'bus_end' end else begin aen_old <= aen; // for negtive edge detect 'aen' // idle state if (g2bus_state == G2_IDLE) begin // negtive edge detect 'aen' & equal IOBASE_LOW if (~aen & aen_old & ad[15:6] == IOBASE_LOW) begin adrs <= ad[5:1]; // SA[4:0] (low word address) latch direction <= lben; // direcion latch wait_cnt <= 4'b0000; // init wait count bus_end <= 1'b1; // init bus end flag g2bus_state <= G2_HI_ADDRESS; // next state end end // high address state if (g2bus_state == G2_HI_ADDRESS) begin if (ad[12:0] == IOBASE_HIGH) g2bus_state <= G2_DATA; // this device then next state else g2bus_state <= G2_IDLE; // else return idle state end // data state if (g2bus_state == G2_DATA) begin if (~aen | (lben & uben)) g2bus_state <= G2_IDLE; // long access or wait timeout then return idle state else begin // normal bus access wait_cnt <= iochrdy ? wait_cnt + 4'b0001 : ACCESS_WIDTH - 2; if (wait_cnt == ACCESS_WIDTH) begin // check bus wait count bus_end <= 1'b0; // bus_end active low g2bus_state <= G2_END; // next state end end end // bus end state (for bus end pulse) if (g2bus_state == G2_END) begin bus_end <= 1'b1; // 1 clock bus_end high if (bus_end) begin // for fast rising edge (guard of hi-z) g2bus_state <= G2_IDLE; // return idle state end end end end endmodule // end of : g2lanadp8019.v