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.

[Synth 8-27] else clause after check for clock not supported

Status
Not open for further replies.

beginner_EDA

Full Member level 4
Joined
Aug 14, 2013
Messages
191
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,296
Activity points
3,854
Hi,
I am trying to synthesized following VHDL code in vivado 2015.2 (kintex kc705) for spi slave
https://eewiki.net/pages/viewpage.action?pageId=7569477
but it shows following error
"[Synth 8-27] else clause after check for clock not supported "
but in simulation it has no error.

I couldn't figure out whats wrong here. The code is:


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
--------------------------------------------------------------------------------
--
--   FileName:         spi_slave.vhd
--   Dependencies:     none
--   Design Software:  Quartus II 32-bit Version 11.1 Build 173 SJ Full Version
--
--   HDL CODE IS PROVIDED "AS IS."  DIGI-KEY EXPRESSLY DISCLAIMS ANY
--   WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT
--   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
--   PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL DIGI-KEY
--   BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL
--   DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF
--   PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
--   BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF),
--   ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS.
--
--   Version History
--   Version 1.0 7/5/2012 Scott Larson
--     Initial Public Release
--   Version 1.1 11/27/2012 Scott Larson
--     Added an asynchronous active low reset
--
--------------------------------------------------------------------------------
 
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
 
ENTITY spi_slave IS
  GENERIC(
    cpol    : STD_LOGIC := '0';  --spi clock polarity mode
    cpha    : STD_LOGIC := '0';  --spi clock phase mode
    d_width : INTEGER := 8);     --data width in bits
  PORT(
    sclk         : IN     STD_LOGIC;  --spi clk from master
    reset_n      : IN     STD_LOGIC;  --active low reset
    ss_n         : IN     STD_LOGIC;  --active low slave select
    mosi         : IN     STD_LOGIC;  --master out, slave in
    rx_req       : IN     STD_LOGIC;  --'1' while busy = '0' moves data to the rx_data output
    st_load_en   : IN     STD_LOGIC;  --asynchronous load enable
    st_load_trdy : IN     STD_LOGIC;  --asynchronous trdy load input
    st_load_rrdy : IN     STD_LOGIC;  --asynchronous rrdy load input
    st_load_roe  : IN     STD_LOGIC;  --asynchronous roe load input
    tx_load_en   : IN     STD_LOGIC;  --asynchronous transmit buffer load enable
    tx_load_data : IN     STD_LOGIC_VECTOR(d_width-1 DOWNTO 0);  --asynchronous tx data to load
    trdy         : BUFFER STD_LOGIC := '0';  --transmit ready bit
    rrdy         : BUFFER STD_LOGIC := '0';  --receive ready bit
    roe          : BUFFER STD_LOGIC := '0';  --receive overrun error bit
    rx_data      : OUT    STD_LOGIC_VECTOR(d_width-1 DOWNTO 0) := (OTHERS => '0');  --receive register output to logic
    busy         : OUT    STD_LOGIC := '0';  --busy signal to logic ('1' during transaction)
    miso         : OUT    STD_LOGIC := 'Z'); --master in, slave out
END spi_slave;
 
ARCHITECTURE logic OF spi_slave IS
  SIGNAL mode    : STD_LOGIC;  --groups modes by clock polarity relation to data
  SIGNAL clk     : STD_LOGIC;  --clock
  SIGNAL bit_cnt : STD_LOGIC_VECTOR(d_width+8 DOWNTO 0);  --'1' for active transaction bit
  SIGNAL wr_add  : STD_LOGIC;  --address of register to write ('0' = receive, '1' = status)
  SIGNAL rd_add  : STD_LOGIC;  --address of register to read ('0' = transmit, '1' = status)
  SIGNAL rx_buf  : STD_LOGIC_VECTOR(d_width-1 DOWNTO 0) := (OTHERS => '0');  --receiver buffer
  SIGNAL tx_buf  : STD_LOGIC_VECTOR(d_width-1 DOWNTO 0) := (OTHERS => '0');  --transmit buffer
