Follow along with the video below to see how to install our site as a web app on your home screen.
Note: This feature may not be available in some browsers.
Several problems with this: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.
- 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 postingI may be using the wrongs words or maybe none one has done a SPI from scratch.
Anything in particular you're discussing here?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.
I would suggest that you not post anything more on this topic unless it includes: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?
http://obrazki.elektroda.pl/4318650400_1372972026.png
http://obrazki.elektroda.pl/3452409600_1372972026.png
http://obrazki.elektroda.pl/7974188300_1372972026.png
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.
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.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.
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 interfacenow 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.
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
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 promisingI my opining all that before was not relevant but as you asked here it is. Why?
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)?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.
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.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.
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)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
Sounds like you are still using two clock domains - needlessly. Timing problems can be expected.The other interface evaluate on the positive edge of the clock_38
Doesn't clarify much. We need the code and testbench to understand the details.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.
Sounds like you are still using two clock domains - needlessly. Timing problems can be expected.
Doesn't clarify much.
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.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.
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;
*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*
What is clock_38 in entity spi_forum?
I don't agree.*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