Addressing many registers

Guest #3794981
Rate this post
useful
not useful
Hi,

i have a question for whoever has the time.
I am writing a vhdl module to interface an IC through SPI.
The main functionality of the module is a FSM, using a few counters and 
looping whenever is needed.
The IC to interface, requires a lot of writing to registers for 
configuration, and then some writing and reading for normal operation, 
all through SPI.

For example, i need to configure 30 something internal IC registers, to 
get the IC ready for operation. So my FSM will loop 30 something times, 
while incrementing a counter to keep track.

I am using a combinational proccess, where the counter above, selects 
the correct SPI instruction, address and data to either read or write.

I am wondering if there is a better way for selecting SPI instruction, 
address and data, because the combinational process becomes very quickly 
too long.

Thank you in advance
Moderator (Company: Titel) #3795036
Rate this post
useful
not useful
SparkyT wrote:
> I am wondering if there is a better way for selecting SPI instruction,
> address and data, because the combinational process becomes very quickly
> too long.
Use a RAM(ROM) and initialize it with the intitializing sequence...
Look at this LCD controller: 
http://www.mikrocontroller.net/attachment/90798/LCD_CTRL.vhd
In it is a RAM which is used in double way: first it contains the 
sequence to initialize the display, after initialisation it contains the 
characters to be displayed...

> So my FSM will loop 30 something times, while incrementing a counter to
> keep track.
You do not have to jump back to the very beginning of your "loop"...
Guest #3795456
Rate this post
useful
not useful
SparkyT wrote:
> I am writing a vhdl module to interface an IC through SPI.
> The main functionality of the module is a FSM, using a few counters and
> looping whenever is needed.

oops, what do you mean with 'looping'?

> The IC to interface, requires a lot of writing to registers for
> configuration,

so, you have an SPI interface (most likely an SPI slave?) which receives 
data via SPI, collects all bits together, and then presents you a e.g. 
32bit register with a 'write-strobe' to your logic? If the cycletime of 
the solution is too slow, you could easily pipeline this write operation 
into your config-registers...

> and then some writing

same as above

> and reading for normal operation,
> all through SPI.

now it gets interesting! Do you have a in-frame SPI protocoll or a 
out-of-frame SPI protocoll? And what's the cycletime of the SPI, how is 
the address to be read passed via SPI to your logic?

>
> For example, i need to configure 30 something internal IC registers, to
> get the IC ready for operation. So my FSM will loop 30 something times,
> while incrementing a counter to keep track.

i simply have no idea what you are stating above... Without the .vhdl 
files i can't even grasp what you are doing...

>
> I am using a combinational proccess, where the counter above, selects
> the correct SPI instruction, address and data to either read or write.
>
> I am wondering if there is a better way for selecting SPI instruction,
> address and data, because the combinational process becomes very quickly
> too long.

without having a clear description what you want to do (not based on 
your non-working solution, just the problem!) and the requirements in 
case of timing, latency, ... i think no one can give you an idea...

Lothar already mentioned embedded RAMs for data storage. Is this an 
option for you? At least for some of the registers?
Guest #3795995
Rate this post
useful
not useful
Hi again,
very interesting points, and i agree my description is not the best.
The FPGA will be the SPI master, and the IC is the SPI slave.

Let me just say that speed is not critical, i am way over some limits.
I just want to make my code simpler and more readable.

About looping, my fsm has about 30-35 states (so far). The first 5 are 
the config loop, where each loop iteration configures a single register 
on the SPI slave. After 30 times (configuring 29 registers, and 
inquiring the state of the slave) i enter on the 6th state where i am in 
normal operation.
But,
the combinational process is already too long, and i haven't even 
started  enquiring the slave in normal operation.

I will also look into ROM (the fpga has embedded), as i need data to be 
there even after power-down.

here is the begining on the combinational process.
obviously the "config_count" is the counter incremented by the fsm, to 
give appropriate data to the SPI link.
1
decode:process (config_count, norm_count, send_can, sel_heart,CAN_DATA_TX,node_count) 
2
begin
3
  -- default value
4
  instruction <= (others => '0');                
5
  addr_byte  <= (others => '0');                
6
  data_byte  <= (others => '0');
7
  data_byte1  <= (others => '0');
8

9
  case config_count is      
10
      
11
    when "000000" =>             