BEGIN
  busy <= NOT ss_n;  --high during transactions
  
  --adjust clock so writes are on rising edge and reads on falling edge i.e. cpha = 1 and cpol = 0
  mode <= cpol XOR cpha;  --'1' for modes that write on rising edge
  WITH mode SELECT
    clk <= sclk WHEN '1',
           NOT sclk WHEN OTHERS;
 
  --keep track of miso/mosi bit counts for data alignmnet
  PROCESS(ss_n, clk)
  BEGIN
    IF(ss_n = '1' OR reset_n = '0') THEN                         --this slave is not selected or being reset
       bit_cnt <= (conv_integer(NOT cpha) => '1', OTHERS => '0'); --reset miso/mosi bit count -- analogous to if condition
    ELSE                                                         --this slave is selected
      IF(rising_edge(clk)) THEN                                  --new bit on miso/mosi
        bit_cnt <= bit_cnt(d_width+8-1 DOWNTO 0) & '0';          --shift active bit indicator
      END IF;
    END IF;
  END PROCESS;
 
  PROCESS(ss_n, clk, st_load_en, tx_load_en, rx_req)
  BEGIN
  
    --write address register ('0' for receive, '1' for status)
    IF(bit_cnt(1) = '1' AND falling_edge(clk)) THEN
      wr_add <= mosi;
    END IF;
 
    --read address register ('0' for transmit, '1' for status)
    IF(bit_cnt(2) = '1' AND falling_edge(clk)) THEN
      rd_add <= mosi;
    END IF;
    
    --trdy register
    IF((ss_n = '1' AND st_load_en = '1' AND st_load_trdy = '0') OR reset_n = '0') THEN  
      trdy <= '0';   --cleared by user logic or reset
    ELSIF(ss_n = '1' AND ((st_load_en = '1' AND st_load_trdy = '1') OR tx_load_en = '1')) THEN
      trdy <= '1';   --set when tx buffer written or set by user logic                                  
    ELSIF(wr_add = '1' AND bit_cnt(9) = '1' AND falling_edge(clk)) THEN
      trdy <= mosi;  --new value written over spi bus
    ELSIF(rd_add = '0' AND bit_cnt(d_width+8) = '1' AND falling_edge(clk)) THEN
     [COLOR="#FF0000"][B] trdy <= '0'; [/B][/COLOR]  --clear when transmit buffer read
    END IF;
    
    --rrdy register
    IF((ss_n = '1' AND ((st_load_en = '1' AND st_load_rrdy = '0') OR rx_req = '1')) OR reset_n = '0') THEN
      rrdy <= '0';   --cleared by user logic or rx_data has been requested or reset
    ELSIF(ss_n = '1' AND st_load_en = '1' AND st_load_rrdy = '1') THEN
      rrdy <= '1';   --set when set by user logic
    ELSIF(wr_add = '1' AND bit_cnt(10) = '1' AND falling_edge(clk)) THEN
      rrdy <= mosi;  --new value written over spi bus
    ELSIF(wr_add = '0' AND bit_cnt(d_width+8) = '1' AND falling_edge(clk)) THEN
      rrdy <= '1';   --set when new data received
    END IF;
    
    --roe register
    IF((ss_n = '1' AND st_load_en = '1' AND st_load_roe = '0') OR reset_n = '0') THEN
      roe <= '0';   --cleared by user logic or reset
    ELSIF(ss_n = '1' AND st_load_en = '1' AND st_load_roe = '1') THEN
      roe <= '1';   --set by user logic
    ELSIF(rrdy = '1' AND wr_add = '0' AND bit_cnt(d_width+8) = '1' AND falling_edge(clk)) THEN
      roe <= '1';   --set by actual overrun
    ELSIF(wr_add = '1' AND bit_cnt(11) = '1' AND falling_edge(clk)) THEN
      roe <= mosi;  --new value written by spi bus
    END IF;
    
    --receive registers
    --write to the receive register from master
    IF(reset_n = '0') THEN
      rx_buf <= (OTHERS => '0');
    ELSE
      FOR i IN 0 TO d_width-1 LOOP          
        IF(wr_add = '0' AND bit_cnt(i+9) = '1' AND falling_edge(clk)) THEN
          rx_buf(d_width-1-i) <= mosi;
        END IF;
      END LOOP;
    END IF;
    --fulfill user logic request for receive data
    IF(reset_n = '0') THEN
      rx_data <= (OTHERS => '0');
    ELSIF(ss_n = '1' AND rx_req = '1') THEN  
      rx_data <= rx_buf;
    END IF;
 
    --transmit registers
    IF(reset_n = '0') THEN
      tx_buf <= (OTHERS => '0');
    ELSIF(ss_n = '1' AND tx_load_en = '1') THEN  --load transmit register from user logic
      tx_buf <= tx_load_data;
    ELSIF(rd_add = '0' AND bit_cnt(7 DOWNTO 0) = "00000000" AND bit_cnt(d_width+8) = '0' AND rising_edge(clk)) THEN
      tx_buf(d_width-1 DOWNTO 0) <= tx_buf(d_width-2 DOWNTO 0) & tx_buf(d_width-1);  --shift through tx data
    END IF;
 
    --miso output register
    IF(ss_n = '1' OR reset_n = '0') THEN           --no transaction occuring or reset
      miso <= 'Z';
    ELSIF(rd_add = '1' AND rising_edge(clk)) THEN  --write status register to master
      CASE bit_cnt(10 DOWNTO 8) IS
        WHEN "001" => miso <= trdy;
        WHEN "010" => miso <= rrdy;
        WHEN "100" => miso <= roe;
        WHEN OTHERS => NULL;
      END CASE;
    ELSIF(rd_add = '0' AND bit_cnt(7 DOWNTO 0) = "00000000" AND bit_cnt(d_width+8) = '0' AND rising_edge(clk)) THEN
      miso <= tx_buf(d_width-1);                  --send transmit register data to master
    END IF;
    
  END PROCESS;
