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.
Yeah, I stand corrected. I noticed that clk_38 and went "huh?".
 

A similar SPI interface, slightly tidied up.
Code:
LIBRARY ieee;
USE ieee.std_logic_1164.all;

ENTITY DAC_OUT IS
   PORT
   (
      CLK      : IN STD_LOGIC;
      RESET    : IN STD_LOGIC;
      data     : IN STD_LOGIC_VECTOR(15 downto 0);
      dav      : IN STD_LOGIC;
      SCK      : OUT STD_LOGIC;
      nCS      : OUT STD_LOGIC;
      MOSI     : OUT STD_LOGIC
   );
END DAC_OUT;

ARCHITECTURE rtl OF DAC_OUT IS
   SIGNAL sr      : STD_LOGIC_VECTOR(15 downto 0);
   SIGNAL bitcnt  : INTEGER RANGE 0 TO 15;
   SIGNAL clkdiv  : INTEGER RANGE 0 TO 40;
   SIGNAL DACCLKi : STD_LOGIC;
BEGIN
   PROCESS(clk, reset)
   BEGIN
      IF reset = '1' THEN
         bitcnt <= 0;
         nCS <= '1';
         DACCLKi <= '0';
         clkdiv <= 0;
      ELSIF rising_edge(clk) THEN
         IF clkdiv < 38 THEN
            clkdiv <= clkdiv + 1;
         ELSE   
            clkdiv <= 0;
            IF dav = '1' AND bitcnt = 0 THEN
               DACCLKi <= '1';
               sr <= data;
               nCS <= '0';
               bitcnt <= 15;
            ELSIF bitcnt > 0 THEN
               DACCLKi <= NOT DACCLKi;
               IF DACCLKi = '0' THEN -- this is a rising edge
                  bitcnt <= bitcnt - 1;
                  IF bitcnt > 0 THEN
                     sr <= sr(14 downto 0) & "0";
                  ELSE
                     nCS <= '1';
                  END IF;
               END IF;
            ELSE
               DACCLKi <= '0';        
            END IF; 
         END IF;
      END IF;
   END PROCESS;
   SCK <= DACCLKi;
   MOSI <= sr(15);
END rtl;
 

Yeah, I stand corrected. I noticed that clk_38 and went "huh?".

that is an output, it's linked on ---> clock_38 <= oneUSClk;

That is why I didn't wanted to paste code as I am interested on principal and coding style more than have a code to do the SPI.

- - - Updated - - -

A similar SPI interface, slightly tidied up.
Code:
LIBRARY ieee;
USE ieee.std_logic_1164.all;

ENTITY DAC_OUT IS
   PORT
   (
      CLK      : IN STD_LOGIC;
      RESET    : IN STD_LOGIC;
      data     : IN STD_LOGIC_VECTOR(15 downto 0);
      dav      : IN STD_LOGIC;
      SCK      : OUT STD_LOGIC;
      nCS      : OUT STD_LOGIC;
      MOSI     : OUT STD_LOGIC
   );
END DAC_OUT;

ARCHITECTURE rtl OF DAC_OUT IS
   SIGNAL sr      : STD_LOGIC_VECTOR(15 downto 0);
   SIGNAL bitcnt  : INTEGER RANGE 0 TO 15;
   SIGNAL clkdiv  : INTEGER RANGE 0 TO 40;
   SIGNAL DACCLKi : STD_LOGIC;
BEGIN
   PROCESS(clk, reset)
   BEGIN
      IF reset = '1' THEN
         bitcnt <= 0;
         nCS <= '1';
         DACCLKi <= '0';
         clkdiv <= 0;
      ELSIF rising_edge(clk) THEN
         IF clkdiv < 38 THEN
            clkdiv <= clkdiv + 1;
         ELSE   
            clkdiv <= 0;
            IF dav = '1' AND bitcnt = 0 THEN
               DACCLKi <= '1';
               sr <= data;
               nCS <= '0';
               bitcnt <= 15;
            ELSIF bitcnt > 0 THEN
               DACCLKi <= NOT DACCLKi;
               IF DACCLKi = '0' THEN -- this is a rising edge
                  bitcnt <= bitcnt - 1;
                  IF bitcnt > 0 THEN
                     sr <= sr(14 downto 0) & "0";
                  ELSE
                     nCS <= '1';
                  END IF;
               END IF;
            ELSE
               DACCLKi <= '0';        
            END IF; 
         END IF;
      END IF;
   END PROCESS;
   SCK <= DACCLKi;
   MOSI <= sr(15);
END rtl;

