Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Two clock domain- Problem!

Status
Not open for further replies.
By way of testing I just googled "ise power estimation"... That comes up with the right resources. Soooo?

Notably this link which was google hit #2. And #1 was the user guide. :p
 

I guess you are feeling it wrong! I did it as It was suggested but if you do an enable (with the second clock domain) to do an syncro design you have sort part of the problem you still have two domains clocks.
Several problems with this:
- You've assumed that there is a need for a second clock domain
- You haven't described what the problem is even if there is a second clock domain

I may be using the wrongs words or maybe none one has done a SPI from scratch.
- You are using the wrong words. The right words would be responding to what has been requested: actual design code and testbench, problem description and requirements. Until you provide all of that, you'll be aimlessly posting
- I'm sure many people here have "done a SPI from scratch", maybe just as a SPI slave, or maybe both master and slave. Again, you leave out important information: are you trying to do a SPI master? SPI slave?

Its very simple in theory I have a code much more robust than the one I am doing and it was created in 2000 that mean 13 years so far.
Anything in particular you're discussing here?

Its very simple if you forget about control of the interface and work on the interface is down to counter, universal shift register, stage machine, do I need to write you the code?
I would suggest that you not post anything more on this topic unless it includes:
- Design code and testbench
- Description of the problem that you observe
- Design requirements that you're trying to meet.

I'm not going to bother anymore with this thread until you've provided the above three. Good luck getting any sort of help from anyone without those three.

Kevin Jennings
 

Ok let start with the requirements we want to have a SPI interface to a separate device. For now let just say one way communication, and let forget for the time being to the control signals. so we are left with data buss which is serial as you may have guess it and clock signal and let package is 8 bits.
So we have faster clock which we can call it main_clock,
we have 38 division of that clock and we called clock/38 it has to be 19 clock circle down and 19 clock circle up. and need to be send to device two.
now we are left with block of data arriving parallel we want to send it serial.
also we can send data constantly without stopping 8 bits per package.
I my opining all that before was not relevant but as you asked here it is. Why?
Because I dont want you to give the code and dont want you to fix my code either. I am interested on learning how to code from understanding at least in this task. I have one SPI complete and example of serial interface.

I did what you have suggest and test it and it works but I some extend I was testing it at writing on

If I write on 1 us you can notice on sdin_out bit dd(0) is not right. but there is nothing wrong we have design it as you suggest but you still have the issue that the register is moving at another clock domain (by the tick enable). to illustrate I am attaching the simulation graphs.
Images:
Code:
http://obrazki.elektroda.pl/4318650400_1372972026.png
http://obrazki.elektroda.pl/3452409600_1372972026.png
http://obrazki.elektroda.pl/7974188300_1372972026.png

one here you have the effect of load if it does not wait for a tick of clock/38 (4318650400_1372972026.png)

