I need to write to a register from 2 sources.. in this case, a pci host
and a microcontroller. The 2 will never access the register at the same time (basically once the PCI is done , it hands it over the other host, which will then have exclusive access until it's finished).
Since the clock domains are different, I can't just have multiple
processes writing to the same register..
always @(posedge pciclk or negedge nrst)
if pci_wr & pci_addr == 0
cntl_reg = pci_data
always @(posedge mcclk or negedge nrst)
if mc_wr & mc_addr == 0
cntl_reg = mc_data
So how is this typically done? Not sure if this a fundamental architectural question, or just a syntax question on how to write the sensitivity list.
Best Answer
The practical FPGA register (a set of D flip-flops) only has one clock pin so it serves exactly one clock domain. Keep this low-level hardware in mind when writing HDL code.
When a signal crosses from one clock domain into another, it's common to use a pipeline of three registers, with the first stage in the source clock domain and the second and third registers in the destination clock domain. This causes some predictable latency, but avoids race conditions and undefined behavior.
Synchronize pci_data, pci_wr, and pci_addr into the mcclk clock domain. For example:
Synchronize mc_data, mc_wr, and mc_addr into the pciclk clock domain. For example:
You will have one register in the pciclk clock domain, and another register in the mcclk clock domain. Both registers have the same data after the signal propagates across the clock domain. For example, the register on the pci side might look like this:
Also note the use of non-blocking assignment <= to help the synthesis tool recognize that you're requesting a set of D flip flops. The verilog
register
keyword is just a data type, it doesn't necessarily always result in synthesizing a D flip-flop.