VHDL register file synthesis

S

stoyan.shopov

Hi everybody,
I am quite new to VHDL and I have some questions. I am trying to
build a register file consisting of 16 registers, each 32 bits wide.
The register file I need must have two outputs - two of the registers
must be driven on two output buses at any time. The register file
is updated synchronously on the rising edge of clock.
I use Xilinx ISE 6.2.
I am sorry that I put here so much code, but it is simple code
and should not take much time to read.

As a building block I use the 'reg' entity listed below.

entity reg is
Port ( din : in std_logic_vector(31 downto 0); -- data input for
register update
dout : out std_logic_vector(31 downto 0); -- data output
(tristate)
dout1 : out std_logic_vector(31 downto 0); -- identical as
dout above
wr : in std_logic; -- write strobe
wren : in std_logic; -- write enable; I shall make these clear
below
clk : in std_logic; -- clock input
oe : in std_logic; -- output enable for dout output
oe1 : in std_logic); -- output enable for daout1 output
end reg;

architecture Behavioral of reg is

signal idata: std_logic_vector(31 downto 0);

begin

update_reg: process(clk)
begin

if clk'event and clk = '1' then
if wr = '1' and wren = '1' then
idata <= din;
end if;
end if;

end process;

drive_output: process(idata, oe, oe1)
begin
-- drive first output
if oe = '1' then
dout <= idata;
else
dout <= (others => 'Z');
end if;
-- drive second output
if oe1 = '1' then
dout1 <= idata;
else
dout1 <= (others => 'Z');
end if;

end process;

end Behavioral;
----------------------------------------------------------------------------
The register is updated on the rising edge of the clock, whenever at
that
time wr AND wren are both high.

Using the reg entity, I have built a register file with the following
structure:
----------------------------------------------------------------------------
entity regarray is
Port ( din : in std_logic_vector(31 downto 0); -- data input for
register update
dout : out std_logic_vector(31 downto 0); -- data output
dout1 : out std_logic_vector(31 downto 0); -- second data
output
clk : in std_logic; -- clock input
wr : in std_logic; -- write strobe
wrsel : in std_logic_vector(3 downto 0); -- selects a
register to update
rsel : in std_logic_vector(3 downto 0); -- selects a
register for dout
rsel1 : in std_logic_vector(3 downto 0)); -- selects a
register for dout1
end regarray;

architecture Behavioral of regarray is

component reg is
Port ( din : in std_logic_vector(31 downto 0);
dout : out std_logic_vector(31 downto 0);
dout1 : out std_logic_vector(31 downto 0);
wr : in std_logic;
wren : in std_logic;
clk : in std_logic;
oe : in std_logic;
oe1 : in std_logic);
end component;

signal rseldec : std_logic_vector(15 downto 0); -- decoder for
selecting a register for dout
signal rseldec1 : std_logic_vector(15 downto 0); -- decoder for
selecting a register for dout1
signal wrseldec : std_logic_vector(15 downto 0); -- decoder for
selecting a register to update

begin

-- instantiate registers - 16 registers
reg0: reg port map(din, dout, dout1, wrseldec(0), wr, clk, rseldec(0),
rseldec1(0));
reg1: reg port map(din, dout, dout1, wrseldec(1), wr, clk, rseldec(1),
rseldec1(1));
....
reg15: reg port map(din, dout, dout1, wrseldec(15), wr, clk,
rseldec(15), rseldec1(15));

-- infer decoder for dout register select
with rsel select rseldec <=
"0000000000000001" when "0000",
"0000000000000010" when "0001",
...
"1000000000000000" when others;

-- infer decoder for dout1 register select
with rsel1 select rseldec1 <=
"0000000000000001" when "0000",
"0000000000000010" when "0001",
...
"1000000000000000" when others;

-- infer decoder for register update select
with wrsel select wrseldec <=
"0000000000000001" when "0000",
"0000000000000010" when "0001",
...
"1000000000000000" when others;

end Behavioral;

My question is: taking in account the requirements for the register
file
(two outputs, synchronous update), is my implementation correct?
I had a look at the generated schematics (I use Xilinx ISE 6.2)
and it looked fine to me - just what I had imagined - registers,
decoders,
tristate buffers. Is there a better way to code such a register file?
I tried another implementation with two multiplexers instead of
tri-state buses,
but it was taking more space on the FPGA I use (Spartan 3).
Also, I got some warning from the synthesizer that I am clueless about:
WARNING:Xst:1904 - Unit regarray : signal N5634 : Multi-source of
tristates is replaced by logic
There are 64 such warnings and they are apparently concerning the two
output
buses. I think that I am not driving the tristate buffers properly,
but this is the best I could think of. Can you help, please.
Thank you very much!

Stoyan Shopov
 
M

Mohammed A khader

HI,

That is not the way to write Register Files. You could check the code
below . It has synchronous write and asynchornous read.

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity Regfile is
generic( DATA_WIDTH : natural := 32;
ADDRS_WIDTH : natural := 4
);
port(
Data_In : in signed(DATA_WIDTH-1 downto 0); -- Input Data

Addrs_In : in unsigned(ADDRS_WIDTH-1 downto 0); -- Input
Address
Addrs1_Out : in unsigned(ADDRS_WIDTH-1 downto 0); -- Output
Address 1
Addrs2_Out : in unsigned(ADDRS_WIDTH-1 downto 0); -- Output Address
2
Wr_En : in std_logic; -- Write Enable
Clk : in std_logic; -- Global Clk

Data1_Out : out signed(DATA_WIDTH-1 downto 0); -- Output Data 1
Data2_Out : out signed(DATA_WIDTH-1 downto 0) -- Output Data 2
);
end entity Regfile;

architecture Regfile_Arch of Regfile is
-- Declarations of Register File type & signal
type Regfile_type is array (natural range<>) of signed(DATA_WIDTH-1
downto 0);
signal Regfile_Coff : Regfile_type(0 to ADDRS_WIDTH-1);
begin
--------------------------------------------------------
-- Concurrent Statements

-- Regfile_Read Assignments
Data1_Out <= Regfile_Coff(TO_INTEGER(Addrs1_Out));
Data2_Out <= Regfile_Coff(TO_INTEGER(addrs2_Out));
--------------------------------------------------------
-- Sequential Process
-- Register File Write Process
Regfile_Write:process(Clk)
begin

if(RISING_EDGE(Clk))then
if(Wr_En = '1')then
Regfile_Coff(TO_INTEGER(Addrs_In)) <= Data_In;
end if;
end if;

end process Regfile_Write;
 
M

Mike Treseler

My question is: taking in account the requirements for the register
file
(two outputs, synchronous update), is my implementation correct?
I had a look at the generated schematics (I use Xilinx ISE 6.2)
and it looked fine to me - just what I had imagined - registers,
decoders, tristate buffers.

That's a good sign, but the only way to
answer the question is to write a simulation
testbench and verify the waveforms.
Is there a better way to code such a register file?

Consider deferring changes until verification
is complete.

-- Mike Treseler
 
S

stoyan.shopov

Thank you, Mohammed! I tried your code, not only it is more compact and
readable but the synthesis tool managed to infer a dual port ram
component, which is a primitive in the FPGA I use (Spartan 3) and so it
took much less space than my implementation!
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top