Reputation: 53
I have the following VHDL code to 1k x 8bit RAM:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY RAM IS
PORT(
DATA : INOUT STD_LOGIC_VECTOR(7 DOWNTO 0); -- data to/from external pin on bi-dir 8 bit bus
ADDR : IN STD_LOGIC_VECTOR(9 DOWNTO 0); -- address from external pin on input 10 bit bus
RW : IN STD_LOGIC;
CS : IN STD_LOGIC
);
END ENTITY;
ARCHITECTURE BEV OF RAM IS
TYPE MEM IS ARRAY (1023 DOWNTO 0) OF STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL MEMORY : MEM;
SIGNAL ADDRESS : INTEGER RANGE 0 TO 1023;
BEGIN
PROCESS(ADDR, DATA, RW, CS)
BEGIN
ADDRESS <= CONV_INTEGER(ADDR);
IF(CS = '0')THEN
IF(RW = '0') THEN
MEMORY(ADDRESS) <= DATA;
ELSE
DATA <= MEMORY(ADDRESS);
END IF;
ELSE
DATA <= "ZZZZZZZZ";
END IF;
END PROCESS;
END BEV;
But I'd like the following final port:
(I just put the part that initializes the PORTs of the module, to show what I would like to modify the above code)
ENTITY RAM IS
PORT(
D0 : INOUT STD_LOGIC; -- data to/from external pin on bi-dir 1 bit wire LSB
D1 : INOUT STD_LOGIC; -- data to/from external pin on bi-dir 1 bit wire
D2 : INOUT STD_LOGIC; -- data to/from external pin on bi-dir 1 bit wire
D3 : INOUT STD_LOGIC; -- data to/from external pin on bi-dir 1 bit wire
D4 : INOUT STD_LOGIC; -- data to/from external pin on bi-dir 1 bit wire
D5 : INOUT STD_LOGIC; -- data to/from external pin on bi-dir 1 bit wire
D6 : INOUT STD_LOGIC; -- data to/from external pin on bi-dir 1 bit wire
D7 : INOUT STD_LOGIC; -- data to/from external pin on bi-dir 1 bit wire HSB
A0 : IN STD_LOGIC; -- address from external pin on input 1 bit wire LSB
A1 : IN STD_LOGIC; -- address from external pin on input 1 bit wire
A2 : IN STD_LOGIC; -- address from external pin on input 1 bit wire
A3 : IN STD_LOGIC; -- address from external pin on input 1 bit wire
A4 : IN STD_LOGIC; -- address from external pin on input 1 bit wire
A5 : IN STD_LOGIC; -- address from external pin on input 1 bit wire
A6 : IN STD_LOGIC; -- address from external pin on input 1 bit wire
A7 : IN STD_LOGIC; -- address from external pin on input 1 bit wire
A8 : IN STD_LOGIC; -- address from external pin on input 1 bit wire
A9 : IN STD_LOGIC; -- address from external pin on input 1 bit wire HSB
RW : IN STD_LOGIC;
CS : IN STD_LOGIC
);
END ENTITY;
I would like to replace the STD_LOGIC_VECTORs by STD_LOGICs (wires).
Could someone help me with this? :)
Hi, I'd like so much to thank everyone who contributed to this post. And now I'd like also to add a few things, that I learned during this period, on the same subject, to help beginners like me.
There are 2 ways to "make" a memory (if there are more ways, I still not learned!): Or using internal logic of FPGA (as seen here earlier, in this post)... Or using internal memory of FPGA (from what I understand, this is possible only in models that have this internal memory).
In the first case, FPGA consumption is large, and if you want to do something else, perhaps will not be possible (which is my case).
In the second case the FPGA consumption is 0 or minimum. There will be only the consumption of internal memory, saving the logic of the FPGA.
So, I figured it would be better for me, to use the ready model, that Altera Quartus offers and modifies it as I learned here. It was also cool, that in this way I learned also other forms of how to write a program in VHDL.
In the first case, is used "PROCESS ()" and "END PROCESS;" and this way I can use the "IF () THEN", as seen in the examples presented here (above).
But in the second case (below), is not possible to use the "IF () THEN". After a brief search, I found the document "VHDL Math Tricks of the Trade.pdf", and learned that it could use the following sentence:
X <= VALUE when (LOGIC) else ANOTHER_VALUE;
This way I managed to solve another problem that existed in the second option of memory (in the library), which is the fact of not having a control pin to put the memory in tri-state or disables it.
In the example below I managed to fit buses (address and data) and add a pin control, as I needed. (I left the original part commented)
Once again, I like to thank, the help of those who participated in the post, with excellent examples.
Thank you guys.
-- ============================================================
-- megafunction wizard: %ROM: 1-PORT%
--
-- GENERATION: STANDARD
-- VERSION: WM1.0
-- MODULE: altsyncram
-- File Name: ROM.vhd
-- Megafunction Name(s): altsyncram
-- Simulation Library Files(s): altera_mf
-- ============================================================
LIBRARY ieee;
USE ieee.std_logic_1164.all;
LIBRARY altera_mf;
USE altera_mf.all;
ENTITY ROM IS
PORT
(
A0 : IN STD_LOGIC;
A1 : IN STD_LOGIC;
A2 : IN STD_LOGIC;
A3 : IN STD_LOGIC;
A4 : IN STD_LOGIC;
A5 : IN STD_LOGIC;
A6 : IN STD_LOGIC;
A7 : IN STD_LOGIC;
A8 : IN STD_LOGIC;
A9 : IN STD_LOGIC;
A10 : IN STD_LOGIC;
D7 : OUT STD_LOGIC;
D6 : OUT STD_LOGIC;
D5 : OUT STD_LOGIC;
D4 : OUT STD_LOGIC;
D3 : OUT STD_LOGIC;
D2 : OUT STD_LOGIC;
D1 : OUT STD_LOGIC;
D0 : OUT STD_LOGIC;
CLK : IN STD_LOGIC := '1';
CS : IN STD_LOGIC := '1'
-- address : IN STD_LOGIC_VECTOR (10 DOWNTO 0);
-- clock : IN STD_LOGIC := '1';
-- q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0)
);
END ROM;
ARCHITECTURE SYN OF rom IS
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (7 DOWNTO 0);
COMPONENT altsyncram
GENERIC (
address_aclr_a : STRING;
clock_enable_input_a : STRING;
clock_enable_output_a : STRING;
init_file : STRING;
intended_device_family : STRING;
lpm_hint : STRING;
lpm_type : STRING;
numwords_a : NATURAL;
operation_mode : STRING;
outdata_aclr_a : STRING;
outdata_reg_a : STRING;
widthad_a : NATURAL;
width_a : NATURAL;
width_byteena_a : NATURAL
);
PORT (
address_a : IN STD_LOGIC_VECTOR (10 DOWNTO 0);
clock0 : IN STD_LOGIC ;
q_a : OUT STD_LOGIC_VECTOR (7 DOWNTO 0)
);
END COMPONENT;
BEGIN
-- q <= sub_wire0(7 DOWNTO 0);
(D7,D6,D5,D4,D3,D2,D1,D0) <= sub_wire0(7 DOWNTO 0) when (CS <= '0') else std_logic_vector'("ZZZZZZZZ");
altsyncram_component : altsyncram
GENERIC MAP (
address_aclr_a => "NONE",
clock_enable_input_a => "BYPASS",
clock_enable_output_a => "BYPASS",
init_file => "ROM.mif",
intended_device_family => "Cyclone IV E",
lpm_hint => "ENABLE_RUNTIME_MOD=NO",
lpm_type => "altsyncram",
numwords_a => 2048,
operation_mode => "ROM",
outdata_aclr_a => "NONE",
outdata_reg_a => "CLOCK0",
widthad_a => 11,
width_a => 8,
width_byteena_a => 1
)
PORT MAP (
-- address_a => address,
address_a => (A10,A9,A8,A7,A6,A5,A4,A3,A2,A1,A0),
-- clock0 => clock,
clock0 => CLK,
q_a => sub_wire0
);
END SYN;
-- ============================================================
-- CNX file retrieval info
-- ============================================================
-- Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0"
-- Retrieval info: PRIVATE: AclrAddr NUMERIC "0"
-- Retrieval info: PRIVATE: AclrByte NUMERIC "0"
-- Retrieval info: PRIVATE: AclrOutput NUMERIC "0"
-- Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0"
-- Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8"
-- Retrieval info: PRIVATE: BlankMemory NUMERIC "0"
-- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0"
-- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0"
-- Retrieval info: PRIVATE: Clken NUMERIC "0"
-- Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0"
-- Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A"
-- Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0"
-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E"
-- Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0"
-- Retrieval info: PRIVATE: JTAG_ID STRING "NONE"
-- Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0"
-- Retrieval info: PRIVATE: MIFfilename STRING "ROM.mif"
-- Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "2048"
-- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
-- Retrieval info: PRIVATE: RegAddr NUMERIC "1"
-- Retrieval info: PRIVATE: RegOutput NUMERIC "1"
-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
-- Retrieval info: PRIVATE: SingleClock NUMERIC "1"
-- Retrieval info: PRIVATE: UseDQRAM NUMERIC "0"
-- Retrieval info: PRIVATE: WidthAddr NUMERIC "11"
-- Retrieval info: PRIVATE: WidthData NUMERIC "8"
-- Retrieval info: PRIVATE: rden NUMERIC "0"
-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
-- Retrieval info: CONSTANT: ADDRESS_ACLR_A STRING "NONE"
-- Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS"
-- Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS"
-- Retrieval info: CONSTANT: INIT_FILE STRING "ROM.mif"
-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E"
-- Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO"
-- Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram"
-- Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "2048"
-- Retrieval info: CONSTANT: OPERATION_MODE STRING "ROM"
-- Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE"
-- Retrieval info: CONSTANT: OUTDATA_REG_A STRING "CLOCK0"
-- Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "11"
-- Retrieval info: CONSTANT: WIDTH_A NUMERIC "8"
-- Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1"
-- Retrieval info: USED_PORT: address 0 0 11 0 INPUT NODEFVAL "address[10..0]"
-- Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock"
-- Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL "q[7..0]"
-- Retrieval info: CONNECT: @address_a 0 0 11 0 address 0 0 11 0
-- Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0
-- Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0
-- Retrieval info: GEN_FILE: TYPE_NORMAL ROM.vhd TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL ROM.inc FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL ROM.cmp TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL ROM.bsf TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL ROM_inst.vhd FALSE
-- Retrieval info: LIB_FILE: altera_mf
Upvotes: 1
Views: 3868
Reputation: 366
There are two options you can explore that I can think of.
The first would be to use the concatenation operator and intermediate internal signals.
Example 1:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY RAM IS
PORT(
D0 : INOUT STD_LOGIC; -- data to/from external pin on bi-dir 1 bit wire LSB
D1 : INOUT STD_LOGIC; -- data to/from external pin on bi-dir 1 bit wire
D2 : INOUT STD_LOGIC; -- data to/from external pin on bi-dir 1 bit wire
D3 : INOUT STD_LOGIC; -- data to/from external pin on bi-dir 1 bit wire
D4 : INOUT STD_LOGIC; -- data to/from external pin on bi-dir 1 bit wire
D5 : INOUT STD_LOGIC; -- data to/from external pin on bi-dir 1 bit wire
D6 : INOUT STD_LOGIC; -- data to/from external pin on bi-dir 1 bit wire
D7 : INOUT STD_LOGIC; -- data to/from external pin on bi-dir 1 bit wire HSB
);
END ENTITY;
ARCHITECTURE BEV OF RAM IS
SIGNAL data_in_i :STD_LOGIC_VECTOR(7 downto 0);
SIGNAL data_out_i :STD_LOGIC_VECTOR(7 downto 0);
BEGIN
data_in_i <= D7 & D6 & D5 & D4 & D3 & D2 & D1 & D0;
...
D7 <= data_out_i(7);
D6 <= data_out_i(6);
D5 <= data_out_i(5);
D4 <= data_out_i(4);
D3 <= data_out_i(3);
D2 <= data_out_i(2);
D1 <= data_out_i(1);
D0 <= data_out_i(0);
...
END BEV;
Personally, I think this is a bit ugly and not as flexible. I'm not sure what your intentions are with splitting up the ports buses into individual bits, but I feel a better solution might be to leave the RAM entity as is and directly assign each bit of the STD_LOGIC_VECTOR inputs when instantiating it in your design.
Example 2:
ram_i: ENTITY work.RAM
PORT MAP(
D(0) => data0,
D(1) => data1,
D(2) => data2,
D(3) => data3,
D(4) => data4,
D(5) => data5,
D(6) => data6,
D(7) => data7
);
Upvotes: 2
Reputation:
You can use aggregates:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity ram is
port(
d0: inout std_logic;
d1: inout std_logic;
d2: inout std_logic;
d3: inout std_logic;
d4: inout std_logic;
d5: inout std_logic;
d6: inout std_logic;
d7: inout std_logic;
a0: in std_logic;
a1: in std_logic;
a2: in std_logic;
a3: in std_logic;
a4: in std_logic;
a5: in std_logic;
a6: in std_logic;
a8: in std_logic;
a7: in std_logic;
a9: in std_logic;
rw: in std_logic;
cs: in std_logic
);
end entity;
architecture foo of ram is
type mem is array (1023 downto 0) of std_logic_vector(7 downto 0);
signal memory : mem;
signal address : integer range 0 to 1023;
begin
process(a9,a8,a7,a6,a5,a4,a3,a2,a1,a0,d7,d6,d5,d4,d3,d2,d1,d0,rw,cs)
begin
address <= to_integer(unsigned'(a9,a8,a7,a6,a5,a4,a3,a2,a1,a0));
if cs = '0' then
if rw = '0' then
memory(address) <= (d7 & d6 & d5 & d4 & d3 & d2 & d1 & d0);
else
(d7,d6,d5,d4,d3,d2,d1,d0) <= std_logic_vector'(memory(address));
end if;
else
(d7,d6,d5,d4,d3,d2,d1,d0) <= std_logic_vector'("ZZZZZZZZ");
end if;
end process;
end architecture;
library ieee;
use ieee.std_logic_1164.all;
entity ramtest_tb is
end entity;
architecture foo of ramtest_tb is
signal a0,a1,a2,a3,a4,a5,a6,a7,a8,a9: std_logic := '0';
signal d0,d1,d2,d3,d4,d5,d6,d7: std_logic := 'Z';
signal rw: std_logic := '1';
signal cs: std_logic := '1';
begin
DUT:
entity work.ram
port map (
d0 => d0,
d1 => d1,
d2 => d2,
d3 => d3,
d4 => d4,
d5 => d5,
d6 => d6,
d7 => d7,
a0 => a0,
a1 => a1,
a2 => a2,
a3 => a3,
a4 => a4,
a5 => a5,
a6 => a6,
a7 => a7,
a8 => a8,
a9 => a9,
rw => rw,
cs => cs
);
TEST:
process
begin
wait for 10 ns;
rw <= '0';
a5 <= '1'; a3 <= '1'; a1 <= '1'; --42
wait for 10 ns;
cs <= '0';
(d7,d6,d5,d4,d3,d2,d1,d0) <= std_logic_vector'("10101010");
wait for 10 ns;
cs <= '1';
(d7,d6,d5,d4,d3,d2,d1,d0) <= std_logic_vector'("ZZZZZZZZ");
wait for 10 ns;
rw <= '1';
wait for 10 ns;
cs <= '0';
wait for 10 ns;
cs <= '1';
wait for 10 ns;
wait;
end process;
end architecture;
Which gives you:
A working RAM.
Upvotes: 2