Thanks for this code first of all, my first impression woow is there any more, I did used lots of signals,stage machine, registers and you managed on one process! :) so I create a test bench and tested, there is perhaps something to set to mosi when ncs is 1 at the beginning, I think it has to be with "sr" also ncs never seen to go high again after transmission end, but I notice you took this from the shell and share it and I am great full.
 

That is why I didn't wanted to paste code as I am interested on principal and coding style more than have a code to do the SPI.
It seem like reviewing the code was necessary to discuss synchronous design principles and coding style.

It has been clarified that generated (or "ripple") clocks should and can be avoided. Below this level of synchronous design principles there's a wide subject of coding style, e.g. how to code states and state machines, how many processes are good for a clear and readable code, suitable data types, etc.

I think I illustrated my personal preference in this regard, few processes, not more state variables than necessary, use integers for internal counters.
 
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.

I created that new all in one code from the only purpose to show to people where asking for code, I know may be easier to point an error by rewrite the code but I think you missed the thinking, that all code is an summary from 4 vhdl files. That is why there is extra function in the shift register that could be taken out, but that is what we may be missing the point. Now I am in the learning exercise to implements things like multi block coding (maybe reusing standard blocks) and so on, for instance one SPI I have (this one support multiple master-slave) have 10 vhdl files (I didnt write it), that was the reason I created another post regarding this issue is maybe there is a good principle design to complex interface.

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

Yes I was surprised when I saw your code and I have commend it, but it will be very hard to scale from you code to include more functionality to it, I am sure you could end up adding more control signals a condition stages but I am sure it will get very messy to visualize and debug, do you think?
 
Last edited:

Yes I was surprised when I so your code and I have commend it, but it will be very hard to scale from you code to include more functionality to it, I am sure you could end up adding more control signals a condition stages but I am sure it will get very messy to visualize and debug, do you think?
Not all all. Coding style is however a subjective category and I don't claim a solution that fits everyone's needs.

The shown code is extracted from a "production" design, stripped down to the actual functionality implemented respectively intended (I didn't verify the correct operation of your code) in your design. In so far it's a bit curious that you are discussing additional functionality that isn't in your code, but on the other hand have a lot of states etc. in your code that aren't needed at all. I think, it doesn't make sense to write a threefold number of code lines just in case.

Regarding debugging. I don't know if you finally managed to make your code work. But from the previous posts, I got the impression that it's far from easy to debug.
 
Regarding debugging. I don't know if you finally managed to make your code work. But from the previous posts, I got the impression that it's far from easy to debug.

Its true, I give you that, when you are coding with multi block and something is does not work I feel like a headache is coming when you change an condition and you have not clue where lie the error I feel I have to start to trace block by block and can be difficult to visualize.

- - - Updated - - -

UPDATE:

Even I though about my original code implement the prinsiple as some could see, I was un easy about the glinch on the clock/38.
So I went further and look at the code again and check timing and even though the ready-out could be something like enbale chip and
clock/38 is delay one clock cycle from the process it works well with the especification as we want to tell enable on and then a positive
edge from clock/38 to second divice in bit 2 the shifting is wrong again as shift is delay on clock cycle.

I sort it this by creating a secondary tick signal by the counter a bit earlier to the clock/38 to compensate delay

Also that glitch at the end of bit "8" transmitting I sort it by making the stage machine to move in with a new condition when counter is 8 and new tick signal is up also to compensate that delay introduced by stage machine into "counter_reset" signal.

I also try to make counter_reset evaluation on next_reg and current but that did mess all up, so I didn't carry on further that route, but I think could also be one way to sort that delay between idle and data stage, right?


So you see my point here very easy illustrate, I use the principal and create all the requirement blocks and then there is delays issue, which I have kind flick creating new signals new conditions.

- - - Updated - - -

UPDATE 2:
For the people want to see code, here it's.

Code:
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_tick2:	std_logic:='0';
signal sclk_out_tick3:	std_logic:='0';
signal sclk_out_tick_p:	std_logic:='0';
signal sclk_out_tick_p2:	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,sclk_out_tick3) --leave_signal 
begin
	case CurrentState is
	
		when idle =>
		if (W = '1') then
		NextState <= send_data;
		else
		NextState <= idle;
		end if;
		
		when send_data =>
		if ((sclk_out_tick3 = '1') and (counter_8clk = "1000" ))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 -- 38
				clkCount <= "000000";
				oneUSClk <= not oneUSClk;
				sclk_out_tick1 <= '1';
			elsif (clkCount = "100100") then	--36
					sclk_out_tick2 <= '1';
					clkCount <= clkCount + 1;
			elsif (clkCount = "100101") then	-- 37
					sclk_out_tick3 <= '1';
					sclk_out_tick2 <= '0';
					clkCount <= clkCount + 1;		
			else
				clkCount <= clkCount + 1;
				sclk_out_tick1 <= '0';
				sclk_out_tick2 <= '0';
				sclk_out_tick3 <= '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';  
