Concept Flow - Dual-port RAM design
Start
Write Port
Write Data to RAM at Write Address
Read Port
Output Read Data
End
The design has two ports: one for writing data to RAM and one for reading data from RAM simultaneously.
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity dual_port_ram is port( clk : in std_logic; we : in std_logic; waddr : in unsigned(3 downto 0); din : in std_logic_vector(7 downto 0); raddr : in unsigned(3 downto 0); dout : out std_logic_vector(7 downto 0) ); end entity; architecture rtl of dual_port_ram is type ram_type is array (0 to 15) of std_logic_vector(7 downto 0); signal ram : ram_type := (others => (others => '0')); begin process(clk) begin if rising_edge(clk) then if we = '1' then ram(to_integer(waddr)) <= din; end if; dout <= ram(to_integer(raddr)); end if; end process; end rtl;
| Step | clk edge | we | waddr | din | raddr | Action | RAM State at waddr | dout Output |
|---|---|---|---|---|---|---|---|---|
| 1 | rising | 0 | 0001 | 00000001 | 0000 | No write, read from addr 0 | 00000000 | 00000000 |
| 2 | rising | 1 | 0010 | 00000010 | 0001 | Write din to addr 2, read addr 1 | 00000010 | 00000000 |
| 3 | rising | 1 | 0001 | 00000101 | 0010 | Write din to addr 1, read addr 2 | 00000101 | 00000010 |
| 4 | rising | 0 | xxxx | xxxxxxxx | 0001 | No write, read addr 1 | 00000101 | 00000101 |
| 5 | rising | 1 | 0011 | 00001000 | 0011 | Write din to addr 3, read addr 3 (old data) | 00001000 | 00000000 |
| 6 | rising | 0 | xxxx | xxxxxxxx | 0010 | No write, read addr 2 | 00001000 | 00000010 |
| 7 | rising | 0 | xxxx | xxxxxxxx | 0100 | No write, read addr 4 | 00001000 | 00000000 |
| Exit | - | - | - | - | - | Simulation ends | - | - |
| Variable | Start | After 1 | After 2 | After 3 | After 4 | After 5 | After 6 | After 7 |
|---|---|---|---|---|---|---|---|---|
| we | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 0 |
| waddr | 0001 | 0001 | 0010 | 0001 | xxxx | 0011 | xxxx | xxxx |
| din | 00000001 | 00000001 | 00000010 | 00000101 | xxxxxxxx | 00001000 | xxxxxxxx | xxxxxxxx |
| raddr | 0000 | 0000 | 0001 | 0010 | 0001 | 0011 | 0010 | 0100 |
| dout | 00000000 | 00000000 | 00000000 | 00000010 | 00000101 | 00000000 | 00000010 | 00000000 |
| ram[1] | 00000000 | 00000000 | 00000000 | 00000101 | 00000101 | 00000101 | 00000101 | 00000101 |
| ram[2] | 00000000 | 00000000 | 00000010 | 00000010 | 00000010 | 00000010 | 00000010 | 00000010 |
| ram[3] | 00000000 | 00000000 | 00000000 | 00000000 | 00000000 | 00001000 | 00001000 | 00001000 |
Dual-port RAM in VHDL: - Two ports: one write (we, waddr, din), one read (raddr, dout) - On clock rising edge: * If we=1, write din to RAM[waddr] * Always read RAM[raddr] to dout - Allows simultaneous read and write - RAM size and data width defined by array and vector sizes
dual-port RAM in VHDL designs?data_b after the rising clock edge if we_a = '1' and addr_a = "0010" with data_a = "10101010"?
process(clk)
begin
if rising_edge(clk) then
if we_a = '1' then
ram(to_integer(unsigned(addr_a))) <= data_a;
end if;
data_b <= ram(to_integer(unsigned(addr_b)));
end if;
end process;process(clk)
begin
if rising_edge(clk) then
if we_a = '1' then
ram(to_integer(unsigned(addr_a))) <= data_a;
end if;
if we_b = '1' then
ram(to_integer(unsigned(addr_b))) <= data_b;
end if;
data_a <= ram(to_integer(unsigned(addr_a)));
data_b <= ram(to_integer(unsigned(addr_b)));
end if;
end process;Pass the test and this pattern moves unknown