// nanoengine_if.v
// Gateway from nanoEngine expansion bus to on-chip FPGA local bus
// $Id$
// Larry Doolittle, LBNL
// llc-suite Copyright (c) 2004, The Regents of the University of
// California, through Lawrence Berkeley National Laboratory (subject
// to receipt of any required approvals from the U.S. Dept. of Energy).
// All rights reserved.
// Your use of this software is pursuant to a "BSD-style" open
// source license agreement, the text of which is in license.txt
// (md5sum a1e0e81c78f6eba050b0e96996f49fd5) that should accompany
// this file. If the license agreement is not there, or if you
// have questions about the license, please contact Berkeley Lab's
// Technology Transfer Department at TTD@lbl.gov referring to
// "llc-suite (LBNL Ref CR-1988)"
// Initial coding: August 2003
//
// Designed according to a two page PDF document from Bright Star,
// unfortunately not published on their web site, titled "Multiplexed
// Mode Timing". Other nanoEngine documentation at
// (http://www.brightstareng.com/arm/nanoeng.htm).
// Stripped out from the working adctest.v on the LBNL LLRF system,
// but updated to enforce stricter timing.
//
// Contrast with vxi_if.v
`timescale 1ns / 1ns
module nanoengine_if(
// pin names that connect to the physical nanoEngine expansion bus
inout [15:0] PD, // pin a
input CK_host, // pin b
input ALE_host, // pin c
input WE_host, // pin d
input RD_host, // pin e
input CS0_host, // pin f
output RDY_host, // pin g
output INT_host, // pin h
// magic interconnect names implement the local (on-chip) bus master
output host_clk, // interconnect
output reg [13:0] host_addr, // interconnect
output reg [15:0] host_data, // interconnect
input [15:0] host_read, // interconnect
output reg host_we, // interconnect
output reg host_re, // interconnect
output rst, // interconnect
input host_interrupt // interconnect
);
assign RDY_host = 1'b1;
`ifdef SIMULATE
reg rst2;
initial begin rst2=0; #5; rst2=1; #5; rst2=0; end
assign rst = rst2;
`else
assign rst = 0;
`endif
assign INT_host = host_interrupt; // copy interconnect to the pin
// buffer the clock
wire clk_hack;
IBUF u4( clk_hack, CK_host); // since CK_host is not a dedicated clock pad
BUFG u3( host_clk, clk_hack);
reg host_write_cycle, host_read_cycle;
reg host_re_mature, bus_drive;
reg [15:0] read_result;
// WE_host, RD_host, and ALE_host are all synchronous with host_clk.
// CS0_host is not, but it goes active (low) before all the other activity.
wire host_write_detect = (~WE_host) & (~CS0_host);
wire host_read_detect = (~RD_host) & (~CS0_host);
wire host_ale_detect = (ALE_host) & (~CS0_host);
wire host_we_lead = host_write_detect & ~host_write_cycle;
wire host_re_lead = host_read_detect & ~host_read_cycle;
always @(posedge host_clk) begin
if (host_ale_detect) host_addr <= PD[15:2];
host_write_cycle <= host_write_detect;
host_we <= host_we_lead; // single cycle only
if (host_we_lead) host_data <= PD;
host_read_cycle <= host_read_detect;
host_re <= host_re_lead; // single cycle only
if (host_re_lead) read_result <= host_read;
bus_drive <= (host_re_lead | bus_drive ) & host_read_detect;
end
// Three-state bus
assign PD = (bus_drive & host_read_detect) ? read_result : 16'hZZZZ;
endmodule