END logic;




and error pointing to red highlighted text in the code. can anybody help?
 
Last edited:

Im not surprised the compiler is choking in your code - it doesnt follow standard templates at all - it has multiple clock branches, many many async resets/sets which have dynamic inputs, using both clock esges and it is hard to read.

Simulation will work with ANY valid vhdl - it is a simulator, it is not trying to create logic from your code. The synthesis tool has to map your code to real hardware, and it just cannot from the poor descriptions.

I recommend:
1. Draw your circuit on some paper or other drawing tool - without knowing what circuit you want, you should not be writing code.

2. Sticking to the standard synchronous template:


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
process(clk, async_rst)
begin
  if async_rst = '1' then
    --async reset here
  if rising_edge(clk) then  --use a single clock edge for all of the code
    
    --synchronous code goes here to infer registers
 
    if enable = '1' then  -- synchronous enable
      -- regs with clock enable go here
    end if;
  end if;
end process;

 

My guess is that altera does a better job converting the if-else statements into something that synthesizes.

The design has multiple latches as well as plenty of async inputs. The user interface lacks a clock. It probably has gated clocks as well, but I'm not 100% sure the tools can't infer clock enables instead.
 

Quartus synthesizes the miso output register code because it can be rewritten as regular synchronous register description according to the template. Just pull-out rising_edge(clk).

There are however many latches generated and missing sensitivity list entries will probably cause simulation to synthesis mismatch.

Don't know why the design is written with so many latches.
 

Unlike most of the designs for SPI you see now days that are synchronous to a higher frequency clock, this design uses SCLK to run the entire SPI interface (which is what the original SPI specification from Motorola used). This works great if you have a slow SPI and if you don't have any other clock running in the system after power up (say the SPI controls the logic that enables the clocks on the board).

I've created SPI designs without using a separate higher frequency clock, but I certainly did not resort to using latches 8-O. Overall this code is not a very good example of SPI.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top