on here I was writing a 385 ns (this is the first clock38 goes up ) that is not problem because that is in sync with clock38 tick. (https://obrazki.elektroda.pl/3452409600_1372972026.png)

and in here I have make load to wait for a tick signal from clock/38 to move to send_data (https://obrazki.elektroda.pl/7974188300_1372972026.png)

You can know notice that load is now one clock circle (clock/38). Clarifying this is now one issue from two clock domain but about the shift register two clock domain I have changed as suggested earlier. For those which need more data = main clock create a clock/38 and with clock/38 create clock38_tick signal which I have used to tick the register on the shift_register by enable evaluating a main clock.

Is this not enough?

- - - Updated - - -

By way of testing I just googled "ise power estimation"... That comes up with the right resources. Soooo?

Notably this link which was google hit #2. And #1 was the user guide. :p

Thanks! I never knew that was ISE, I looked on fast mode its seen I need Microsoft Office as its a macro I will need to sort that out as I have moved nearly totally from windows. I also I am not clear is the free ISE license support this feature, I haven't try but is not clear from the that user guide and the page it suggest it does but I notice that ISE say is running in little version I think the Free ISE is not the whole thing. Have anyone try it on a free web version? Thanks
 

The power estimation tool inside ISE you might want is under Tools => XPower Analyzer. You can run that after PAR. And again, googling on "XPower Analyzer" or "xilinx XPower Analyzer" gives you all sorts of handy information.

Oh yeah, also: https://www.youtube.com/watch?v=L02JGvLECuY

That should get you started.

- - - Updated - - -

Aaaaaah, so that is where your crop circles are coming from. Where you say "clock circle" the rest of us says "clock cycle". :p Best use clock cycles in future posts because then we understand wtf you are on about.
 

Ok let start with the requirements we want to have a SPI interface to a separate device. For now let just say one way communication, and let forget for the time being to the control signals. so we are left with data buss which is serial as you may have guess it and clock signal and let package is 8 bits.
So we have faster clock which we can call it main_clock,
we have 38 division of that clock and we called clock/38 it has to be 19 clock circle down and 19 clock circle up. and need to be send to device two.
There is still only one clock domain. Just because you're generating the SPI clock and it happens to be 1/38 the frequency of main_clock does not make it a 'clock domain'. At this point, it is simply a signal and it is not used to clock anything.

now we are left with block of data arriving parallel we want to send it serial.
also we can send data constantly without stopping 8 bits per package.
OK, but now you have to put some thought into the interface into your block. Since main_clock runs much faster than the SPI interface the thing that is external to your block which is providing the data to be written will need some form of 'wait' signal. I would suggest the following interface by your block of code to the external thing that is the source of the data that you are trying to send out the SPI interface
Code:
write: in std_ulogic; -- Command from outside that indicates that there is valid data to be written
write_data:  in std_ulogic_vector(7 downto 0); -- The parallel data that is to be serialized and written
wait: out std_ulogic; -- Output from your block to indicate that you cannot accept more data on this clock cycle

I my opining all that before was not relevant but as you asked here it is. Why?
Because you were unable to describe what problem you're having. To this point, you still haven't but at least this posting of yours is a bit more promising

Because I dont want you to give the code and dont want you to fix my code either. I am interested on learning how to code from understanding at least in this task. I have one SPI complete and example of serial interface.
OK...the SPI master (i.e. the one that generates the SPI clock) or the SPI slave (i.e. the one that receives the SPI clock)?

I did what you have suggest and test it and it works but I some extend I was testing it at writing on
If I write on 1 us you can notice on sdin_out bit dd(0) is not right. but there is nothing wrong we have design it as you suggest but you still have the issue that the register is moving at another clock domain (by the tick enable). to illustrate I am attaching the simulation graphs.
You did attach them...you didn't describe what the problem is but I'm guessing the problem is that your state machine went into the 'load' state for one clock cycle while keeping the SPI clock running thereby messing up the receiver since valid data was not received.

one here you have the effect of load if it does not wait for a tick of clock/38 (4318650400_1372972026.png)

on here I was writing a 385 ns (this is the first clock38 goes up ) that is not problem because that is in sync with clock38 tick. (https://obrazki.elektroda.pl/3452409600_1372972026.png)

and in here I have make load to wait for a tick signal from clock/38 to move to send_data (https://obrazki.elektroda.pl/7974188300_1372972026.png)

You can know notice that load is now one clock circle (clock/38). Clarifying this is now one issue from two clock domain but about the shift register two clock domain I have changed as suggested earlier. For those which need more data = main clock create a clock/38 and with clock/38 create clock38_tick signal which I have used to tick the register on the shift_register by enable evaluating a main clock.

Is this not enough?
Not really since you haven't stated the problem, I had to deduce it from the waveforms. You also haven't indicated where the other clock domain is, but again I'm deducing that you are thinking that sclk_out should be a clock domain (if you are using it to clock something then you need to stop)

Since you want to fix the code yourself (which is good), then we can only give generic suggestions but those should be good enough to get you on your way:
- If you are using anything other than 'main_clock' in your block of code then you will need to rewrite it to eliminate all other clocks.
- Consider a state machine that works something like this:
- Idle state transfers to senddata state when write input is active
- When in idle and write is received, initialize a counter that will count from 37 down to 0 (will be used to generate Sclk). Initialize another counter that counts from 7 down to 0 (will be used to keep track of which data bit you're sending)
- While in senddata state decrement the 37..0 counter by 1 until 0 then reset to 37 unless the 7..0 counter indicates that you've sent the last bit. At that condition, transfer back to idle state
- wait output is active whenever you're not in the idle state
- Sclk can be reset to 0 while in idle and then set it to 1 when you're making the transition out of idle; set it back to 0 halfway through the 37..0 counting

Notice that there is only one clock domain. The above description can be made to work so that there are no gaps if there is new data to send and it will come to a clean stop if there is nothing new to send.

Kevin Jennings
 
  • Like
Reactions: FvM

    FvM

    Points: 2
    Helpful Answer Positive Rating
Not really since you haven't stated the problem, I had to deduce it from the waveforms. You also haven't indicated where the other clock domain is, but again I'm deducing that you are thinking that sclk_out should be a clock domain (if you are using it to clock something then you need to stop)

Since you want to fix the code yourself (which is good), then we can only give generic suggestions but those should be good enough to get you on your way:
- If you are using anything other than 'main_clock' in your block of code then you will need to rewrite it to eliminate all other clocks.
- Consider a state machine that works something like this:
- Idle state transfers to senddata state when write input is active
- When in idle and write is received, initialize a counter that will count from 37 down to 0 (will be used to generate Sclk). Initialize another counter that counts from 7 down to 0 (will be used to keep track of which data bit you're sending)
- While in senddata state decrement the 37..0 counter by 1 until 0 then reset to 37 unless the 7..0 counter indicates that you've sent the last bit. At that condition, transfer back to idle state
- wait output is active whenever you're not in the idle state
- Sclk can be reset to 0 while in idle and then set it to 1 when you're making the transition out of idle; set it back to 0 halfway through the 37..0 counting

Notice that there is only one clock domain. The above description can be made to work so that there are no gaps if there is new data to send and it will come to a clean stop if there is nothing new to send.

Kevin Jennings

Sorry for the delay here I tried to spend some time traing to do it with a running "clock/38"
and its possible but I am getting delay introduced from the processor and shift register which creating an unwanted delay
which make all more difficult, I solved it by add delay process and some logic but I feel I was more trying to trick something
to make it works more that just trying to apply what I have learned, if you know what I mean?
Even though I was told in a post before it (clock/38) should be a running clock?


Let describe the interface, -its a SPI not more than 4M so that is why I divided by 38.
-One master one slave (I am creating the master)
-We have chip_enable, data or commands, clock/38, data, reset, also a power up routine.
-The other interface evaluate on the positive edge of the clock_38

So let implement what you suggested:

One Stage machine:
idle
send data. (Shall we stage send_comand?, and Stop?)

Step one I think good to define a bit the input port (I know I am leaving some stuff out for the time being):

in clock, in reset, in W, in data.
out clock_38, out data_out, enable_out,
Let Add "ready" to the interface above.

I have attached the Simulation, you can see some problems right the way. clock/38 is off sinc and loading into register is wrong too.

forum_SPI.png
 

The other interface evaluate on the positive edge of the clock_38
Sounds like you are still using two clock domains - needlessly. Timing problems can be expected.

I have attached the Simulation, you can see some problems right the way. clock/38 is off sinc and loading into register is wrong too.
Doesn't clarify much. We need the code and testbench to understand the details.
 

The clock_38 can be easily fix by making resent to "100110" and not to "000000"

here is simulation:
forum_SPI2.png

Now if you notice data out is wrong because shift register is ticking over by clock_38_tick1'event and clock_38_out_tick1='1'
as you can see from the simulation here:

forum_SPI3.png

Also I try to changed leading when reset not to "0" but as you see it not working.

I can see the problem which its in bit_transmitting "0" we want one clock_38 event, but we dont want the shift register to shift.

I suggest, add loading process to stage machine?
 

Wow, still not listening to suggestions? ploughing on ahead without trying the suggestions?
Good luck, you're going to keep hitting timing problems until you make it all one clock domain.
 

Sounds like you are still using two clock domains - needlessly. Timing problems can be expected.

Doesn't clarify much.

I am implementing as suggested it, but the need to clock/38 and second device assess data at positive edge of that clock is requirements I cannot change that.

- - - Updated - - -

UPDATE:

I though a bit more about that problem and I also suggest to move the stage machine with a tick signal not from the positive edge of clock/38 if not negative edge, I think that may also work, right?

I have not time to implement it now, so I will try to do it as soon as possible and update, Thanks
 

I am implementing as suggested it, but the need to clock/38 and second device assess data at positive edge of that clock is requirements I cannot change that.
It's OK to generate an external SPI clock in the code, but according to the rather slow SPI clock, everything can still work on the main clock's edge. Usually, as long as the SPI clock can be generated by dividing the main clock, you don't need to start a second clock domain.
 

Sorry about the thought of negative edge, that was wrong? the register would move in half cycle.

Ok I really change the code just to please some people about using tick and evaluate at main clock, to be honest I only have to change counter_to_8 as the rest was evaluated on that way.

Now I have tested some bits and there seen to be a problem with clock/38 when it reach end 8 bit. I dont have more time now but I will try to more soon.

here is the tb snap shot.

spi_forum.png
and
spi_forum2.png
 

I don't follow this penchant for extra clock domains... By way of testing how you do thing Mr Peter sir, how many clock domains do you need for the following:

- main part of design runs at 100 MHz
- SPI interface at lets say 20 MHz
- RS232 at 19k2 baud

Do you suddenly need 3 "clock domains"? Because the rest of us just might get the job done with a single clock domain.
 
Last edited:

The code, this time I put it all into one file, I would have liked it to do it in multi code block but here its:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity spi_forum is
generic(N: integer := 8);
port(
clk, reset, W: in std_logic;
data: in std_logic_vector(N-1 downto 0);
ready_out: out std_logic;
clock_38: out std_logic;
serial_out: out std_logic
);
end spi_forum;

architecture Behavioral of spi_forum is
--signals
signal counter_8clk : std_logic_vector(3 downto 0);
signal counter_8clk_tick : std_logic:='0';
signal counter_reset : std_logic:='0';
--clock_divided
signal clkCount: std_logic_vector (5 downto 0);
signal OneUSClk: std_logic:='0';
signal sclk_out_tick1: std_logic:='0';
signal sclk_out_tick_p: std_logic:='0';
signal idle_load: std_logic:='0';
-- shift register
signal r_reg: std_logic_vector(N-1 downto 0);
signal r_next: std_logic_vector(N-1 downto 0);
signal ctrl: std_logic_vector(1 downto 0);
-- ready
signal ready: std_logic:='0';
--**************************************************************************
-- STATE MACHINE SIGNAL DECLARATION:
type StateType is (
idle,
send_data
);

signal CurrentState, NextState : StateType;
--**************************************************************************

begin

COMB: process(CurrentState ,W , counter_8clk_tick) --leave_signal
begin
case CurrentState is

when idle =>
if (W = '1') then
NextState <= send_data;
else
NextState <= idle;
end if;

when send_data =>
if (counter_8clk_tick = '1') then
NextState <= idle;
else
NextState <= send_data;
end if;

end case;
end process COMB;


SEQ: process(reset, clk)
begin
if(reset = '1') then
CurrentState <= idle;
elsif (clk'event and clk = '1') then
CurrentState <= NextState;
end if;
end process SEQ;
with CurrentState select
counter_reset <= '1' when idle,
'0' when send_data,
'1' when Others;
with CurrentState select
ctrl <= "11" when idle,
"10" when send_data,
"11" when others;
with CurrentState select
ready <= '1' when idle,
'0' when send_data,
'0' when others;
with CurrentState select
idle_load <= '1' when idle,
'0' when others;
ready_out <= ready;
--**************************************************************************
-- 4 bit counter - 8 times count
--**************************************************************************

process(reset, clk, counter_reset,sclk_out_tick_p,counter_8clk)
begin
if((reset = '1') or (counter_reset = '1')) then
counter_8clk <= (others=>'0');
counter_8clk_tick <= '0';
elsif (clk = '1' and clk'event) then
if (sclk_out_tick_p = '1') then
if (counter_8clk = "1000") then -- Terminal Count value
counter_8clk <= (others=>'0');
counter_8clk_tick <= '1';
else
counter_8clk <= counter_8clk + 1;
counter_8clk_tick <= '0';
end if;
end if;
end if;
end process;


--**************************************************************************
-- 6 bit counter - 38 times count
--**************************************************************************
process (clk,reset,clkCount,counter_reset)
begin
if ((reset = '1') or (counter_reset = '1')) then
clkCount <= "100110";
sclk_out_tick1 <= '0';
OneUSClk <= '0';
elsif (clk = '1' and clk'event) then
if(clkCount = "100110") then
clkCount <= "000000";
oneUSClk <= not oneUSClk;
sclk_out_tick1 <= '1';
else
clkCount <= clkCount + 1;
sclk_out_tick1 <= '0';
end if;
end if;
end process;
clock_38 <= oneUSClk;
sclk_out_tick_p <= '1' when sclk_out_tick1 = '1' and oneUSClk = '1' else '0';
--**************************************************************************
-- shit register
--**************************************************************************

-- register
process(clk,reset,sclk_out_tick1,sclk_out_tick_p,idle_load,data)
begin
if (reset='1') then
r_reg <= data;
elsif (clk'event and clk='1') then
if ((sclk_out_tick_p = '1' and counter_8clk >= "000001" ) or (idle_load = '1')) then
r_reg <= r_next;
end if;
end if;
end process;
with ctrl select
r_next <=
r_reg when "00", --no op
r_reg(N-2 downto 0) & data(0) when "01", --shift left;
data(N-1) & r_reg(N-1 downto 1) when "10", --shift right;
data when others; -- load
serial_out <= r_reg(0);

end Behavioral;
 
Last edited:

*grin* I love the way you incorporated all the suggestions in this thread so far. Especially the bit where you persist in using a counter to generate your divide-by-38 clock. Well on your way to a good coding habit! XD




*cough* clock enables *cough*
 

*grin* I love the way you incorporated all the suggestions in this thread so far. Especially the bit where you persist in using a counter to generate your divide-by-38 clock. Well on your way to a good coding habit! XD

*cough* clock enables *cough*

If you notice I am using a tick signal from that counter! What do you suggest?

Also from the datasheet I am attaching a transition requirements:

spi_forum5.png

Would you still send a tick signal?
 

What is clock_38 in entity spi_forum?
 

*grin* I love the way you incorporated all the suggestions in this thread so far. Especially the bit where you persist in using a counter to generate your divide-by-38 clock. Well on your way to a good coding habit! XD
I don't agree.

Although you might not recognize it at first sight, Peter is now applying the previous suggestions to implement the SPI interface in a single clock domain. There are probably detail faults, but the basic topology is a reasonable synchronous design.

On the other hand, the bare SPI function can be probably implemented on 1/3 or 1/4 the number of code lines. There's also some garbage like an unsused shift left function. It will be ignored in synthesis and most likely doesn't cost resources but affects code readablity. There are also some inconsistencies, you have a word length parameter, but the internal bit count is fixed to eight.

Personally, I tend to put a trivial SPI interface like this in a single process.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top