sclk_out_tick_p2 <= '1' when sclk_out_tick2 = '1' and oneUSClk = '0' else '0'; 				
--**************************************************************************
--  shift 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_p2 = '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;

- - - Updated - - -

UPDATE3:
Sorry looked again and it was an error with bit 8 so here is the fix, more of the same to be honest:
Code:
	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 -- 38
				clkCount <= "000000";
				oneUSClk <= not oneUSClk;
				sclk_out_tick3 <= '0';
				sclk_out_tick1 <= '1';
			elsif (clkCount = "100100") then	--36
					sclk_out_tick2 <= '1';
					clkCount <= clkCount + 1;
					sclk_out_tick3 <= '0';
			elsif (clkCount = "100101") then	-- 37
					sclk_out_tick3 <= '1';
					sclk_out_tick2 <= '0';
					clkCount <= clkCount + 1;		
			else
				clkCount <= clkCount + 1;
				sclk_out_tick1 <= '0';
				sclk_out_tick2 <= '0';
				sclk_out_tick3 <= '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';  
sclk_out_tick_p2 <= '1' when sclk_out_tick2 = '1' and oneUSClk = '0' else '0'; 	
sclk_out_tick_p3 <= '1' when sclk_out_tick3 = '1' and oneUSClk = '0' else '0';

and move stage with sclk_out_tick_p3 and counter to 8 in stead.
 

Its a shame that lots of people have seen this post and only a few have comment/help :-(!

Today I implemented the same code onto 4 hdl files, one universal counter, universal_shift register, clock/38, and top with stage machine and logic.

I got to say it was a bit hard, I need to look at my previous posted file.

I could comment if I implement the counter reset on the top file (trying not to modified the others blocks) I did something like:

cnt_reset <= '1' when (counter_8clk = "1000") or (reset ='1') or (counter_reset = '1') else '0';

But like that as its evaluate in the process counter result in an error the counter never get to 8, but its very strange as If I look into the simulation "cnt_reset" never change but the counter goes from 7 to 0. (extra note: I still think clear on a 8 can be removed as the stage machine reset it by "counter_rese" signal, I just wanted to add the extra condition that that counter never goes to 9 if its left in free running)

Also I kind of try to add the negation of that reset signal by adding a not in the port mapping (), it seen to work on Synthesize and simulation, never have tested something like it on hardware, is that fine?.

Code:
upcnt8_module : upcnt8
 port map (     
				clk => clk ,
				clr => not cnt_reset ,
				cnt_en => sclk_out_tick_p_sync_ad_cnt,
				qout => counter_8clk);
 

cnt_reset <= '1' when (counter_8clk = "1000") or (reset ='1') or (counter_reset = '1') else '0';
Looks like a step backwards. What's cnt_reset exactly doing?
Are you pulling the design wide initial reset into the clock edge sensitive code or are you applying asynchronous reset in regular conter operation? Both won't be a good idea.

Apart from this point, nothing to discuss in your post, I think.
 

Looks like a step backwards. .

:) , no I am doing all exactly the same as post #47, but all in multi-blocks
What's cnt_reset exactly doing?

The code:
Code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.std_logic_arith.all;

entity upcnt8 is
     port(
         cnt_en       : in STD_LOGIC;                        -- Count enable                       -- Load line enable
         clr          : in STD_LOGIC;                        -- Active low clear
         clk          : in STD_LOGIC;                        -- Clock
         qout         : inout STD_LOGIC_VECTOR (3 downto 0)
        
         );
end upcnt8;

