EmbDev.net

Forum: FPGA, VHDL & Verilog Evalueting problem condition in a verilog description


von Jonas E. (lerechercheur)


Attached files:

Rate this post
0 useful
not useful
Good morning all !!

I allow myself to turn to you today after several to seek the solutions 
without success.

Indeed I am in a rather material project where it is necessary to set up 
a dating device using a CPLD card.

One of the functions to perform is the description of an SPI. It is a 
question of describing the SPI in such a way that we can have 4 states 
at the output (00, 01, 10 and 11) and this according to two inputs which 
are the CS and the CLOCK. For this, I use verilog as language.

The problem is that I cannot evaluate this condition "end else if 
(CS_SPI == 1'b1 && i == 1'b0) begin
next_state = Trans_DataBit;
Count_Bit <= 4'b1100;
assign j = i;
end
in order to access the fourth state which would allow me to count down 
the 12 bits of data to be transmitted.
I enclose the description and the timing diagram where I forced the 
entries.

Thank you all in advance.
I have attached files for more details.

von Ale (Guest)


Rate this post
0 useful
not useful
One of the problems is that you are changing >> Count_Bit << in two 
separated always blocks, the simulator is kind of dead-locking.
Changing a register using blocking and non-blocking assignments is bad 
because it doesn't synthesize : you have like "two drivers" for the same 
signal, to put it simple.

always @(state or CS_SPI)
begin : MEF_SPI
next_state = 4'b0001;


//Count_Bit <=4'b0011;
//Count_DateBit <= 2'b11;
//Count_DataBit <= 4'b1111;

case(state)
...
  Trans_FlagBit : if(CS_SPI == 1'b1) begin
             next_state = Trans_DateBit;
             Count_Bit =4'b0011; 
             //i = 0;
             //i=3;
             //SPI_Select = 1;
             end
            
              
  Trans_DateBit : if(CS_SPI == 1'b1 && i!= 1'b0 ) begin
             next_state = Trans_DateBit; 
              Count_Bit =4'b0011;  
always @ (posedge CLK_SPI)
begin : Sorie_Logiq
if (reset == 1'b1) begin
  SPI_Select <= #1 2'b11;
end
else begin
  case(state)
...
   Trans_DateBit : begin
            SPI_Select <= #1 2'b01;
            Count_Bit <= Count_Bit -1;
            if(Count_Bit == 4'b0) begin
            i=0;
            end
            //Count_Bit <=4'b0011;


von Jonas E. (lerechercheur)


Attached files:

Rate this post
0 useful
not useful
Thank you Von Ale for your answer.

I have fixed that problem but I still have some.


1 ) One of them is that I have a delay at the begining of the 
SPI_Select. And that consequence of that delay is that the output is not 
corresponding with the state anymore.

2 ) The other one is that I am not suppose to have 1111 after 0000 when 
counting but I am having it and I don't really understang why.

I have attached the result of simulation and the description.
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    17:16:35 12/27/2019 
// Design Name: 
// Module Name:    Projet_Tech_SPI 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module Projet_Tech_SPI(
     CLK_SPI,
     CS_SPI,
    reset,
    Count_Bit,
    //Count_DateBit, 
    //Count_DataBit, 
     SPI_Select
    ); 

//------------- Déclaration des entrées -----------------------------
input   CLK_SPI, CS_SPI, reset;
//------------- Déclaration des sorties ----------------------------
output   [1:0] SPI_Select;
output   [3:0] Count_Bit;

//output   [1:0] Count_DateBit;
//output   [3:0] Count_DataBit;

//------------- Les ports d'entrées -------------------
wire    CLK_SPI, CS_SPI, reset;
//------------- Les ports de sorties ------------------
reg     [1:0] SPI_Select;
reg    [3:0] Count_Bit;
reg        i=1'b1;
//reg     [1:0] Count_DateBit;
//reg     [3:0] Count_DataBit;

//------------- Les constantes internes --------------------------- 
//assign CS_SPI = i;
parameter SIZE = 4;
parameter Idle = 4'b0001, Trans_FlagBit = 4'b0010, Trans_DateBit = 4'b0100, Trans_DataBit = 4'b1000 ;