12
      instruction <= reset_inst;  
13
         
14
    when "000001" =>             
15
      instruction <= write_inst;               
16
      addr_byte  <= x"2A";  
17
      data_byte  <= "01001100";  -- TODO    
18

19
    when "000010" =>
20
      instruction <= write_inst;               
21
      addr_byte  <= x"29";    
22
      data_byte  <= "11001100";  -- TODO       
23

24
    when "000011" =>
25
      instruction <= write_inst;               
26
      addr_byte  <= x"28";
27
      data_byte  <= "10101010";  -- TODO          
28
 
29
    when "000100" =>
30
      instruction <= write_inst;               
31
      addr_byte  <= x"20";    
32
      data_byte  <= x"FF";          
33

34
    when "000101" =>
35
      instruction <= write_inst;               
36
      addr_byte  <= x"21";    
37
      data_byte  <= x"FF";    
38

39
    when "000110" =>
40
      instruction <= write_inst;               
41
      addr_byte  <= x"00";  
42
      data_byte  <= x"FF";   
43

44
    when "000111" =>
45
      instruction <= write_inst;               
46
      addr_byte  <= x"01";  
47
      data_byte  <= x"FF";    
48

49
    when "001000" =>
50
      instruction <= write_inst;               
51
      addr_byte  <= x"04";  
52
      data_byte  <= x"FF";   
53

54
    when "001001" =>
55
      instruction <= write_inst;               
56
      addr_byte  <= x"05";  
57
      data_byte  <= x"FF";    --   (TODO)
58

59
    when "001010" =>
60
      instruction <= write_inst;               
61
      addr_byte  <= x"24";    
62
      data_byte  <= x"FF";
Moderator (Company: Titel) #3796153
Rate this post
useful
not useful
SparkyT wrote:
> About looping, my fsm has about 30-35 states (so far).
This is the ideal use for a RAM. Make config_count as an integer and 
use it as the adress to read the addr_byte and data_byte from the 
RAM in a way like that:
1
-- define the RAM
2
type ram_t is array (0 to 31) of std_logic_vector(15 downto 0); -- addr_byte + data_byte  
3
-- init the RAM
4
signal ram : ram_t := ( x"2A4C",
5
                        x"29CC",
6
                        ...
7
                        others => x"00000"
8
                       );
9

10
-- access the RAM
11
   addr_byte <= ram(config_count)(15 downto 8);
12
   data_byte <= ram(config_count)(7 downto 0);


SparkyT wrote:
> By the way, i am using the SPI master from this website
Where is "this"?
Guest #3810637
Rate this post
useful
not useful
i was wondering how to adjust the SPI-master to a variable length SPI 
tranfer. I need to interface an IC where i have SPI instructions that 
are 1 byte long, 3 bytes long and 4 bytes long. The IC will always reply 
on the third byte of the SPI variable transfer.

I have managed to change (well, trying) the example above, but keeping 
the exact same logic. (repeating the sequence of the states, but 
spi_bitcounter is not a generic. Its set every time according to need)
I have one Receive shift register (8bits), that registers MISO, and my 
FSM knows when its the third byte, to read.
I have 3  Transmit shift registers used as follows,
-- 'tx_reg1' is 8 bits,  used for 1 Byte SPI TRANSFER
-- 'tx_reg3' is 24 bits, used for 3 Bytes SPI TRANSFER
-- 'tx_reg4' is 32 bits, used for 4 Bytes SPI TRANSFER
The FSM knows what SPI length is needed for communication, and uses the 
apropriate tx_regx.

So far, so good. Simulations look ok, waiting for the hardware to start 
testing. But the FSM  has 49 states. I can already see some redudant 
ones, that i will try to remove.
I guess the SPI-master example is your work. Very nice VHDL coding. So, 
my question is how would you go about changing it to a variable length?
Guest #3812944
Rate this post
useful
not useful
I was thinking something like this.

need this input
1
SEL_SPI  : in  STD_LOGIC_VECTOR (2 downto 0);

make the spi count up to the max possible size (remove generic)
1
signal bitcounter    : integer range 0 to 32;

then the fsm state is like this
1
  case spitxstate is
2
       when spi_stx =>
3
             SS          <= '1';             -- slave select disabled
4
             TX_Done     <= '0';
5
             spiclk      <= '0';             -- SPI-Mode 0
