--- Quote Start ---
The implementation for your design depends on the timing relationship between signals.
Even though ALE is called "Address Latch Enable", it does not have to be used as a latch enable, rather it can be used as a register enable.
The same goes for the read and write signals, if they are synchronous to the clock signal, you can use them combinatorially to create the address increment signal.
If the external bus is completely asynchronous to any clock you have access to, then the logic becomes quite different.
If you are using an FPGA that contains a PLL, then you can generally create an internal clock that can be used to oversample and synchronize external signals. If the processor interface has a wait-state control, then you can extend bus read/write cycles to meet timing.
So what bus are you trying to interface to?
Cheers,
Dave
--- Quote End ---
We are using a TS-7400 CPU board which basically has a 20 bit data IO bus that comes off of a CPLD on their board. They use a EP9302 processor chip which is running from the 14.7456 MHz crystal. However, I do not know about whats happening internal to that processor. The 9302 talks to their CPLD and manipulates the data IO bus. They also pass the 14 MHz clock signal through their CPLD (which ends up being the FPGA clk) and they can turn it off or on in the CPLD (which means there must be delays as it passes through their CPLD). We have decided to use 8 bits as a multiplexed addr/data bus and 3 other lines as ale, rd, and wr. Because of the number of IO lines we need from the FPGA its not practical to use more lines to interface to the TS7400.
So our code that runs on the TS7400 basically goes through this process:
Set the Data Direction Register (DDR) for DIO[7:0] to output.
Place the data on the data bus.
Set the ale (or wr) bit high.
Set the ale (or wr) bit low.
Read cycles would by like this:
Set the DDR for DIO[7:0] to input.
Set the rd bit high.
Read the DIO[7:0] data
Set the rd bit low.
By scope measurements I have determined that the rate that we can go through this process takes about 1us for each steo (depending on what instructions we need to execute). That means when writing (addr or data) the data will be on the DIO bus about 1 us before the rising edge of ale or wr and will be held there until about 1 us after the falling edge of ale or wr. We would read data in about 1 us after asserting rd. Seems like plenty of setup and hold time to me though the ale, wr, and rd are not necessarily synchronous with the clk signal.
The ale_clk in the code that I showed earlier is just a gated version of clk made like this:
assign ale_clk = (clk & ale);
In my inexperience I have been coding all register transfers using edge triggered blocks like this:
always_ff @ (posedge ale, negedge end_rd_or_wr)
begin
if (ale) addr_reg <= data_in;
else addr_reg <= addr_reg + addr_incr;
end
Would it be better in some cases to use logic levels, not egdes? And does that mean necessarily that its combinatorial logic rather that flip flops?