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.

[SOLVED] Spartan 3A used up more than 100% device resource

Status
Not open for further replies.

ptjw

Junior Member level 3
Joined
Apr 29, 2011
Messages
29
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,597
hello all,

i mentioned a few weeks ago that i am doing a project which uses a Spartan 3A FPGA to read info from an SD card. this info tells the FPGA to route certain input signals to the output signals like if i want the signal from input 1 to be repeated at output 1 or 3 i can just change the data on the SD card and it will be done. (so much easier said than done..)

anyway i've run into a brick wall during the last phase of my code: during the assigning of output ports.

basically Xilinx ISE tells me that i have used up more than 100% of the device's resources...i have edited my code and by elimination, i have found the problem. my main code is really long and in a mess now but this is the primary culprit:

Code:
                                FPGA_OUT(CLKLCD_BUF) <= CLKLCD;
				FPGA_OUT(LCD_RESET_BUF) <= LCD_RESET;
				FPGA_OUT(CS1_BUF) <= CS1;
				FPGA_OUT(CS2_BUF) <= CS2;
				FPGA_OUT(A0_BUF) <= A0;
				FPGA_OUT(WR_BUF) <= WR;
				FPGA_OUT(RD_SDA_BUF) <= RD_SDA;
				FPGA_OUT(CLKIN_BUF) <= CLKIN;
				FPGA_OUT(D0_BUF) <= D0;
				FPGA_OUT(D1_BUF) <= D1;
				FPGA_OUT(D2_BUF) <= D2;
				FPGA_OUT(D3_BUF) <= D3;

the arrayed variables on the left are the output ports while the variables on the right are the input ports. the variables with the '_BUF' are integers with a range of 1 to 40. when synthesizing this code i get this:

Code:
Selected Device : 3s50atq144-4 

 Number of Slices:                      894  out of    704   126% (*) 
 Number of Slice Flip Flops:            242  out of   1408    17%  
 Number of 4 input LUTs:               1613  out of   1408   114% (*) 
 Number of IOs:                          67
 Number of bonded IOBs:                  63  out of    108    58%  
 Number of GCLKs:                         1  out of     24     4%  

WARNING:Xst:1336 -  (*) More than 100% of Device resources are used

as you can see, this is totally not cool because this means my code can't be implemented into hardware (i'm guessing due to acute inefficiency from my inexperience in VHDL :oops:)

anyway, if i assign a random integer into the output port arrays, i use much lesser resources:

Code:
                                FPGA_OUT(1) <= CLKLCD;
				FPGA_OUT(2) <= LCD_RESET;
				FPGA_OUT(3) <= CS1;
				FPGA_OUT(4) <= CS2;
				FPGA_OUT(5) <= A0;
				FPGA_OUT(6) <= WR;
				FPGA_OUT(7) <= RD_SDA;
				FPGA_OUT(8) <= CLKIN;
				FPGA_OUT(9) <= D0;
				FPGA_OUT(10) <= D1;
				FPGA_OUT(11) <= D2;
				FPGA_OUT(12) <= D3;


Code:
Selected Device : 3s50atq144-4 

 Number of Slices:                      122  out of    704    17%  
 Number of Slice Flip Flops:            105  out of   1408     7%  
 Number of 4 input LUTs:                236  out of   1408    16%  
 Number of IOs:                          67
 Number of bonded IOBs:                  35  out of    108    32%  
 Number of GCLKs:                         1  out of     24     4%


it's a drastic difference in amount of resources used, but i need to put the _BUF variables there because they hold the data retrieved from the SD card for routing the inputs to outputs. am i missing something here? i hope i'm doing something wrong and that there's a more efficient way of doing this...


i declared the _BUF variables like so:

Code:
                variable CLKLCD_BUF : integer range 0 to 40 := 0;
		variable LCD_RESET_BUF : integer range 0 to 40 := 0;
		variable CS1_BUF : integer range 0 to 40 := 0;
		variable CS2_BUF : integer range 0 to 40 := 0;
		variable A0_BUF : integer range 0 to 40 := 0;
		variable WR_BUF : integer range 0 to 40 := 0;
		variable RD_SDA_BUF : integer range 0 to 40 := 0;
		variable CLKIN_BUF : integer range 0 to 40 := 0;
		variable D0_BUF : integer range 0 to 40 := 0;
		variable D1_BUF : integer range 0 to 40 := 0;
		variable D2_BUF : integer range 0 to 40 := 0;
		variable D3_BUF : integer range 0 to 40 := 0;
		variable D4_BUF : integer range 0 to 40 := 0;
		variable D5_BUF : integer range 0 to 40 := 0;
		variable D6_BUF : integer range 0 to 40 := 0;
		variable D7_BUF : integer range 0 to 40 := 0;
 

