Search code examples
vhdlclockfpga

Drive input clock to output


I've a module that have a 8bit input and a serial output, I want to serialize input data and synchronize it with a clock.

I want to set my data when falling edge then wait when clock rise, when clock fall again I set another data. I don't want to connect the directly reference clock to the output because when I don't use this module I want a 1 state on clock output.

I've tried this code:

process(Clock, ModuleReset)
    begin
        if ModuleReset = '0' then
            OutData <= '0';
            OutCK <= '0';
            counter <= 7;
        elsif falling_edge(Clock) then
                OutCK <= '0';
                OutData <= Data(counter);
        elsif rising_edge(Clock) then
                OutCK <= '1';
        end if;
end process;

The synthesizer gives me this error:

"Asynchronous load of non-constant data for SCK is not supported"

When I separate the code in two blocks like this:

process(Clock, ModuleReset)
    begin
        if ModuleReset = '0' then
            OutData <= '0';
            OutCK <= '0';
            counter <= 7;
        elsif falling_edge(Clock) then
                OutCK <= '0';
                OutData <= Data(counter);
end process;

process(Clock)
        if rising_edge(Clock) then
                OutCK <= '1';
        end if;
end process;

I have these two errors:

"Multiple non tristate drivers for net SCK"
"Unresolved tristate drivers for net SCK"

Another code I've tried is:

process(Clock, ModuleReset)
    if ModuleEN = '1' then
       OutCK <= Clock;
    end if;
    begin
        if ModuleReset = '0' then
            OutData <= '0';
            OutCK <= '0';
            counter <= 7;
        elsif falling_edge(Clock) then
                OutCK <= '0';
                OutData <= Data(counter);
        end if;
end process;

But the output clock looks strange with a different frequency.


Solution

  • Your last idea, which I understand ended up working for you, is sub-optimal. If your clock is slow, it should be fine, but I suggest you fix it nevertheless.

    if ModuleEN = '1' then
        OutCK <= Clock;
    else
        OutCK <= '1';
    end if;
    

    Yields combinational logic with the clock signals for the output. Having the clock used as a logic signal is never recommended, since clocks use clock paths which doesn't route well to general routing resources. The output signal will have potential glitches (very bad for an output interface!) and large delay/skew.

    Your first approach, to use a DDR register to forward the clock, is indeed the correct and best approach. With this scheme, your clock only use clock paths, and if both the registers outputing the clock and data are situated in IO blocks, they will have the same output delay with very little skew.

    You didn't specify the technology you're using, but I suggest you lookup how to write code that maps to DDR register for your synthesizer. Alternatively, you can manually instantiate the DDR output register primitive, likely ODDR for Xilinx or ALTDDIO_OUT for altera.