0
\$\begingroup\$

I have a Verilog block (Block A) that samples a serial signal with a relatively slow clock and then puts data in several registers based on the contents of the serial data.

Ultimately, these data need to go into several AXI slave register, since Block A is part of a larger AXI slave peripheral. A faster AXI clock drives another block (Block B) that handles the AXI transactions with the ARM core.

The sampling clock clocks the data into the Block A output registers, so these data are sitting there waiting to be placed in the AXI registers. (I think) I want some kind of multi-dimensional shift register to get these data into the AXI clock domain, something like:

...
input wire axi_clk,
input wire [5:0] data_in,
output wire [5:0] data_out,
...

reg [5:0] data_buf[2:0];
assign data_out = data_buf[2];
...

always @ (posedge axi_clk) begin
    data_buf[2:0] <= {data_buf[1:0], data_in};
end 

Instead of shifting one bit at a time every clock, I want to shift all 6 bits of data_buf in parallel each clock.

How should I set this up? Forgive the pseudocode; everything I've done so far has thrown errors, and I haven't found example code of what I'm trying to do, or confirmation that it's even possible with easily readable code.

PS - My team does not want to use SystemVerilog, but any version of VHDL or Verilog is acceptable.

\$\endgroup\$
  • \$\begingroup\$ Its advisable to use existing CDC cells/IPs. Designing one by ourselves at behavioral level, for eg. mux based synchroniser sometimes get optimised by synthesiser and still cause metastability. \$\endgroup\$ – Mitu Raj Dec 4 '19 at 10:05
1
\$\begingroup\$

To transport a multi bit vector. in parallel, between clock domains you should use an asynchronous FIFO. There is no other solution.
Do not try to design an asynchronous FIFO yourself, you are not ready for that. Instead instance one from the IP library. (Select one with independent read and write clock.)

The alternative is to transport the data bit-by-bit between the clock domains, using a single bit synchronizer. You said you don't want to do that, but it is a lot simpler. (For synchronizers look up the Xilinx xpm_cdc_array_single module or related cdc IP blocks.)

\$\endgroup\$
  • \$\begingroup\$ I'm not above doing bit-by-bit transport. I was more curious if there was a less tedious and error-prone way to code it. \$\endgroup\$ – schadjo Dec 3 '19 at 18:48
3
\$\begingroup\$

A FIFO will work in most if not all scenarios, but it is not the only solution for multi-bit clock domain crossing. Since the source data rate is low in your scenario when compared to the destination clock rate, it would be well suited to a handshake based system. You would not even need the acknowledge signal.

This article has a decent explanation of the main types of sychroniser and when they are each appropriate. Of course you would need to calculate for the worst case to make sure that there was no chance of missing any data in your particular case.

If your primary goal is to just get it working as quickly as possible, then a FIFO is a great tool, but I wanted to point out that there are others if you are having to scrape around for the leanest possible solution, as I usually am.

I don't understand your system fully, but what I'm imagining is a signal from the serial clock domain that toggles every time it finishes receiving a serial word, with the serial data also being latched into a parallel register at this point (again, in the serial clock domain). The toggling signal would then go through a simple two-register CDC element, where it would then feed an edge detector in the destination clock domain. The output of this edge detector would be a single-clock pulse, which would act as an enable signal for a data register in the destination clock domain, latching data directly from the serial clock domain parallel data register. Assuming your serial words are 8-bits wide, this should I think work with a serial bit clock up to almost double the parallel clock, but you would need to verify this of course.

\$\endgroup\$
  • \$\begingroup\$ For the handshake method, would you typically set the max delay for the data to be latched in to be less than the destination domain's clock period times the number of shift reg cycles used to buffer in the handshake bit? \$\endgroup\$ – schadjo Dec 4 '19 at 18:42
  • \$\begingroup\$ @schadjo see my edit, I hope this makes sense \$\endgroup\$ – scary_jeff Dec 5 '19 at 9:15
  • \$\begingroup\$ Got it. Thanks! \$\endgroup\$ – schadjo Dec 5 '19 at 13:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.