Implementing multiple registers with one single input output

J

James Williams

Guest
Hello,

I am just now learning VHDL and am wondering how I work write code to use
one single 8bit in/out pins, which is mapped to 4 internal 8bit registers,
which can either be read or written too. It of course would has a 2 bit
address select. I know how to do the entity declaration, I'm not quite sure
how to do the arch process. Here is what I am thinking, please tell me if I
am doing this wrong.

Note also that this is just an example on not my actual project.


entity myMemory is
port (Clk : in std_logic;
DataIo :inout std_logic_vector (7 downto 0) Bus :=(others=>'Z');
OutEn : in std_logic_vector; --Enables the output buffers.
Write : in std_logic; --Write to memory " Active low"
Read : in std_logic; --Read from memory "Active low"
Addr : in std_logic_vector (1 downto 0));
end myMemory;
architecture Behavioral of myMemory is
signal Reg0 : std_logic_vector (7 downto 0);
signal Reg1 : std_logic_vector (7 downto 0);
signal Reg2 : std_logic_vector (7 downto 0);
signal Reg3 : std_logic_vector (7 downto 0);
begin
process(Clk) begin
if(Clk'event and Clk='1') then
case Addr is
when "00"=>
if(Read='0' and Write='1' and 'OutEn='1') then
DataIo<=Reg0;
elsif (Read='1' and Write='0' and OutEn='X') then
Reg0<=DataIo;
else DataIo<=(others=>'Z');
when "01"=>
if(Read='0' and Write='1' and 'OutEn='1') then
DataIo<=Reg1;
elsif (Read='1' and Write='0' and OutEn='X') then
Reg1<=DataIo;
else DataIo<=(others=>'Z');
when "10"=>
if(Read='0' and Write='1' and 'OutEn='1') then
DataIo<=Reg2;
elsif (Read='1' and Write='0' and OutEn='X') then
Reg2<=DataIo;
else DataIo<=(others=>'Z');
when "11"=>
if(Read='0' and Write='1' and 'OutEn='1') then
DataIo<=Reg3;
elsif (Read='1' and Write='0' and OutEn='X') then
Reg3<=DataIo;
else DataIo<=(others=>'Z');
when others =>
if(OutEn='0' then DataIo<=(others=>'Z');
end if;
end case;

end if;
end process;
end Behavioral;
 
James,
Before coding, you want to start with a good picture
of the hardware in your mind (or even better on paper).

Your code probably has a few surprises in it. There is
a register on DataIO and on OutEn. Is this what you wanted?

First a couple of HDL principles
1) Any signal assignment in a clocked process (one that
has "wait until Clk='1'", or an if expression with 'event or rising_edge).
2) Always code tristates separate from all other logic
(avoids a number of issues).
3) Don't code things that your hardware implementation
already guarantee's (such as read and write being
mutually exclusive - if you need to check them, then
use an assert statement).

What I would suggest is to write it as three separate
pieces of code.
1) A register bank that accepts writes to the correct address
2) A Multiplexer for read back
3) A Tristate


Recoding your design a little:

-- Writing to register bank
RegBankProc : process(Clk) begin
if rising_edge(Clk) then
if Write = '1' and ChipEnable = '1' then
case Addr is
when "00"=> Reg0<=DataIo;
when "01"=> Reg1<=DataIo;
when "10"=> Reg2<=DataIo;
when "11"=> Reg3<=DataIo;
when others =>
-- report not required, but good for validation
report "address invalid during valid write"
severity error ;
end case ;
end if ;
end if ;
end process ;

-- Readback Multiplexer
ReadBackMuxProc : process(Addr, Read)
begin
DataIo_int <= (Others => 'X') ; -- Default value if not read
if Read = '1' and ChipEnable = '1' then
case Addr is
when "00"=> DataIo_int <=Reg0;
when "01"=> DataIo_int <=Reg1;
when "10"=> DataIo_int <=Reg2;
when "11"=> DataIo_int <=Reg3;
when others =>
-- report not required, but good for validation
report "address invalid during valid read"
severity error ;
end case ;
end if ;
end process ;

-- Tristate (process also ok)
with OutEn select
DataIo <=
DataIo_int when '1',
(others => 'Z') when '0',
(others => 'X') when others ;

-- Check for bad things,
-- not required, but good for validation
-- addresses issues in your code without creating hardware
assert not (ChipEnable='1' and Read='1' and Write='1')
report "Read and Write asserted simultaneously"
severity ERROR ;

Cheers,
Jim
--
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Jim Lewis
Director of Training mailto:Jim@SynthWorks.com
SynthWorks Design Inc. http://www.SynthWorks.com
1-503-590-4787

Expert VHDL Training for Hardware Design and Verification
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


James Williams wrote:

Hello,

I am just now learning VHDL and am wondering how I work write code to use
one single 8bit in/out pins, which is mapped to 4 internal 8bit registers,
which can either be read or written too. It of course would has a 2 bit
address select. I know how to do the entity declaration, I'm not quite sure
how to do the arch process. Here is what I am thinking, please tell me if I
am doing this wrong.

Note also that this is just an example on not my actual project.


entity myMemory is
port (Clk : in std_logic;
DataIo :inout std_logic_vector (7 downto 0) Bus :=(others=>'Z');
OutEn : in std_logic_vector; --Enables the output buffers.
Write : in std_logic; --Write to memory " Active low"
Read : in std_logic; --Read from memory "Active low"
Addr : in std_logic_vector (1 downto 0));
end myMemory;
architecture Behavioral of myMemory is
signal Reg0 : std_logic_vector (7 downto 0);
signal Reg1 : std_logic_vector (7 downto 0);
signal Reg2 : std_logic_vector (7 downto 0);
signal Reg3 : std_logic_vector (7 downto 0);
begin
process(Clk) begin
if(Clk'event and Clk='1') then
case Addr is
when "00"=
if(Read='0' and Write='1' and 'OutEn='1') then
DataIo<=Reg0;
elsif (Read='1' and Write='0' and OutEn='X') then
Reg0<=DataIo;
else DataIo<=(others=>'Z');
when "01"=
if(Read='0' and Write='1' and 'OutEn='1') then
DataIo<=Reg1;
elsif (Read='1' and Write='0' and OutEn='X') then
Reg1<=DataIo;
else DataIo<=(others=>'Z');
when "10"=
if(Read='0' and Write='1' and 'OutEn='1') then
DataIo<=Reg2;
elsif (Read='1' and Write='0' and OutEn='X') then
Reg2<=DataIo;
else DataIo<=(others=>'Z');
when "11"=
if(Read='0' and Write='1' and 'OutEn='1') then
DataIo<=Reg3;
elsif (Read='1' and Write='0' and OutEn='X') then
Reg3<=DataIo;
else DataIo<=(others=>'Z');
when others =
if(OutEn='0' then DataIo<=(others=>'Z');
end if;
end case;

end if;
end process;
end Behavioral;
 

Welcome to EDABoard.com

Sponsor

Back
Top