it will be nothing to do with your input or output ports. It will be the logic internally. I can only assume that previous to assigning ports it was synthesising some logic away.

I would see where the LUTs are being used internally, and redesign any high usage areas.

Separatly - you should not be assigning integers directly to IO because you cannot garantee what bit maps to which pin. You should convert them to an array type like unsigned, signed or std_logic-vector first.
 

I would see where the LUTs are being used internally, and redesign any high usage areas.


ok..i did try redesigning a few times and managed to trim off 10% of the resource but its still over the 100% :shock: and there's only so much i can trim away and redesign...its like i have an overweight car and the only way to get it light enough is ironically to throw out the engine...i trimmed so much that the code didn't work...


Separatly - you should not be assigning integers directly to IO because you cannot garantee what bit maps to which pin. You should convert them to an array type like unsigned, signed or std_logic-vector first.


i don't fully understand this point...i declared FPGA_OUT as STD_LOGIC_VECTOR like so:

Code:
 FPGA_OUT : out STD_LOGIC_VECTOR (40 downto 1) := x"0000000000";


there would be an issue if i use integers directly? so i should do this?

Code:
FPGA_OUT(to_stdlogicvector(CLKLCD_BUF)) <= CLKLCD;
 

hang on - I just re-read what you wrote: The reason you're having problems is that you can potentially connect any signal to any port because all of your _BUF signals are variables. This means each output bit has a 16-1 mux connected to it. Did you really want these _BUF values to be changable, or do you want them constant? Why do the need to change on the fly? and have you considered what happens when two _BUF variables are the same value?

---------- Post added at 10:28 ---------- Previous post was at 10:27 ----------

Actually, not just 16 to one, 64 to one because you have declared them 0 to 40 - do you have a 40 bit output bus or just 12?
 

ah..ok i totally forgot about that part...sorry my bad! i used 12 because that was the limit where it goes above 100%, there's supposed to be 40 outputs but only 16 will be active.

let me explain it in more detail:

- there are 16 input ports, these ports can be rerouted to any of the 40 outputs (uniquely, so no 2 inputs go to the same output port).

- the configuration is determined by a text file stored in a SD card. this text file is generated by a separate program which has its own error checking code that ensures no 2 ports go to the same output so no worries there. if any port is unassigned then it will be 0, otherwise it will be any number from 1-40

- before reading from the SD card, i don't know which input will be routed to which output, therefore i assign all the xx_BUF variables as 0 (unassigned/unknown)

- after reading the data from the SD card, i now know which port will be routed to which output, and this data is stored in xx_BUF (eg CLKLCD_BUF = 1 so the input port CLKLCD goes to output port FPGA_OUT(1))

- so now i assign the outputs to the inputs accordingly by:

Code:
                                FPGA_OUT(CLKLCD_BUF) <= CLKLCD;
				FPGA_OUT(LCD_RESET_BUF) <= LCD_RESET;
				FPGA_OUT(CS1_BUF) <= CS1;
				FPGA_OUT(CS2_BUF) <= CS2;
				FPGA_OUT(A0_BUF) <= A0;
				FPGA_OUT(WR_BUF) <= WR;
				FPGA_OUT(RD_SDA_BUF) <= RD_SDA;
				FPGA_OUT(CLKIN_BUF) <= CLKIN;
				FPGA_OUT(D0_BUF) <= D0;
				FPGA_OUT(D1_BUF) <= D1;
				FPGA_OUT(D2_BUF) <= D2;
                                FPGA_OUT(D3_BUF) <= D3;
                                FPGA_OUT(D4_BUF) <= D4;
				FPGA_OUT(D5_BUF) <= D5;
				FPGA_OUT(D6_BUF) <= D6;
				FPGA_OUT(D7_BUF) <= D7;

which is 16 outputs, the other 34 have been declared as '0' so they aren't active...
 

try changing the range on the integer variable to 0 to 15 to see if that helps. Basically you have got 40 16 to 1 muxes. Without further limiting the choices, your device just may be too small.

But just reading the spec, can this routing change while in use? is the port mapping changed every time the SD card is read, or is this just a setup thing? If this text file is available when you compile the FPGA, you may be best reading in the port mapping in the text file direct to the VHDL and assigning the port mapping then. Xilinx allows you to use textio to read text files to set up constants during compilation.
 

This is still the same problem as some time ago right? Read text file from SD. Interpret file, and use this to configure a switchbox as it were between the leds and switches.

What you need to remember is that you don't need a full speed all update all the time. If I remember correctly it was just switches + leds right?