//-------------Variables internes---------------------------
reg   [SIZE-1:0]          state        ;// Seq part of the FSM
reg   [SIZE-1:0]          next_state   ;// combo part of FSM
//----------Code startes Here------------------------
//assign next_state = fsm_function(state, Idle, Trans_FlagBit, Trans_DateBit, Trans_DataBit);


//---------- Logique séquentielle -----------------------------
always @ (posedge CLK_SPI)
begin : MEF_Seq
   if (reset == 1'b1) begin 
     state <=  #1  Idle;
   end else begin
     state <=  #1  next_state;
   end
end
//---------- Fin logique séquentielle -----------------------------

always @(state or next_state or CS_SPI or i )
begin : MEF_SPI
//next_state = 4'b0001;
 

//Count_Bit <=4'b0011;
//Count_DateBit <= 2'b11;
//Count_DataBit <= 4'b1111;

case(state)
  Idle         : if(CS_SPI == 1'b0) begin
             next_state = Idle;
             end else if (CS_SPI == 1'b1) begin
             next_state = Trans_FlagBit;
             end 
             
  Trans_FlagBit : if(CS_SPI == 1'b1) begin
             next_state = Trans_DateBit;
             //Count_Bit =4'b0011; 
             end            
              
  Trans_DateBit : if((CS_SPI == 1'b1) && (i!= 1'b0) ) begin
             Count_Bit =4'b0010; 
             next_state = Trans_DateBit; 
               
             end else if((CS_SPI == 1'b1) && (i==1'b0) ) begin 
             next_state = Trans_DataBit;
             //Count_Bit <=4'b1100;
             i=1'b1;
             end
             
  Trans_DataBit : if((CS_SPI == 1) && (i != 1'b0)) begin
             Count_Bit <=4'b1011;
             next_state = Trans_DataBit ;
             end else if((CS_SPI == 1) && (i == 1'b0)) begin
             next_state = Trans_FlagBit;
             i=1'b1;
            
             //SPI_Select = 0; 
            end 
            
  default     : next_state = Idle;
  
  endcase; 
end
 



//---------- La logique de sortie -----------------------------
always @ (posedge CLK_SPI)
begin : Sorie_Logiq
/*if (reset == 1'b1) begin
  SPI_Select <= #1 2'b11;
end
else begin*/
  case(state)
    Idle : begin
            SPI_Select <=  2'b11;

               end
   Trans_FlagBit : begin
                   SPI_Select <=  2'b00;
             //Count_Bit <=4'b0011;
             
                end
   Trans_DateBit : begin
            SPI_Select <=  2'b01;
            Count_Bit <= Count_Bit -1;
            if(Count_Bit == 4'b0) begin
            i=1'b0;
            end 
            //Count_Bit <=4'b0011; 
 
                end 
  Trans_DataBit : begin
            SPI_Select <=  2'b10;
            Count_Bit <= Count_Bit -1;
            if(Count_Bit == 4'b0) begin 
            i=1'b0;
            end
            //Count_Bit <=4'b1100;

                end
   /*default : begin
            SPI_Select <= #1 2'b11;

                  end*/ 
  endcase
//end
end // End Of Block OUTPUT_LOGIC

endmodule



I will welcome any help

Thank you in advance !!

von Ale (Guest)


Rate this post
0 useful
not useful
Count_Bit is still being modified in both always. Maybe you should do 
one clocked always block for the state machine, instead of two.

You are using ModelSim to simulate, maybe you should try to synthesize 
the code for some random FPGA, whatever you have installed, and have a 
look at the errors and warnings you get. It helps with double written 
registers and things like that :).
I also find that a state diagram with conditions helps during the design 
phase and implementation phases, it helps you visualize what you intend 
to do and to find possible misunderstandings between how you think the 
problem can be solved and how you are trying to solve it :). Sometimes I 
write down timing diagrams, helps too when the state machines get a bit 
too complicated.

von Jonas E. (lerechercheur)


Attached files:

Rate this post
0 useful
not useful
Thank you for your answer,

I have tried with a single always but it doesn't work.

I have attached the description and the result.

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    17:16:35 12/27/2019 
// Design Name: 
// Module Name:    Projet_Tech_SPI 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module Projet_Tech_SPI(
     CLK_SPI,
     CS_SPI,
    reset,
    Count_Bit,
    //Count_DateBit, 
    //Count_DataBit, 
     SPI_Select
    ); 

//------------- Déclaration des entrées -----------------------------
input   CLK_SPI, CS_SPI, reset;
//------------- Déclaration des sorties ----------------------------
output   [1:0] SPI_Select;
output   [3:0] Count_Bit;

//output   [1:0] Count_DateBit;
//output   [3:0] Count_DataBit;

//------------- Les ports d'entrées -------------------
wire    CLK_SPI, CS_SPI, reset;
//------------- Les ports de sorties ------------------
reg     [1:0] SPI_Select;
reg    [3:0] Count_Bit;
reg        i=1'b1;
//reg     [1:0] Count_DateBit;
//reg     [3:0] Count_DataBit;

//------------- Les constantes internes --------------------------- 
//assign CS_SPI = i;
parameter SIZE = 4;
parameter Idle = 4'b0001, Trans_FlagBit = 4'b0010, Trans_DateBit = 4'b0100, Trans_DataBit = 4'b1000 ;

//-------------Variables internes---------------------------
reg   [SIZE-1:0]          state        ;// Seq part of the FSM
reg   [SIZE-1:0]          next_state   ;// combo part of FSM
//----------Code startes Here------------------------
//assign next_state = fsm_function(state, Idle, Trans_FlagBit, Trans_DateBit, Trans_DataBit);



always @(posedge CLK_SPI )
begin : MEF_SPI
//next_state = 4'b0001;
 
 state = Idle;
//Count_Bit <=4'b0011;
//Count_DateBit <= 2'b11;
//Count_DataBit <= 4'b1111;

case(state)
  Idle         : if(CS_SPI == 1'b0) begin
             state = Idle;
             SPI_Select =  2'b11;
             end else if (CS_SPI == 1'b1) begin
             state =  Trans_FlagBit; 
             end 
             
  Trans_FlagBit : if(CS_SPI == 1'b1) begin
             SPI_Select =  2'b00;
             state = Trans_DateBit;
             //SPI_Select =  2'b00;
             //Count_Bit =4'b0011; 
             end            
              
  Trans_DateBit : if((CS_SPI == 1'b1) && (i!= 1'b0) ) begin
             SPI_Select <=  2'b01;
             Count_Bit =4'b0010; 
             Count_Bit <= Count_Bit -1;
             state = Trans_DateBit; 
                if(Count_Bit == 4'b0) begin
                i=1'b0;
                end 
                
             end else if((CS_SPI == 1'b1) && (i==1'b0) ) begin 
             state = Trans_DataBit;
             //Count_Bit <=4'b1100;
             i=1'b1;
             end
             
  Trans_DataBit : if((CS_SPI == 1) && (i != 1'b0)) begin
             SPI_Select <=  2'b01;
             Count_Bit <=4'b1011;
             Count_Bit <= Count_Bit -1;
             state = Trans_DataBit ;
                if(Count_Bit == 4'b0) begin
                i=1'b0;
                end 
             end else if((CS_SPI == 1) && (i == 1'b0)) begin
             state = Trans_FlagBit;
             i=1'b1;
            
             //SPI_Select = 0; 
            end 
            
  default     : next_state = Idle;
  
  endcase; 
end



endmodule


Thank you and Happy New Year !!

: Edited by Moderator
von Ale (Guest)


Rate this post
0 useful
not useful
You are mixing two kinds of assignments '=' and '<=' they do not mean 
the same and are to be used in different kinds of assignments !.
Short description: Inside a clocked always block use '<=' only.

What I see from the simulation is that SPI_Select is not being updated, 
the simulator is not understanding your code correctly.

The use of an extra flag 'i' kinds of defeats the simplicity of the 
state machine you have more unneeded states, when Count_Bit is zero you 
can transition.

this code is ...
             Count_Bit <=4'b1011;
             Count_Bit <= Count_Bit -1;

The second one is the one that has effect, but which one was the 
intended one ?
Verilog is not a procedural language, what you describe is hardware and 
it works in parallel. So all assignments happen at the same time, 
enables permitting, of course.

Count_Bit should be initialized before you transition to the next state, 
in Trans_FlagBit and in Trans_DateBit before you go to Trans_DataBit 
(when the bit counter is zero).

von Ale (Guest)


Rate this post
0 useful
not useful
A nice example of a SPI controller is given in the site fpga4fun, They 
explain the workings too, you may give it a look. The good thing is that 
they examples while simple, actually work !

von Ale (Guest)


Rate this post
0 useful
not useful
their (and not they).

von Lothar M. (lkmiller) (Moderator)


Rate this post
0 useful
not useful
Jonas E. wrote:
> in order to access the fourth state which would allow me to count down
> the 12 bits of data to be transmitted.
Have a close look what SPI really is, then the world gets as simple as 
it is: SPI are only two shift registers coupled one behind the other.

Is there any counter in this suprisingly description? No, because the 
"easiest to handle" SPI slaves don't count any bits. Instead they simply 
shift them out of or into a shift register while SS# is low. And they 
handle new data while SS# is high.

Having brought this to mind, a implementation for a 24 bit parallel 
in/out SPI device are only a few lines like those:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity SPI_Slave is
    Generic ( breite: natural := 24);
    Port ( SCLK : in  STD_LOGIC;
           SS   : in  STD_LOGIC;
           MOSI : in  STD_LOGIC;
           MISO : out  STD_LOGIC;
           Dout : out  STD_LOGIC_VECTOR (breite-1 downto 0);
           Din  : in  STD_LOGIC_VECTOR (breite-1 downto 0));
end SPI_Slave;

architecture Behavioral of SPI_Slave is

signal dsr  : STD_LOGIC_VECTOR (breite-1 downto 0); -- the one and only SPI shift register

begin

  -- parallel inputs --> handle MISO
  process (SS, Din, SCLK) begin
     if (SS='1') then                           -- with "inactive" SS#: load parallel inputs
        dsr <= Din;
     elsif rising_edge(SCLK) then               -- with SS#=0 and each SCLK
        dsr <= dsr(dsr'left-1 downto 0) & MOSI; -- shift left for new MISO and load MOSI as LSB
     end if;
  end process;
  MISO <= dsr(dsr'left) when SS='0' else 'Z';   -- map MSB of shift register to MISO
  
  -- parallel outputs --> handle SS# 
  process (SS) begin
     if rising_edge(SS) then  -- device is deselected at rising edge of SS#
        Dout <= dsr;          -- store shiftet data tparallel outputs
     end if;
  end process;

end Behavioral;
Its VHDL, but you will get the trick easily...

A SPI master is a little bit more tricky, and indeed some kind of 
counter is necessary. But you must not (never ever!!)(**) use the SCLK 
in a SPI master as a clock in your design. The one and only clock is the 
50MHz (or whatsoever xtal is connected to your FPGA pins). All the other 
"clocks" are simply synchronous signals.

See this VHDL implementation using exactly 1 clock:
http://www.lothar-miller.de/s9y/categories/45-SPI-Master

(**) the only two groups of people using more than 1 clock in a FPGA 
design are absolute beginners and absolute professionals. The ones 
accidentally, the others with absolute caution.

: Edited by Moderator
von Jonas E. (lerechercheur)


Attached files:

Rate this post
0 useful
not useful
Thank you once again,

I have tried to modified many of thing that you have mentioned but still 
don't work.
Is not evaluating even the first state because un the result the CS_SPI 
is not working. Even the state and the Count_Bit are not working.

I don't realy know what I am missing.
I will be please to have your help again.
I have attached the description and the result.

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    17:16:35 12/27/2019 
// Design Name: 
// Module Name:    Projet_Tech_SPI 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module Projet_Tech_SPI_2(
     CLK_SPI,
     CS_SPI,
    reset,
    Count_Bit, 
     SPI_Select
    ); 

//------------- Déclaration des entrées -----------------------------
input   CLK_SPI, CS_SPI, reset;
//------------- Déclaration des sorties ----------------------------
output   [1:0] SPI_Select;
output   [3:0] Count_Bit;

//output   [1:0] Count_DateBit;
//output   [3:0] Count_DataBit;

//------------- Les ports d'entrées -------------------
wire    CLK_SPI, CS_SPI, reset;
//------------- Les ports de sorties ------------------
reg     [1:0] SPI_Select;
reg    [3:0] Count_Bit;
reg        i=1'b1;
//reg     [1:0] Count_DateBit;
//reg     [3:0] Count_DataBit;

//------------- Les constantes internes --------------------------- 
//assign CS_SPI = i;
parameter SIZE = 4;
parameter Idle = 4'b0001, Trans_FlagBit = 4'b0010, Trans_DateBit = 4'b0100, Trans_DataBit = 4'b1000 ;

//-------------Variables internes---------------------------
reg   [SIZE-1:0]          state        ;// Seq part of the FSM
reg   [SIZE-1:0]          next_state   ;// combo part of FSM
//----------Code startes Here------------------------
//assign next_state = fsm_function(state, Idle, Trans_FlagBit, Trans_DateBit, Trans_DataBit);


always @(posedge CLK_SPI )
begin : MEF_SPI

//state = Idle;

case(state)
  Idle         : if(CS_SPI == 1'b0) begin
             state <= Idle;
             SPI_Select <=  2'b11;
             end else if (CS_SPI == 1'b1) begin
             state <= Trans_FlagBit; 
             SPI_Select <=  2'b00;
             end 
             
  Trans_FlagBit : if(CS_SPI == 1'b1) begin
             SPI_Select <=  2'b00;
             state <= Trans_DateBit;
             //SPI_Select =  2'b00;
             Count_Bit =4'b0010; 
             end  
              
  Trans_DateBit : if((CS_SPI == 1'b1) && (i!= 1'b0) ) begin
             SPI_Select <=  2'b01;
             Count_Bit <= Count_Bit -1;
             state = Trans_DateBit; 
                if(Count_Bit == 4'b0) begin
                i=1'b0;
                end 
                 
             end else if((CS_SPI == 1'b1) && (i==1'b0) ) begin 
             state <= Trans_DataBit;
             Count_Bit <=4'b1011;
             i=1'b1;
             end
             
  Trans_DataBit : if((CS_SPI == 1) && (i != 1'b0)) begin
             SPI_Select <=  2'b01;
             Count_Bit <= Count_Bit -1;
             state <= Trans_DataBit ;
                if(Count_Bit == 4'b0) begin
                i=1'b0;
                end 
             end else if((CS_SPI == 1) && (i == 1'b0)) begin
             state <= Trans_FlagBit;
             i=1'b1;
            
             //SPI_Select = 0; 
            end 
            
  //default     : next_state = Idle;
  
  endcase; 
end

endmodule



von Lothar M. (lkmiller) (Moderator)


Rate this post
0 useful
not useful
You must initialize reg with a valid value. Otherwise its initialized 
with X:
https://link.springer.com/chapter/10.1007%2F978-1-4615-1713-9_7
And in your case(state) there is nothing to handle a 4'bXXXX...

: Edited by Moderator

Reply

Entering an e-mail address is optional. If you want to receive reply notifications by e-mail, please log in.

Rules — please read before posting

  • Post long source code as attachment, not in the text
  • Posting advertisements is forbidden.

Formatting options

  • [c]C code[/c]
  • [avrasm]AVR assembler code[/avrasm]
  • [vhdl]VHDL code[/vhdl]
  • [code]code in other languages, ASCII drawings[/code]
  • [math]formula (LaTeX syntax)[/math]




Bild automatisch verkleinern, falls nötig
Note: the original post is older than 6 months. Please don't ask any new questions in this thread, but start a new one.