merge memory
[firearm.git] / Memory.v
1 `include "ARM_Constants.v"
2
3 module Memory(
4         input clk,
5         input Nrst,
6
7         /* bus interface */
8         output reg [31:0] busaddr,
9         output reg rd_req,
10         output reg wr_req,
11         input rw_wait,
12         output reg [31:0] wr_data,
13         input [31:0] rd_data,
14
15         /* regfile interface */
16         output reg [3:0] st_read,
17         input [31:0] st_data,
18         
19         /* stage inputs */
20         input inbubble,
21         input [31:0] pc,
22         input [31:0] insn,
23         input [31:0] op0,
24         input [31:0] op1,
25         input [31:0] op2,
26         input write_reg,
27         input [3:0] write_num,
28         input [31:0] write_data,
29
30         /* outputs */
31         output reg outstall,
32         output reg outbubble,
33         output reg [31:0] outpc,
34         output reg [31:0] outinsn,
35         output reg out_write_reg = 1'b0,
36         output reg [3:0] out_write_num = 4'bxxxx,
37         output reg [31:0] out_write_data = 32'hxxxxxxxx
38         );
39
40         reg [31:0] addr, raddr, next_regdata;
41         reg [3:0] next_regsel, cur_reg, prev_reg;
42         reg next_writeback, next_notdone, next_inc_next;
43         reg [31:0] align_s1, align_s2, align_rddata;
44
45         wire next_outbubble;    
46         wire next_write_reg;
47         wire [3:0] next_write_num;
48         wire [31:0] next_write_data;
49
50         reg [15:0] regs, next_regs;
51         reg started = 1'b0, next_started;
52
53         reg notdone = 1'b0;
54         reg inc_next = 1'b0;
55
56         always @(posedge clk)
57         begin
58                 outpc <= pc;
59                 outinsn <= insn;
60                 outbubble <= next_outbubble;
61                 out_write_reg <= next_write_reg;
62                 out_write_num <= next_write_num;
63                 out_write_data <= next_write_data;
64                 notdone <= next_notdone;
65                 inc_next <= next_inc_next;
66                 regs <= next_regs;
67                 prev_reg <= cur_reg;
68                 started <= next_started;
69         end
70
71         always @(*)
72         begin
73                 addr = 32'hxxxxxxxx;
74                 raddr = 32'hxxxxxxxx;
75                 rd_req = 1'b0;
76                 wr_req = 1'b0;
77                 wr_data = 32'hxxxxxxxx;
78                 busaddr = 32'hxxxxxxxx;
79                 outstall = 1'b0;
80                 next_notdone = 1'b0;
81                 next_write_reg = write_reg;
82                 next_write_num = write_num;
83                 next_write_data = write_data;
84                 next_inc_next = 1'b0;
85                 next_outbubble = inbubble;
86                 outstall = 1'b0;
87                 next_regs = 16'b0;
88                 next_started = started;
89
90                 casez(insn)
91                 `DECODE_LDRSTR_UNDEFINED: begin end
92                 `DECODE_LDRSTR: begin
93                         if (!inbubble) begin
94                                 next_outbubble = rw_wait;
95                                 outstall = rw_wait | notdone;
96                         
97                                 addr = insn[23] ? op0 + op1 : op0 - op1; /* up/down select */
98                                 raddr = insn[24] ? op0 : addr; /* pre/post increment */
99                                 busaddr = {raddr[31:2], 2'b0};
100                                 rd_req = insn[20];
101                                 wr_req = ~insn[20];
102                                 
103                                 /* rotate to correct position */
104                                 align_s1 = raddr[1] ? {rd_data[15:0], rd_data[31:16]} : rd_data;
105                                 align_s2 = raddr[0] ? {align_s1[7:0], align_s1[31:8]} : align_s1;
106                                 /* select byte or word */
107                                 align_rddata = insn[22] ? {24'b0, align_s2[7:0]} : align_s2;
108                                 
109                                 if(!insn[20]) begin
110                                         wr_data = insn[22] ? {4{op2[7:0]}} : op2; /* XXX need to actually store just a byte */
111                                 end
112                                 else if(!inc_next) begin
113                                         next_write_reg = 1'b1;
114                                         next_write_num = insn[15:12];
115                                         next_write_data = align_rddata;
116                                         next_inc_next = 1'b1;
117                                 end
118                                 else if(insn[21]) begin
119                                         next_write_reg = 1'b1;
120                                         next_write_num = insn[19:16];
121                                         next_write_data = addr;
122                                 end
123                                 next_notdone = rw_wait & insn[20] & insn[21];
124                         end
125                 end
126                 `DECODE_LDMSTM: begin
127                         rd_req = insn[20];
128                         wr_req = ~insn[20];
129                         if(!started) begin
130                                 next_regs = op1[15:0];
131                                 next_started = 1'b1;
132                         end
133                         else if(inc_next) begin
134                                 if(insn[21]) begin
135                                         next_write_reg = 1'b1;
136                                         next_write_num = insn[19:16];
137                                         next_write_data = op0;
138                                 end
139                                 next_started = 1'b0;
140                         end
141                         else if(rw_wait) begin
142                                 next_regs = regs;
143                                 cur_reg = prev_reg;
144                         end
145                         else begin
146                                 casez(regs)
147                                 16'b???????????????1: begin
148                                         cur_reg = 4'h0;
149                                         next_regs = regs & 16'b1111111111111110;
150                                 end
151                                 16'b??????????????10: begin
152                                         cur_reg = 4'h1;
153                                         next_regs = regs & 16'b1111111111111100;
154                                 end
155                                 16'b?????????????100: begin
156                                         cur_reg = 4'h2;
157                                         next_regs = regs & 16'b1111111111111000;
158                                 end
159                                 16'b????????????1000: begin
160                                         cur_reg = 4'h3;
161                                         next_regs = regs & 16'b1111111111110000;
162                                 end
163                                 16'b???????????10000: begin
164                                         cur_reg = 4'h4;
165                                         next_regs = regs & 16'b1111111111100000;
166                                 end
167                                 16'b??????????100000: begin
168                                         cur_reg = 4'h5;
169                                         next_regs = regs & 16'b1111111111000000;
170                                 end
171                                 16'b?????????1000000: begin
172                                         cur_reg = 4'h6;
173                                         next_regs = regs & 16'b1111111110000000;
174                                 end
175                                 16'b????????10000000: begin
176                                         cur_reg = 4'h7;
177                                         next_regs = regs & 16'b1111111100000000;
178                                 end
179                                 16'b???????100000000: begin
180                                         cur_reg = 4'h8;
181                                         next_regs = regs & 16'b1111111000000000;
182                                 end
183                                 16'b??????1000000000: begin
184                                         cur_reg = 4'h9;
185                                         next_regs = regs & 16'b1111110000000000;
186                                 end
187                                 16'b?????10000000000: begin
188                                         cur_reg = 4'hA;
189                                         next_regs = regs & 16'b1111100000000000;
190                                 end
191                                 16'b????100000000000: begin
192                                         cur_reg = 4'hB;
193                                         next_regs = regs & 16'b1111000000000000;
194                                 end
195                                 16'b???1000000000000: begin
196                                         cur_reg = 4'hC;
197                                         next_regs = regs & 16'b1110000000000000;
198                                 end
199                                 16'b??10000000000000: begin
200                                         cur_reg = 4'hD;
201                                         next_regs = regs & 16'b1100000000000000;
202                                 end
203                                 16'b?100000000000000: begin
204                                         cur_reg = 4'hE;
205                                         next_regs = regs & 16'b1000000000000000;
206                                 end
207                                 16'b1000000000000000: begin
208                                         cur_reg = 4'hF;
209                                         next_regs = 16'b0;
210                                 end
211                                 default: begin
212                                         cur_reg = 4'hx;
213                                         next_regs = 16'b0;
214                                 end
215                                 endcase
216                                 next_inc_next = next_regs == 16'b0;
217                                 next_notdone = ~next_inc_next | (rw_wait & insn[20] & insn[21]);
218                         end
219                 end
220                 default: begin end
221                 endcase
222         end
223 endmodule
This page took 0.029152 seconds and 4 git commands to generate.