]> rtime.felk.cvut.cz Git - fpga/plasma.git/blob - vhdl/mem_ctrl.vhd
Local copy of Plasma MIPS project.
[fpga/plasma.git] / vhdl / mem_ctrl.vhd
1 ---------------------------------------------------------------------
2 -- TITLE: Memory Controller
3 -- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4 -- DATE CREATED: 1/31/01
5 -- FILENAME: mem_ctrl.vhd
6 -- PROJECT: Plasma CPU core
7 -- COPYRIGHT: Software placed into the public domain by the author.
8 --    Software 'as is' without warranty.  Author liable for nothing.
9 -- DESCRIPTION:
10 --    Memory controller for the Plasma CPU.
11 --    Supports Big or Little Endian mode.
12 ---------------------------------------------------------------------
13 library ieee;
14 use ieee.std_logic_1164.all;
15 use work.mlite_pack.all;
16
17 entity mem_ctrl is
18    port(clk          : in std_logic;
19         reset_in     : in std_logic;
20         pause_in     : in std_logic;
21         nullify_op   : in std_logic;
22         address_pc   : in std_logic_vector(31 downto 2);
23         opcode_out   : out std_logic_vector(31 downto 0);
24
25         address_in   : in std_logic_vector(31 downto 0);
26         mem_source   : in mem_source_type;
27         data_write   : in std_logic_vector(31 downto 0);
28         data_read    : out std_logic_vector(31 downto 0);
29         pause_out    : out std_logic;
30         
31         address_next : out std_logic_vector(31 downto 2);
32         byte_we_next : out std_logic_vector(3 downto 0);
33
34         address      : out std_logic_vector(31 downto 2);
35         byte_we      : out std_logic_vector(3 downto 0);
36         data_w       : out std_logic_vector(31 downto 0);
37         data_r       : in std_logic_vector(31 downto 0));
38 end; --entity mem_ctrl
39
40 architecture logic of mem_ctrl is
41    --"00" = big_endian; "11" = little_endian
42    constant ENDIAN_MODE   : std_logic_vector(1 downto 0) := "00";
43    signal opcode_reg      : std_logic_vector(31 downto 0);
44    signal next_opcode_reg : std_logic_vector(31 downto 0);
45    signal address_reg     : std_logic_vector(31 downto 2);
46    signal byte_we_reg     : std_logic_vector(3 downto 0);
47
48    signal mem_state_reg   : std_logic;
49    constant STATE_ADDR    : std_logic := '0';
50    constant STATE_ACCESS  : std_logic := '1';
51
52 begin
53
54 mem_proc: process(clk, reset_in, pause_in, nullify_op, 
55                   address_pc, address_in, mem_source, data_write, 
56                   data_r, opcode_reg, next_opcode_reg, mem_state_reg,
57                   address_reg, byte_we_reg)
58    variable address_var    : std_logic_vector(31 downto 2);
59    variable data_read_var  : std_logic_vector(31 downto 0);
60    variable data_write_var : std_logic_vector(31 downto 0);
61    variable opcode_next    : std_logic_vector(31 downto 0);
62    variable byte_we_var    : std_logic_vector(3 downto 0);
63    variable mem_state_next : std_logic;
64    variable pause_var      : std_logic;
65    variable bits           : std_logic_vector(1 downto 0);
66 begin
67    byte_we_var := "0000";
68    pause_var := '0';
69    data_read_var := ZERO;
70    data_write_var := ZERO;
71    mem_state_next := mem_state_reg;
72    opcode_next := opcode_reg;
73
74    case mem_source is
75    when MEM_READ32 =>
76       data_read_var := data_r;
77
78    when MEM_READ16 | MEM_READ16S =>
79       if address_in(1) = ENDIAN_MODE(1) then
80          data_read_var(15 downto 0) := data_r(31 downto 16);
81       else
82          data_read_var(15 downto 0) := data_r(15 downto 0);
83       end if;
84       if mem_source = MEM_READ16 or data_read_var(15) = '0' then
85          data_read_var(31 downto 16) := ZERO(31 downto 16);
86       else
87          data_read_var(31 downto 16) := ONES(31 downto 16);
88       end if;
89
90    when MEM_READ8 | MEM_READ8S =>
91       bits := address_in(1 downto 0) xor ENDIAN_MODE;
92       case bits is
93       when "00" => data_read_var(7 downto 0) := data_r(31 downto 24);
94       when "01" => data_read_var(7 downto 0) := data_r(23 downto 16);
95       when "10" => data_read_var(7 downto 0) := data_r(15 downto 8);
96       when others => data_read_var(7 downto 0) := data_r(7 downto 0);
97       end case;
98       if mem_source = MEM_READ8 or data_read_var(7) = '0' then
99          data_read_var(31 downto 8) := ZERO(31 downto 8);
100       else
101          data_read_var(31 downto 8) := ONES(31 downto 8);
102       end if;
103
104    when MEM_WRITE32 =>
105       data_write_var := data_write;
106       byte_we_var := "1111";
107
108    when MEM_WRITE16 =>
109       data_write_var := data_write(15 downto 0) & data_write(15 downto 0);
110       if address_in(1) = ENDIAN_MODE(1) then
111          byte_we_var := "1100";
112       else
113          byte_we_var := "0011";
114       end if;
115
116    when MEM_WRITE8 =>
117       data_write_var := data_write(7 downto 0) & data_write(7 downto 0) &
118                   data_write(7 downto 0) & data_write(7 downto 0);
119       bits := address_in(1 downto 0) xor ENDIAN_MODE;
120       case bits is
121       when "00" =>
122          byte_we_var := "1000"; 
123       when "01" => 
124          byte_we_var := "0100"; 
125       when "10" =>
126          byte_we_var := "0010"; 
127       when others =>
128          byte_we_var := "0001"; 
129       end case;
130
131    when others =>
132    end case;
133
134    if mem_source = MEM_FETCH then --opcode fetch
135       address_var := address_pc;
136       opcode_next := data_r;
137       mem_state_next := STATE_ADDR;
138    else
139       if mem_state_reg = STATE_ADDR then
140          if pause_in = '0' then
141             address_var := address_in(31 downto 2);
142             mem_state_next := STATE_ACCESS;
143             pause_var := '1';
144          else
145             address_var := address_pc;
146             byte_we_var := "0000";
147          end if;
148       else  --STATE_ACCESS
149          if pause_in = '0' then
150             address_var := address_pc;
151             opcode_next := next_opcode_reg;
152             mem_state_next := STATE_ADDR;
153             byte_we_var := "0000";
154          else
155             address_var := address_in(31 downto 2);
156             byte_we_var := "0000";
157          end if;
158       end if;
159    end if;
160
161    if nullify_op = '1' and pause_in = '0' then
162       opcode_next := ZERO;  --NOP after beql
163    end if;
164
165    if reset_in = '1' then
166       mem_state_reg <= STATE_ADDR;
167       opcode_reg <= ZERO;
168       next_opcode_reg <= ZERO;
169       address_reg <= ZERO(31 downto 2);
170       byte_we_reg <= "0000";
171    elsif rising_edge(clk) then
172       if pause_in = '0' then
173          address_reg <= address_var;
174          byte_we_reg <= byte_we_var;
175          mem_state_reg <= mem_state_next;
176          opcode_reg <= opcode_next;
177          if mem_state_reg = STATE_ADDR then
178             next_opcode_reg <= data_r;
179          end if;
180       end if;
181    end if;
182
183    opcode_out <= opcode_reg;
184    data_read <= data_read_var;
185    pause_out <= pause_var;
186
187    address_next <= address_var;
188    byte_we_next <= byte_we_var;
189
190    address <= address_reg;
191    byte_we <= byte_we_reg;
192    data_w <= data_write_var;
193
194 end process; --data_proc
195
196 end; --architecture logic