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.
// From Xilinx ISE 14.1 Language Templates
// Verilog | Synthesis Constructs | Coding Examples | Misc | Asynchronous Input Synchronization
module async_input_sync(
input clk,
(* TIG="TRUE", IOB="FALSE" *) input async_in,
output reg sync_out
);
(* ASYNC_REG="TRUE", SHREG_EXTRACT="NO", HBLKNM="sync_reg" *) reg [1:0] sreg;
always @(posedge clk) begin
sync_out <= sreg[1];
sreg <= {sreg[0], async_in};
end
endmodule
Synchronize pci_data, pci_wr, and pci_addr into the mcclk clock domain. For example:
wire [xxx] pci_mc_data; // pci_ signal in pciclk clock domain, source mc_data
wire pci_mc_wr; // pci_ signal in pciclk clock domain, source mc_data
wire [xxx] pci_mc_addr; // pci_ signal in pciclk clock domain, source mc_data
async_input_sync(pciclk, mc_data[xxx], pci_mc_data[xx]);
async_input_sync(pciclk, mc_wr, pci_mc_wr);
async_input_sync(pciclk, mc_addr[xxx], pci_mc_addr[xx]);
Synchronize mc_data, mc_wr, and mc_addr into the pciclk clock domain. For example:
wire [xxx] mc_pci_data; // mc_ signal in mcclk clock domain, source pci_data
async_input_sync(mcclk, pci_data[xxx], mc_pci_data[xx]);
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:
// All of these signals are in the pciclk clock domain
always @(posedge pciclk) begin
if (pci_wr & pci_addr == 0) begin
pci_cntl_reg <= pci_data;
end
if (pci_mc_wr & pci_mc_addr == 0) begin
pci_cntl_reg <= pci_mc_data;
end
end
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.