architecture Behavioral of upcnt8 is
constant RESET_ACTIVE : std_logic := '0';
signal q_int : UNSIGNED (3 downto 0);
begin
     process(clk, clr)
     begin
          
          -- Clear output register
          if (clr = RESET_ACTIVE) then
           q_int <= (others => '0');
           
      -- On falling edge of clock count
      elsif (clk'event) and clk = '1' then
           if cnt_en = '1' then
                q_int <= q_int + 1;
           end if;
      end if;

     end process;

     qout <= STD_LOGIC_VECTOR(q_int);

end Behavioral;

That is the 4 bits counter which now its in one block by its own.

and its mapped as
Code:
upcnt8_module : upcnt8
 port map (     
				clk => clk ,
				clr => not cnt_reset ,
				cnt_en => sclk_out_tick_p_sync_ad_cnt,
				qout => counter_8clk);


Are you pulling the design wide initial reset into the clock edge sensitive code or are you applying asynchronous reset in regular conter operation? Both won't be a good idea.

there counter (4 bits) will reset when reset = 1 (initial reset), counter_reset = '1' which is a stage machine condition (reset on in idle) as the stage machine will move from data to idle in bit 8 so if will never get to 9 as idle stage reset. I also though would be good idea to reset that counter with an evaluation of its own counter which is signal "counter_8clk" but that is what of the condition you are talking about "applying asynchronous reset in regular counter operation" I did it on post #47 in Update 2 at:

Code:
if (counter_8clk = "1000") then	        --  Terminal Count value
			counter_8clk <= (others=>'0');
			counter_8clk_tick <= '1';
		else		...............

Why this reset is not a good idea?
 
Last edited:

no I am doing all exactly the same as post #47, but all in multi-blocks
You are doing not the same. Previously, your counter has been counting 0,1,2 ... 7, 8, 0 ,1 now it's 0,1,2 ... 7, 0 ,1

That's a result of the asynchronous reset on counter_8clk = "1000".

But the full truth is, you had already asynchronous resets by signal counter_reset (on CurrentState = idle) in your previous code. That's also bad coding style that I wasn't aware of before.

There are different reasons why asynchronous reset of registers should be avoided, to mention the worst one, logic glitches can cause an unwanted reset when multiple inputs to the reset condition change at the same time. It's even possible that only some register bits are reset and others keep their previous value. In so far my valuation of the code in post #35 has to be narrowed.
 

You are doing not the same. Previously, your counter has been counting 0,1,2 ... 7, 8, 0 ,1 now it's 0,1,2 ... 7, 0 ,1

That's a result of the asynchronous reset on counter_8clk = "1000".

Sorry I see now the problem I know if you do something like counter_8clk > "1000" it does count until 8, now I can see previous it was a if condition with a process and now it a logic evaluation so as soon as we are in 8 will reset right the way.

But the full truth is, you had already asynchronous resets by signal counter_reset (on CurrentState = idle) in your previous code. That's also bad coding style that I wasn't aware of before.

There are different reasons why asynchronous reset of registers should be avoided, to mention the worst one, logic glitches can cause an unwanted reset when multiple inputs to the reset condition change at the same time. It's even possible that only some register bits are reset and others keep their previous value. .

there is going to be one type of reset one way or another one, do you suggest loading process? but bare in mind that reset is kind of loading, right?

Is that why you want to decrement and not increment?

In so far my valuation of the code in post #35 has to be narrowed.

Sorry what do you mean? you have to take off the good comments? :-/
 


Sorry what do you mean? you have to take off the good comments?
The code had been certainly improved. In so far it deserves a good comment. But it's not fully synchronous as it should be.
 


Thanks! I can see clearly sync reset but I need to read some more on the async one in order to be able to implement it

- - - Updated - - -

The code had been certainly improved. In so far it deserves a good comment. But it's not fully synchronous as it should be.

Now I have changed a few things, one I do count inverse but from that to force 0 or a value Its a bit of semantic so I need to learn a bit more to actually try to implemented with async reset.
Also I left out that reset on counter match and leave the stage machine to set values.

I also read the "J-K" comments in post #25 and add it on board, but I cannot see why would I do this:

- 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
Kevin Jennings

I using "ready" to tell you its ready to write again, which I added as extra as I believe is about this post scope. Is that what you intended with that flag turn to 0 half way through? a ready flag?

For the people like so code here its:

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

entity spi_forum2 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_forum2;

architecture Behavioral of spi_forum2 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_tick2:	std_logic:='0';
signal sclk_out_tick3:	std_logic:='0';
signal sclk_out_tick_p:	std_logic:='0';
signal sclk_out_tick_p2:	std_logic:='0';
signal sclk_out_tick_p3:	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,sclk_out_tick_p3) --leave_signal 
begin
	case CurrentState is
	
		when idle =>
		if (W = '1') then
		NextState <= send_data;
		else
		NextState <= idle;
		end if;
		
		when send_data =>
		if ((sclk_out_tick_p3 = '1') and (counter_8clk = "0000" ))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') then
			counter_8clk <= "1001";
		counter_8clk_tick <= '0';	
	elsif (counter_reset = '1') then
		counter_8clk <= "1000";
		counter_8clk_tick <= '0';
		elsif (counter_reset = '1') then
		elsif (clk = '1' and clk'event) then
	if (sclk_out_tick_p = '1') then
		if (counter_8clk = "0010") then	        --  Terminal Count value
			counter_8clk_tick <= '1';
			counter_8clk <= counter_8clk - 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"; --38
				sclk_out_tick1 <= '1';
				OneUSClk <= '0';
		elsif (clk = '1' and clk'event) then
			if(clkCount = "100110") then -- 38
				clkCount <= "000000";
				oneUSClk <= not oneUSClk;
				sclk_out_tick3 <= '0';
				sclk_out_tick1 <= '1';
			elsif (clkCount = "100100") then	--36
					sclk_out_tick2 <= '1';
					clkCount <= clkCount + 1;
					sclk_out_tick3 <= '0';
			elsif (clkCount = "100101") then	-- 37
					sclk_out_tick3 <= '1';
					sclk_out_tick2 <= '0';
					clkCount <= clkCount + 1;		
			else
				clkCount <= clkCount + 1;
				sclk_out_tick1 <= '0';
				sclk_out_tick2 <= '0';
				sclk_out_tick3 <= '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';  
sclk_out_tick_p2 <= '1' when sclk_out_tick2 = '1' and oneUSClk = '0' else '0'; 	
sclk_out_tick_p3 <= '1' when sclk_out_tick3 = '1' and oneUSClk = '0' else '0';
--**************************************************************************
--  shift 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_p2 = '1' ) 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;
 

Sorry I picked the wrong code in the previous code here is the right one:

Code:
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_tick2:	std_logic:='0';
signal sclk_out_tick3:	std_logic:='0';
signal sclk_out_tick_p:	std_logic:='0';
signal sclk_out_tick_p2:	std_logic:='0';
signal sclk_out_tick_p3:	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,sclk_out_tick_p3) --leave_signal 
begin
	case CurrentState is
	
		when idle =>
		if (W = '1') then
		NextState <= send_data;
		else
		NextState <= idle;
		end if;
		
		when send_data =>
		if ((sclk_out_tick_p3 = '1') and (counter_8clk = "0000" ))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') then
			counter_8clk <= "1001";
		counter_8clk_tick <= '0';	
	elsif (counter_reset = '1') then
		--counter_8clk <= (others=>'0');
		counter_8clk <= "1000";
		counter_8clk_tick <= '0';
		elsif (counter_reset = '1') then
		elsif (clk = '1' and clk'event) then
	if (sclk_out_tick_p = '1') then
		if (counter_8clk = "0010") then	        --  Terminal Count value
		--	counter_8clk <= (others=>'0');
			counter_8clk_tick <= '1';
			counter_8clk <= counter_8clk - 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,clkCount2,counter_reset2)
    	begin
		if (reset = '1') then
			clkCount2 <= "100111"; --38
				sclk_out_tick1_1 <= '1';
				OneUSClk2 <= '0';
		elsif (counter_reset2 = '1') then 
		clkCount2 <= "100111"; --38
		elsif (clk = '1' and clk'event) then
			if(clkCount2 = "100111") then -- 38
				oneUSClk2 <= not oneUSClk2;
				clkCount2 <= clkCount2 - 1;
				sclk_out_tick3_1 <= '0';
				sclk_out_tick1_1 <= '1';
		elsif (clkCount2 = "000010") then	--2
					sclk_out_tick2_1 <= '1';
					clkCount2 <= clkCount2 - 1;
					sclk_out_tick3_1 <= '0';
			
			elsif (clkCount2 = "000001") then	-- 37
					sclk_out_tick3_1 <= '1';
					sclk_out_tick2_1 <= '0';
					clkCount2 <= clkCount2 - 1;		
			else
				clkCount2 <= clkCount2 - 1;
				sclk_out_tick1_1 <= '0';
				sclk_out_tick2_1 <= '0';
				sclk_out_tick3_1 <= '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';  
sclk_out_tick_p2 <= '1' when sclk_out_tick2 = '1' and oneUSClk = '0' else '0'; 	
sclk_out_tick_p3 <= '1' when sclk_out_tick3 = '1' and oneUSClk = '0' else '0';			
--**************************************************************************
--  shift 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_p2 = '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:

Thanks! I can see clearly sync reset but I need to read some more on the async one in order to be able to implement it

As long as that means that you will apply a synchronizer to your async reset input, everything should be fine.
You really really don't want an async de-assert of your reset because that would result in all sorts of trouble. But no need for me to ramble on about it, those papers cover all that. For the impatient: search for word "de-assert" in those pdf's.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top