Lets assume 8 switches + 8 leds. So, sample the switches at a decent speed. Say 1 kHz is MORE than enough.

Now all you need to do is this:

you have an array of 8 pairs (source, destination). source being the sample of the switch. destination being led output.

Just iterate over the 8 (source, destinations) and update the destination output flip-flop with the source value.

There's more solutions to this, but I just mean to illustrate you don't NEED a full mux for every single combination...

Just connect them one at a time, and iterate over it fast enough.

---------- Post added at 12:09 ---------- Previous post was at 12:06 ----------

reread problem. okay 16 input to 40 output. Same principle applies. It all depends on wether the updates to the output should be "instantaneous", or if you are allowed a certain update delay.
 

the leds and switches problem was for getting used to the idea of switching ports via an input file because i was using the basic starter kit.

if you can tell from the variable names i used in the code above, this project is actually for testing LCD screens. i have a pattern generator box that has 16 standard inputs and a few LCD screens that accept 16 or less inputs. the thing is different models of screens have different pin configuration, eg: pin 1 on model A is CLKLCD but on model B it is pin 4...

so this config can be changed by changing a file on a SD card that will be read and handled by the FPGA on this 'middle-man, rerouting' device. you plug the pattern generator box into the inputs of this thing device, and the outputs of this device to the LCD screen you want to test.

i will read the SD card using SPI protocol (haven't tested it yet because the physical device hasn't been built yet) but assuming that my coding for the SPI/SDcard info retrieval works the only problem i have now is the mapping of input to output ports.

the config file is simply like this:

Code:
01 --CLKLCD
03 --RESET
05 --CS1
11 --CS2
12 --A0
13 --WR
14 --RD_SDA
06 --CLKIN
07 --D0
08 --D1
02 --D2
04 --D3
06 --D4
40 --D5
39 --D6
38 --D7

since the inputs are fixed, the numbers on the first row will always be the input CLKLCD, meaning CLKLCD will be sent to FPGA_OUT(1). the second row will be RESET so FPGA_OUT(3) will be equal to RESET and so on..

i hope you understand what i'm trying to do so far :???: so anyway, i will only read the SD card once, and as i'm reading the data row by row, i store it into a buffer, this is so that i can refresh the data on the ports every clock cycle.

initially i was assigning the outputs to the respective inputs during the SD card read cycle, but once the reading stops...the outputs are forever locked to whatever signal the inputs were during the read cycle only and never updated after that. so i had to store the pin numbers into buffers to refresh it every cycle.

if SD card has not been read then

