The data sheet specifies that ADDR to DATA is 12ns max, while Gbar to DATA is 6ns.
Since Gbar is delayed 7ns from ADDR, it controls when data appears for the first
access. The timing of DATA for the second access is determined by when the new
address (A2) becomes stable.
The "conservative" timing for DATA after Gbar is deasserted depends on the question you're trying to answer. If you're interested in the hold time for DATA after Gbar is deasserted, the data sheet says the minimum time is 0ns. If you're interested in when DATA is tristated (so you can drive it from another chip), the data sheet says the maximum tristate time is 6ns.
ADDR must be stable for 0ns before Wbar is asserted. Asserting Wbar starts the
write process and the cell to be accessed must be specified before the process begins.
Wbar must be asserted (ie, held low) for at least 8ns assuming Gbar is deasserted.
The "active" edge of Wbar is the low-to-high transition -- that's when the data
is latched in the memory. ADDR must be setup for at least 10ns before the active
edge and DATA must be setup for at least 6ns. Both ADDR and DATA have zero hold time
after the active edge.
module test(clk,reset,addr[3:0],data[3:0],wbar,gbar,success,failure);
input clk,reset;
output [3:0] addr; // address for the memory chip
inout [3:0] data; // bidirectional data base
output wbar,gbar,success,failure;
// we'll use a counter as our state machine. Each memory access will be
// allocated 4 cycles. The address will change at the beginning of the
// first cycle and be held for all four cycles. On writes, Wbar will be
// asserted on the second cycle; DATA will driven with the write data on
// the second and third cycles. On reads, Gbar will be asserted on the
// second and third cycles, and the incoming memory data checked at the
// end of the second cycle. All the required timing constraints could
// be met using only 3 cycles, but, hey, if we make it 4, the counter
// will serve as our state register and we won't have to fool around with
// messy next state logic.
// state[1:0] -- counts through 4 cycles per memory access
// state[5:2] -- location to be read or written
// state[6] -- 0 if we're in pass 1 (writing), 1 if we're in pass 2 (reading)
// state[7] -- 0 if we're running, 1 if we're halted
reg [7:0] state;
reg test_failed; // keeps track of test result
always @ (posedge clk)
begin
if (reset)
begin state <= 0; test_failed <= 0; end
else if (!state[7])
state <= state + 1; // increment counter if we're still running
// if we're running in the read phase and this is the end of the second
// cycle, check to see if the memory is returning the correct data.
// if not, halt and indicate failure
if (!state[7] && state[6] && state[1:0]==2'b01 && data!=state[5:2])
begin state[7] <= 1; test_failed <= 1; end
end
// assert memory write enable during write phase on cycle 01
assign wbar = !(!state[7] && !state[6] && state[1:0]==2'b01);
// assert memory output enable during read phase on cycles 01 and 10
assign gbar = !(!state[7] && state[6] && (state[1:0]==2'b01 || state[1:0]==2'b10));
// memory address comes from the counter
assign addr = state[5:2];
// output data to the memory during the write phase on cycles 01 and 10
wire oe;
assign oe = !state[7] && !state[6] && (state[1:0]==2'b01 || state[1:0]==2'b10);
assign data = oe ? state[5:2] : 4'hz; // this is how we make a tristate output
// test result indicators -- asserted after test has halted
assign success = state[7] && !test_failed;
assign failure = state[7] && test_failed;
endmodule