Generic for port with array type

N

nivparsons

I have a package that declares an array of STD_LOGIC, so I can use a
generic to declare the port width and internal signal width(s).

However, this is used on a 32 bit processor bus with separate byte
enables.

So, how can assign writes (& reads) to signals on a byte by byte
allocation when the width is generic?

I thought of something like: (ignoring write & read strobes etc).

IF byte_en_0 THEN
IF generic > 7 THEN
my_signal(7:0) <= cpu_bus(7:0);
ELSE
my_signal(generic - 1:0) <= cpu_bus(generic-1 :0);
END IF;

IF byte_en_1 THEN
IF generic > 15 THEN
my_signal(15:8) <= cpu_bus(15:8);
ELSIF generic > 8 THEN
my_signal(generic - 1:8) <= cpu_bus(generic-1 :8);
ELSE
NULL;
END IF;

-- and similarly for byte_enable 2 & 3.
I believe the above works, but seems very messy, is there a neater way
please?
 
K

KJ

I have a package that declares an array of STD_LOGIC, so I can use a
generic to declare the port width and internal signal width(s).

However, this is used on a 32 bit processor bus with separate byte
enables.

So, how can assign writes (& reads) to signals on a byte by byte
allocation when the width is generic?

I thought of something like: (ignoring write & read strobes etc).

IF byte_en_0 THEN
IF generic > 7 THEN
my_signal(7:0) <= cpu_bus(7:0);
ELSE
my_signal(generic - 1:0) <= cpu_bus(generic-1 :0);
END IF;

IF byte_en_1 THEN
IF generic > 15 THEN
my_signal(15:8) <= cpu_bus(15:8);
ELSIF generic > 8 THEN
my_signal(generic - 1:8) <= cpu_bus(generic-1 :8);
ELSE
NULL;
END IF;

-- and similarly for byte_enable 2 & 3.
I believe the above works, but seems very messy, is there a neater way
please?

First recognize that the byte enables are a vector of width 'generic/8'. So the byte enable and data should be declared as:

generic(data_width: in natural)
....
cpu_bus(datawidth-1 downto 0);
byte_enable(datawidth/-1 downto 0);

Now you modify your code to index through the byte enables like this...

for i in byte_en'range loop
IF byte_en(i) THEN
my_signal(8*i+7 downto 8*i) <= cpu_bus(8*i+7 downto 8*i);
END IF;
end loop;

Kevin Jennings
 
N

nivparsons

First recognize that the byte enables are a vector of width 'generic/8'. So the byte enable and data should be declared as:

generic(data_width: in natural)
...
cpu_bus(datawidth-1 downto 0);
byte_enable(datawidth/-1 downto 0);

Now you modify your code to index through the byte enables like this...

for i in byte_en'range loop
IF byte_en(i) THEN
my_signal(8*i+7 downto 8*i) <= cpu_bus(8*i+7 downto 8*i);
END IF;
end loop;

Kevin Jennings

I see what you mean, but this doesn't handle things when the bus is,say, 19 bit s wide. OK for byte enables 0 & 1, but it wont really handl ebyte enable 2, which needs to handle just 3 bits.

Niv
 
K

KJ

On Saturday, May 19, 2012 6:04:46 PM UTC+1, KJ wrote:

I see what you mean, but this doesn't handle things when the bus is,say, 19 bit s wide. OK for byte enables 0 & 1, but it wont really handl ebyte enable 2, which needs to handle just 3 bits.
A 'byte' enable would imply 8 bits, which is the solution I provided. For your new problem, there is only a slight modification required which is contained in the innermost 'if' statement.

for i in byte_en'range loop
IF byte_en(i) THEN
if 8*i+7 > my_signal'high then
my_signal(my_signal'high downto 8*i) <= cpu_bus(my_signal'high downto 8*i);
else
my_signal(8*i+7 downto 8*i) <= cpu_bus(8*i+7 downto 8*i);
end if;
END IF;
end loop;

Kevin Jennings
 
N

nivparsons

A 'byte' enable would imply 8 bits, which is the solution I provided. For your new problem, there is only a slight modification required which is contained in the innermost 'if' statement.

for i in byte_en'range loop
IF byte_en(i) THEN
if 8*i+7 > my_signal'high then
my_signal(my_signal'high downto 8*i) <= cpu_bus(my_signal'high downto 8*i);
else
my_signal(8*i+7 downto 8*i) <= cpu_bus(8*i+7 downto 8*i);
end if;
END IF;
end loop;

Kevin Jennings

I sorted what I wanted with a hint from your code.
I needed my port width and associated registers to have the generic width, anywhere between 1 & 32, but writes to regs were from a CPU bus with separate byte write enable, so here is what I did: (code obfuscated a bit).

write_to_registers : PROCESS (clk_66)
BEGIN
IF rising_edge(clk_66) THEN
IF reset = '1' THEN
sig_1 <= (OTHERS => '0');
sig_2 <= (OTHERS => '0');
ELSE

sig_1 <= (OTHERS => '0'); -- Default condition.

FOR i IN 0 TO 3 LOOP
IF write_strb(i) = '1' THEN
CASE address_bus IS
WHEN addr_sig_1 =>

IF GENERIC >= (8*i + 7) THEN
sig_1(8*i+7 DOWNTO 8*i) <= write_data_bus(8*i+7 DOWNTO 8*i);
ELSE
IF GENERIC >= (8*i + 1) THEN
sig_1(GENERIC-1 DOWNTO 8*i) <= write_data_bus(GENERIC-1 DOWNTO 8*i);
ELSE
NULL;
END IF;
END IF;

WHEN addr_sig_2 =>
sig_2(8*i+7 DOWNTO 8*i) <= write_data_bus(8*i+7 DOWNTO 8*i); -- Full 32 bit allocation

WHEN OTHERS => NULL;

END CASE;
END IF;
END LOOP;

END IF;
END IF;
END PROCESS write_to_registers;
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top