read sd card and store all pin/port config in buffers
(if data is from row 1 then CLKLCD_BUF := data read, if row 2 then RESET_BUF := data read etc...

else --when done reading sd card

FPGA_OUT(buffer containing pin number) <= respective input port assigned
--eg: FPGA_OUT(CLKLCD_BUF) <= CLKLCD..etc etc, if the buffer is 0 then this is skipped

end if


i would only know which port goes to which only after the SD card is read, thats why i needed to declare 16 variables with a range of 0 to 40 (0 being in case it is not assigned to any port)


if i don't have to use the buffers then all is golden...but i need to keep refreshing the outputs to make sure they follow the inputs otherwise they'd just be stuck at the initial value.


to clarify something: the config will only be set when the device is powered on and the sd card is read. if i want to change the config i'd power it off, change the contents on the sd card, then plug the card back in and restart. so this means that the xx_BUF variables are assigned a value once and will always be constant.

i'm guessing the problem is that i'm keeping a range of 0-40 open for the 16 buffers and this is using up too much resources, i only actually need one..the problem is i don't know which one until after the sd card is read...
 
Last edited:

hello again,

after a day of rewriting and trying to optimize everything again and again, i managed to successfully synthesize the code:

Code:
Device utilization summary:
---------------------------

Selected Device : 3s50atq144-4 

 Number of Slices:                      660  out of    704    93%  
 Number of Slice Flip Flops:            798  out of   1408    56%  
 Number of 4 input LUTs:               1116  out of   1408    79%  
 Number of IOs:                          67
 Number of bonded IOBs:                  67  out of    108    62%  
 Number of GCLKs:                         1  out of     24     4%

all i did was use a for loop to keep refreshing the outputs on every clock cycle like so:

Code:
                      for count in 1 to 40 loop
				
				if count = CLKLCD_BUF then
					FPGA_OUT(count) <= CLKLCD;
				end if;
				
				if count = LCD_RESET_BUF then
					FPGA_OUT(count) <= LCD_RESET;
				end if;
			
				if count = CS1_BUF then
					FPGA_OUT(count) <= CS1;
				end if;
				
				if count = CS2_BUF then
					FPGA_OUT(count) <= CS2;
				end if;
				
				if count = A0_BUF then
					FPGA_OUT(count) <= A0;
				end if;
				
				if count = WR_BUF then
					FPGA_OUT(count) <= WR;
				end if;
				
				if count = RD_SDA_BUF then
					FPGA_OUT(count) <= RD_SDA;
				end if;
				
				if count = CLKIN_BUF then
					FPGA_OUT(count) <= CLKIN;
				end if;
				
				if count = D0_BUF then
					FPGA_OUT(count) <= D0;
				end if;
				
				if count = D1_BUF then
					FPGA_OUT(count) <= D1;
				end if;
				
				if count = D2_BUF then
					FPGA_OUT(count) <= D2;
				end if;
				
				if count = D3_BUF then
					FPGA_OUT(count) <= D3;
				end if;
				
				if count = D4_BUF then
					FPGA_OUT(count) <= D4;
				end if;
				
				if count = D5_BUF then
					FPGA_OUT(count) <= D5;
				end if;
				
				if count = D6_BUF then
					FPGA_OUT(count) <= D6;
				end if;
				
				if count = D7_BUF then
					FPGA_OUT(count) <= D7;
				end if;
			end loop;

but then just as i thought everything was peachy, i tried to implement the design and got an error during the mapping phase:

Code:
Design Summary
--------------
Number of errors:      2
Number of warnings:    0
Logic Utilization:
  Number of Slice Flip Flops:           798 out of   1,408   56%
  Number of 4 input LUTs:             1,119 out of   1,408   79%
Logic Distribution:
  Number of occupied Slices:            831 out of     704  118% [B](OVERMAPPED)[/B]
    Number of Slices containing only related logic:     831 out of     831 100%
    Number of Slices containing unrelated logic:          0 out of     831   0%
      *See NOTES below for an explanation of the effects of unrelated logic.
  Total Number of 4 input LUTs:       1,161 out of   1,408   82%
    Number used as logic:             1,119
    Number used as a route-thru:         42

what's the meaning of occupied slices (118%) as opposed to the slices (93%) in the synthesis summary? is my design really too big to fit into the device, or is there a setting in the designer that might possibly help me fit this design in?

how do i find 18% more slices to free up :-(
 

"all i did was use a for loop to keep refreshing the outputs on every clock cycle like so:"

I didn't see a clock in the piece of code you posted...

It is entirely possible that this piece of code does not do what you intend it to do... Before expending large amounts of time on it, were the results in simulation correct?
 

ok, i tried my best to optimize the code and it seems that the device might really be a tad too small to fit everything in. i removed the CRC check after receiving a block...even reduced a block read from 512 bytes to 32 bytes just to hopefully save some resources (i only need 32 bytes because thats how long the configuration file is anyway)

it is now at 116%:

Code:
Logic Utilization:
  Number of Slice Flip Flops:           756 out of   1,408   53%
  Number of 4 input LUTs:             1,093 out of   1,408   77%
Logic Distribution:
  Number of occupied Slices:            823 out of     704  116% (OVERMAPPED)
    Number of Slices containing only related logic:     823 out of     823 100%
    Number of Slices containing unrelated logic:          0 out of     823   0%
      *See NOTES below for an explanation of the effects of unrelated logic.
  Total Number of 4 input LUTs:       1,133 out of   1,408   80%
    Number used as logic:             1,093
    Number used as a route-thru:         40

  The Slice Logic Distribution report is not meaningful if the design is
  over-mapped for a non-slice resource or if Placement fails.

  Number of bonded IOBs:                 67 out of     108   62%
    IOB Flip Flops:                      44
  Number of BUFGMUXs:                     1 out of      24    4%

i didn't post my entire code the previous few times because i didn't want to confuse anyone..but now i will and if anyone has any ideas of optimizing this to free up the last 16% of slices available i will be grateful!

the code basically starts reading the SD card, which contains a textfile with the text "00010203040506070809101112131415".

every 2 digits stand for which output port follows which input port, eg 1st 2 digits are 00 so CLKLCD = unassigned, second 2 digits are 01 so port 01 = LCD_RESET and so on..

Code:
library IEEE;
library std;
use IEEE.Numeric_std.ALL;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;


entity Main is
    Port ( 
			  --- VARIABLE OUTPUTS ---
			  FPGA_OUT : out STD_LOGIC_VECTOR (40 downto 1) := x"0000000000";
			  -------
			  
			  ---  SD CARD PORTS ---
           SD_MOSI : out  STD_LOGIC; -- master out slave in
           SD_MISO : in  STD_LOGIC; -- master in slave out
           SD_CLK : out  STD_LOGIC; -- slave clock (set to half the speed of master clock)
           SD_CS : out  STD_LOGIC := '1'; -- chip select
			  -------
			  
			  --- INPUT PORTS FROM LCD --- these inputs are fixed
			  CLKLCD : in  STD_LOGIC;
           LCD_RESET : in  STD_LOGIC;
           CS1 : in  STD_LOGIC;
           CS2 : in  STD_LOGIC;
           A0 : in  STD_LOGIC;
           WR : in  STD_LOGIC;
           RD_SDA : in  STD_LOGIC;
           CLKIN : in  STD_LOGIC;
           D0 : in  STD_LOGIC;
           D1 : in  STD_LOGIC;
           D2 : in  STD_LOGIC;
           D3 : in  STD_LOGIC;
           D4 : in  STD_LOGIC;
           D5 : in  STD_LOGIC;
           D6 : in  STD_LOGIC;
           D7 : in  STD_LOGIC;
			  -------
			  
			  CLOCK : in STD_LOGIC;
			  
           PUDC_B : out  STD_LOGIC := '1';
           CSO_B : out  STD_LOGIC := '1';
           LS_OUT_DE : out  STD_LOGIC := '0';
           LS_IN_DE : out  STD_LOGIC := '0';
           PROM_DE : out  STD_LOGIC := '1';
           LED : out  STD_LOGIC := '0');
			   
end Main;
 
architecture Behavioral of Main is

	type states is (
		INIT,
		CMD0,
		CMD55,
		CMD41,
		POLL_CMD,
		IDLE,	-- wait for read or write pulse
		READ_BLOCK,
		READ_BLOCK_WAIT,
		READ_BLOCK_DATA,
		SEND_CMD,
		RECEIVE_BYTE_WAIT,
		RECEIVE_BYTE
	);
	
	signal state, return_state : states := INIT;
	signal sclk_sig : std_logic := '0'; -- slave clock
	signal cmd_out : std_logic_vector(55 downto 0) := "11111111111111111111111111111111111111111111111111111111"; -- command to be sent out
	signal recv_data : std_logic_vector(15 downto 0) := "0000000000000000"; -- received bits (1 byte, but bit by bit is pushed on to this)
	signal address : std_logic_vector(31 downto 0) := "00000000000000000000000000000000"; -- address of data needed to be accessed, don't know this yet so assign to 0
 
begin
	
	process(CLOCK)
		
		variable portcounter : natural range 0 to 15 := 0; -- count the number of times linebreak has occured, each line corresponds to a new port assignment
		variable byte_counter : natural range 0 to 31 := 0; -- counter to keep track of bytes received, 512 data plus additional CRC bytes
		variable bit_counter : natural range 0 to 160 := 160; -- counter to keep track of bits received
		variable count : positive range 1 to 40 := 1; -- counter to keep track of which input goes to which port, eg: if count = 10 and CLKLCD = count then CLKLCD goes to output10
		variable read_done : boolean := false; -- check to see if done reading from SD card
		
		
		-- these variables store the output port for the respective inputs, used to keep refreshing the outputs with the inputs
		variable CLKLCD_BUF : natural range 0 to 40 := 0;
		variable LCD_RESET_BUF : natural range 0 to 40 := 0;
		variable CS1_BUF : natural range 0 to 40 := 0;
		variable CS2_BUF : natural range 0 to 40 := 0;
		variable A0_BUF : natural range 0 to 40 := 0;
		variable WR_BUF : natural range 0 to 40 := 0;
		variable RD_SDA_BUF : natural range 0 to 40 := 0;
		variable CLKIN_BUF : natural range 0 to 40 := 0;
		variable D0_BUF : natural range 0 to 40 := 0;
		variable D1_BUF : natural range 0 to 40 := 0;
		variable D2_BUF : natural range 0 to 40 := 0;
		variable D3_BUF : natural range 0 to 40 := 0;
		variable D4_BUF : natural range 0 to 40 := 0;
		variable D5_BUF : natural range 0 to 40 := 0;
		variable D6_BUF : natural range 0 to 40 := 0;
		variable D7_BUF : natural range 0 to 40 := 0;
		
		-- FUNCTION DECLARATION --
		
		
		-- this function is to convert the received binary (16 bits/2 bytes) into a integer (2 digits)
		function binary_to_integer(binary: STD_LOGIC_VECTOR(15 downto 0)) return integer is -- this function converts the byte (binary) to integer
		variable number: integer range 0 to 40;
		 begin
			case binary is
				when "0011000000110000" => number := 0;
				when "0011000000110001" => number := 1;
				when "0011000000110010" => number := 2;
				when "0011000000110011" => number := 3;
				when "0011000000110100" => number := 4;
				when "0011000000110101" => number := 5;
				when "0011000000110110" => number := 6;
				when "0011000000110111" => number := 7;
				when "0011000000111000" => number := 8;
				when "0011000000111001" => number := 9;
				when "0011000100110000" => number := 10;
				when "0011000100110001" => number := 11;
				when "0011000100110010" => number := 12;
				when "0011000100110011" => number := 13;
				when "0011000100110100" => number := 14;
				when "0011000100110101" => number := 15;
				when "0011000100110110" => number := 16;
				when "0011000100110111" => number := 17;
				when "0011000100111000" => number := 18;
				when "0011000100111001" => number := 19;
				when "0011001000110000" => number := 20;
				when "0011001000110001" => number := 21;
				when "0011001000110010" => number := 22;
				when "0011001000110011" => number := 23;
				when "0011001000110100" => number := 24;
				when "0011001000110101" => number := 25;
				when "0011001000110110" => number := 26;
				when "0011001000110111" => number := 27;
				when "0011001000111000" => number := 28;
				when "0011001000111001" => number := 29;
				when "0011001100110000" => number := 30;
				when "0011001100110001" => number := 31;
				when "0011001100110010" => number := 32;
				when "0011001100110011" => number := 33;
				when "0011001100110100" => number := 34;
				when "0011001100110101" => number := 35;
				when "0011001100110110" => number := 36;
				when "0011001100110111" => number := 37;
				when "0011001100111000" => number := 38;
				when "0011001100111001" => number := 39;
				when "0011010000110000" => number := 40;
				when others => number := 0;
			end case;
		 return number;
		end binary_to_integer;
	
		-- END OF FUNCTION DECLARATION --
	
	begin
		
		if rising_edge(CLOCK) then
		
			if read_done = false then -- false if not done reading all info from SD card
			
				if count = 3 then -- when count = 3 means 2 bytes have been received
					case portcounter is
					when 0 =>
						CLKLCD_BUF :=  binary_to_integer(recv_data); -- convert received data into integer for port buffer
					when 1 =>
						LCD_RESET_BUF := binary_to_integer(recv_data);
					when 2 =>
						CS1_BUF := binary_to_integer(recv_data);
					when 3 =>
						CS2_BUF := binary_to_integer(recv_data);
					when 4 => 
						A0_BUF := binary_to_integer(recv_data);
					when 5 =>
						WR_BUF := binary_to_integer(recv_data);
					when 6 =>
						RD_SDA_BUF := binary_to_integer(recv_data);
					when 7 =>
						CLKIN_BUF := binary_to_integer(recv_data);
					when 8 =>
						D0_BUF := binary_to_integer(recv_data);
					when 9 =>
						D1_BUF := binary_to_integer(recv_data);
					when 10 =>
						D2_BUF := binary_to_integer(recv_data);
					when 11 =>
						D3_BUF := binary_to_integer(recv_data);
					when 12 =>
						D4_BUF := binary_to_integer(recv_data);
					when 13 =>
						D5_BUF := binary_to_integer(recv_data);
					when 14 =>
						D6_BUF := binary_to_integer(recv_data);
					when 15 =>
						D7_BUF := binary_to_integer(recv_data);
					end case;
					portcounter := portcounter + 1;
					count := 1;
				end if;
				
			
				case state is	
					
					when INIT =>		-- CS=1, send 80 (slave)clocks, then CS=0
						if (bit_counter = 0) then
							SD_CS <= '0'; -- chip select low
							state <= CMD0;
						else
							bit_counter := bit_counter - 1;
							sclk_sig <= not sclk_sig; -- this is to set slave clock to half of master clock
						end if;	
							
					when CMD0 =>	
						cmd_out <= x"FF400000000095"; -- CMD 0 "go idle state"
						bit_counter := 55; -- always 55 bits because protocol requires 7 high bits after command
						return_state <= CMD55;
						state <= SEND_CMD;
						
					when CMD55 =>
						cmd_out <= x"FF770000000001";	-- 55d OR 40h = 77h
						bit_counter := 55;
						return_state <= CMD41;
						state <= SEND_CMD;
					
					when CMD41 =>
						cmd_out <= x"FF690000000001";	-- 41d OR 40h = 69h
						bit_counter := 55;
						return_state <= POLL_CMD;
						state <= SEND_CMD;
						
					when POLL_CMD =>
						if (recv_data(0) = '0') then
							state <= READ_BLOCK;
						else
							state <= CMD55;
						end if;
						
					when READ_BLOCK =>	
						cmd_out <= x"FF" & x"51" & address & x"FF"; -- change address setting in state RESET
						bit_counter := 55;
						return_state <= READ_BLOCK_WAIT;
						state <= SEND_CMD;
			
					when READ_BLOCK_WAIT =>
						if (sclk_sig = '1' and SD_MISO = '0') then
							state <= READ_BLOCK_DATA;
							--byte_counter := 511; -- always read blocks of 512 bytes TRY AND SEE IF 63 WOULD WORK, IF YES THEN DISABLE CRC ALTOGETHER
							byte_counter := 31; -- data file is only 32 bytes big
							bit_counter := 7;
							return_state <= READ_BLOCK_DATA;
							state <= RECEIVE_BYTE;
						end if;
						sclk_sig <= not sclk_sig;
					
					when READ_BLOCK_DATA =>
						if (byte_counter = 0) then
							bit_counter := 7;
							return_state <= IDLE;
							state <= RECEIVE_BYTE;
						else
							byte_counter := byte_counter - 1;
							return_state <= READ_BLOCK_DATA;
							bit_counter := 7;
							state <= RECEIVE_BYTE;
						end if;
					
					when RECEIVE_BYTE_WAIT =>
						if (sclk_sig = '1') then	
							if (SD_MISO = '0') then			
								recv_data <= (others => '0');
								bit_counter := 6; -- already read bit 7
								state <= RECEIVE_BYTE;			
							end if;		
						end if;
						sclk_sig <= not sclk_sig;
					
					when RECEIVE_BYTE =>
						if (sclk_sig = '1') then				
							recv_data <= recv_data(14 downto 0) & SD_MISO;
							if (bit_counter = 0) then
								--recv_data <= recv_data(14 downto 0) & SD_MISO; -- might not need
								state <= return_state;
								if (return_state = IDLE) or (return_state = READ_BLOCK_DATA) then -- check if byte needs to be stored
									count := count + 1; -- byte required to be stored, increment count such that when count = 3 means 2 bytes received
								else
									count := 1; -- not required, so reset count to 1
								end if;
							else
								bit_counter := bit_counter - 1;
							end if;
						end if;
						sclk_sig <= not sclk_sig;
					
					
					when SEND_CMD =>	
						if (sclk_sig = '1') then
							if (bit_counter = 0) then
								state <= RECEIVE_BYTE_WAIT;
							else
								bit_counter := bit_counter - 1;
								cmd_out <= cmd_out(54 downto 0) & '1';
							end if;
						end if;			
						sclk_sig <= not sclk_sig;
					
					when IDLE => 
						read_done := true; -- done storing all info, move on to port assignment
					
				end case;
			
			else -- read_done = true, done reading data from SD card, assign input ports to output ports
			
				LED <= '1'; -- turn on LED
				PUDC_B <= '1'; -- standard procedure
				LS_OUT_DE <= '0'; -- standard procedure
				LS_IN_DE <= '0'; -- standard procedure
				PROM_DE <= '1'; -- standard procedure
				CSO_B <= '1'; -- standard procedure
				
				for count in 1 to 40 loop -- loop count and check each buffer, if similar then output = that particular input
					
					if count = CLKLCD_BUF then
						FPGA_OUT(CLKLCD_BUF) <= CLKLCD;
					
					elsif count = LCD_RESET_BUF then
						FPGA_OUT(LCD_RESET_BUF) <= LCD_RESET;
					
					elsif count = CS1_BUF then
						FPGA_OUT(CS1_BUF) <= CS1;
					
					elsif count = CS2_BUF then
						FPGA_OUT(CS2_BUF) <= CS2;
					
					elsif count = A0_BUF then
						FPGA_OUT(A0_BUF) <= A0;
					
					elsif count = WR_BUF then
						FPGA_OUT(WR_BUF) <= WR;
					
					elsif count = RD_SDA_BUF then
						FPGA_OUT(RD_SDA_BUF) <= RD_SDA;
					
					elsif count = CLKIN_BUF then
						FPGA_OUT(CLKIN_BUF) <= CLKIN;
					
					elsif count = D0_BUF then
						FPGA_OUT(D0_BUF) <= D0;
					
					elsif count = D1_BUF then
						FPGA_OUT(D1_BUF) <= D1;
					
					elsif count = D2_BUF then
						FPGA_OUT(D2_BUF) <= D2;
					
					elsif count = D3_BUF then
						FPGA_OUT(D3_BUF) <= D3;
					
					elsif count = D4_BUF then
						FPGA_OUT(D4_BUF) <= D4;
					
					elsif count = D5_BUF then
						FPGA_OUT(D5_BUF) <= D5;
					
					elsif count = D6_BUF then
						FPGA_OUT(D6_BUF) <= D6;
					
					elsif count = D7_BUF then
						FPGA_OUT(D7_BUF) <= D7;
					
					else
						null;
					end if;
					
				end loop;
				
			end if; -- end read_done = false;
			
		end if;
		
	end process;
	
SD_CLK <= sclk_sig; -- set slave clock
SD_MOSI <= cmd_out(55); -- send 1 bit to MOSI line
end Behavioral;
 

one method might be to use a different method to perform the operations. I have a feeling the largest part of the design is the switches. if you have a fast clock, you could fix this by cycling data around. eg, viewing this as a networking operation, this could be viewed as token-ring. now each register routes to two places -- the output register and the next register in the chain.

Another method would be to use block rams. or rams. you could strobe the lines, then use the address lines to select the correct bit. again, you get gains because you split the operation over multiple cycles in a manner that reduces area.
 
  • Like
Reactions: ptjw

    ptjw

    Points: 2
    Helpful Answer Positive Rating
oh beautiful...

your answer helped me realize one thing that i totally overlooked all this while...

the Spartan 3A operates at 16MHz, and i am trying to interface with a LCD screen which definitely doesn't operate at that speed. your sentence "if you have a fast clock, you could fix this by cycling data around." helped me realize this :)

Code:
                               if count = CLKLCD_BUF then
					FPGA_OUT(CLKLCD_BUF) <= CLKLCD;
				
				elsif count = LCD_RESET_BUF then
					FPGA_OUT(LCD_RESET_BUF) <= LCD_RESET;
				
				elsif count = CS1_BUF then
					FPGA_OUT(CS1_BUF) <= CS1;
				
				elsif count = CS2_BUF then
					FPGA_OUT(CS2_BUF) <= CS2;
				
				elsif count = A0_BUF then
					FPGA_OUT(A0_BUF) <= A0;
				
				elsif count = WR_BUF then
					FPGA_OUT(WR_BUF) <= WR;
				
				elsif count = RD_SDA_BUF then
					FPGA_OUT(RD_SDA_BUF) <= RD_SDA;
				
				elsif count = CLKIN_BUF then
					FPGA_OUT(CLKIN_BUF) <= CLKIN;
				
				elsif count = D0_BUF then
					FPGA_OUT(D0_BUF) <= D0;
				
				elsif count = D1_BUF then
					FPGA_OUT(D1_BUF) <= D1;
				
				elsif count = D2_BUF then
					FPGA_OUT(D2_BUF) <= D2;
				
				elsif count = D3_BUF then
					FPGA_OUT(D3_BUF) <= D3;
				
				elsif count = D4_BUF then
					FPGA_OUT(D4_BUF) <= D4;
				
				elsif count = D5_BUF then
					FPGA_OUT(D5_BUF) <= D5;
				
				elsif count = D6_BUF then
					FPGA_OUT(D6_BUF) <= D6;
				
				elsif count = D7_BUF then
					FPGA_OUT(D7_BUF) <= D7;
				end if;

				
				if count = 40 then
					count := 1;
					LED <= '1'; -- turn on LED
					PUDC_B <= '1'; -- standard procedure
					LS_OUT_DE <= '0'; -- standard procedure
					LS_IN_DE <= '0'; -- standard procedure
					PROM_DE <= '1'; -- standard procedure
					CSO_B <= '1'; -- standard procedure
				else
					count := count + 1;
				end if;

i changed my code to update one port once every 40 cycles since i have 40 ports, i guess by doing this i would be putting less strain on the resources. when i synthesized i got 99% of slices used which is actually worse than my previous result 8O but i went ahead to implement the design and the map report comes out like so:

Code:
Number of errors:      0
Number of warnings:    0
Logic Utilization:
  Number of Slice Flip Flops:           212 out of   1,408   15%
  Number of 4 input LUTs:             1,250 out of   1,408   88%
Logic Distribution:
  Number of occupied Slices:            688 out of     704   97%
    Number of Slices containing only related logic:     688 out of     688 100%
    Number of Slices containing unrelated logic:          0 out of     688   0%
      *See NOTES below for an explanation of the effects of unrelated logic.
  Total Number of 4 input LUTs:       1,250 out of   1,408   88%
  Number of bonded IOBs:                 67 out of     108   62%
    IOB Flip Flops:                      44
  Number of BUFGMUXs:                     1 out of      24    4%

Average Fanout of Non-Clock Nets:                3.62

the most beautiful block of text i have seen for the past 2 weeks *sniff*, 97% of slices occupied..

thanks!
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top