6
    case SEL_SPI is
7
      when "001" =>
8
        bitcounter  <= 8;
9
      when "010" =>
10
        bitcounter  <= 16;
11
      when "011" =>
12
        bitcounter  <= 24;
13
      when "100" =>
14
        bitcounter  <= 32;
15
      when others =>
16
        bitcounter  <= 0;
17
    end case;
18
             if(TX_Start = '1') then 
19
                spitxstate <= spi_txactive; 
20
                SS         <= '0';
21
                delay      <= clock_delay; 
22
             end if;

and finally use the multiple txreg
1
    case SEL_SPI is
2
-- ONE BYTE SPI TRANSFER -------------------------------------------------------
3
      when "001" =>
4
             if (spitxstate=spi_stx) then             -- Reset if the SS inactive
5
                tx_reg1 <= TX_Data(7 downto 0);
6
             end if;
7
            if (spiclk='0' and  spiclklast='1') then         -- SPI-Mode 0
8
                tx_reg1 <= tx_reg1(tx_reg1'left-1 downto 0) & tx_reg1(0);
9
             end if;
10
      MOSI    <= tx_reg1(tx_reg1'left);
11
      tx_reg2 <= (others => '0');
12
      tx_reg3 <= (others => '0');
13
      tx_reg4 <= (others => '0');
14
-- TWO BYTES SPI TRANSFER -------------------------------------------------------
15
      when "010" =>
16
             if (spitxstate=spi_stx) then             -- Reset if the SS inactive
17
                tx_reg2 <= TX_Data(15 downto 0);
18
             end if;
19
            if (spiclk='0' and  spiclklast='1') then         -- SPI-Mode 0
20
                tx_reg2 <= tx_reg2(tx_reg2'left-1 downto 0) & tx_reg2(0);
21
             end if;
22
      MOSI    <= tx_reg2(tx_reg2'left);
23
      tx_reg1 <= (others => '0');
24
      tx_reg3 <= (others => '0');
25
      tx_reg4 <= (others => '0');
26
-- THREE BYTES SPI TRANSFER -------------------------------------------------------
27
      when "011" =>
28
             if (spitxstate=spi_stx) then             -- Reset if the SS inactive
29
                tx_reg3 <= TX_Data(23 downto 0);
30
             end if;
31
            if (spiclk='0' and  spiclklast='1') then         -- SPI-Mode 0
32
                tx_reg3 <= tx_reg3(tx_reg3'left-1 downto 0) & tx_reg3(0);
33
             end if;
34
      MOSI    <= tx_reg3(tx_reg3'left);
35
      tx_reg1 <= (others => '0');
36
      tx_reg2 <= (others => '0');
37
      tx_reg4 <= (others => '0');
38
-- FOUR BYTES SPI TRANSFER -------------------------------------------------------
39
      when "100" =>
40
             if (spitxstate=spi_stx) then             -- Reset if the SS inactive
41
                tx_reg4 <= TX_Data;
42
             end if;
43
            if (spiclk='0' and  spiclklast='1') then         -- SPI-Mode 0
44
                tx_reg4 <= tx_reg4(tx_reg4'left-1 downto 0) & tx_reg4(0);
45
             end if;
46
      MOSI    <= tx_reg4(tx_reg4'left);
47
      tx_reg1 <= (others => '0');
48
      tx_reg2 <= (others => '0');
49
      tx_reg3 <= (others => '0');
50
--------------------------------------------------------------------------------
51
      when others =>
52
        tx_reg1 <= (others => '0');
53
        tx_reg3 <= (others => '0');
54
        tx_reg4 <= (others => '0');
55
        MOSI <= '0';
56
    end case;

What about this?
Moderator (Company: Titel) #3813888
Rate this post
useful
not useful
SparkyT wrote:
> What about this?
Seems far to difficult. There is no need to have one 8 bit, one 16 bit 
and one 32 bit SPI. I would configure only one SPI engine as an 32 bit 
SPI (as you did). In that 32 bit register I would place the shorter 8 
and 16 bit words to the correct place and then start a transmission with 
the length of the bitcounter.

Michael Fischer did this already. You can find his adaption at the 
bottom of the page: http://www.emb4fun.de/fpga/components/index.html

Reply

Please log in before posting.

or

Log in with Google account

Registration is free and takes only a minute.

Register now