memory: add some stuff in ldm/stm
[firearm.git] / Memory.v
1 `include "ARM_Constants.v"
2
3 module Memory(
4         input clk,
5         input Nrst,
6         input [31:0] pc,
7         input [31:0] insn,
8         input [31:0] op0,
9         input [31:0] op1,
10
11         /* bus interface */
12         output reg [31:0] busaddr,
13         output reg rd_req,
14         output reg wr_req,
15         input rw_wait,
16         output reg [31:0] wr_data,
17         input [31:0] rd_data,
18
19         /* regfile interface */
20         output reg [3:0] st_read,
21         input [31:0] st_data,
22
23         /* writeback to base */
24         output reg writeback,
25         output reg [3:0] regsel,
26         output reg [31:0] regdata,
27
28         /* pc stuff */
29         output reg [31:0] outpc,
30
31         /* stall */
32         output outstall,
33         output reg outbubble
34 );
35
36         reg [31:0] addr, raddr, next_regdata;
37         reg [3:0] next_regsel;
38         reg next_writeback, next_notdone, next_inc_next;
39         reg [31:0] align_s1, align_s2, align_rddata;
40         reg [15:0] regs, next_regs;
41
42         reg notdone = 1'b0;
43         reg inc_next = 1'b0;
44         assign outstall = rw_wait | notdone;
45
46         always @(*)
47         begin
48                 addr = 32'hxxxxxxxx;
49                 raddr = 32'hxxxxxxxx;
50                 rd_req = 1'b0;
51                 wr_req = 1'b0;
52                 wr_data = 32'hxxxxxxxx;
53                 busaddr = 32'hxxxxxxxx;
54                 outstall = 1'b0;
55                 next_notdone = 1'b0;
56                 next_regsel = 4'hx;
57                 next_regdata = 32'hxxxxxxxx;
58                 next_inc_next = 1'b0;
59                 casez(insn)
60                 `DECODE_LDRSTR_UNDEFINED: begin end
61                 `DECODE_LDRSTR: begin
62                         addr = insn[23] ? op0 + op1 : op0 - op1; /* up/down select */
63                         raddr = insn[24] ? op0 : addr;
64                         busaddr = {raddr[31:2], 2'b0}; /* pre/post increment */
65                         rd_req = insn[20];
66                         wr_req = ~insn[20];
67
68                         /* rotate to correct position */
69                         align_s1 = raddr[1] ? {rd_data[15:0], rd_data[31:16]} : rd_data;
70                         align_s2 = raddr[0] ? {align_s1[7:0], align_s1[31:8]} : align_s1;
71                         /* select byte or word */
72                         align_rddata = insn[22] ? {24'b0, align_s2[7:0]} : align_s2;
73
74                         if(!insn[20]) begin
75                                 st_read = insn[15:12];
76                                 wr_data = insn[22] ? {4{st_data[7:0]}} : st_data; /* XXX need to actually store just a byte */
77                         end
78                         else if(!inc_next) begin
79                                 next_writeback = 1'b1;
80                                 next_regsel = insn[15:12];
81                                 next_regdata = align_rddata;
82                                 next_inc_next = 1'b1;
83                         end
84                         else if(insn[21]) begin
85                                 next_writeback = 1'b1;
86                                 next_regsel = insn[19:16];
87                                 next_regdata = addr;
88                         end
89                         next_notdone = rw_wait & insn[20] & insn[21];
90                 end
91                 `DECODE_LDMSTM: begin
92                         busaddr = {op0[31:2], 2'b0};
93                         rd_req = insn[20];
94                         wr_req = ~insn[20];
95                         casez(regs)
96                         16'b???????????????1: begin
97                                 next_regs = regs;
98                         end
99                         16'b??????????????10: begin
100                         end
101                         16'b?????????????100: begin
102                         end
103                         16'b????????????1000: begin
104                         end
105                         16'b???????????10000: begin
106                         end
107                         16'b??????????100000: begin
108                         end
109                         16'b?????????1000000: begin
110                         end
111                         16'b????????10000000: begin
112                         end
113                         16'b???????100000000: begin
114                         end
115                         16'b??????1000000000: begin
116                         end
117                         16'b?????10000000000: begin
118                         end
119                         16'b????100000000000: begin
120                         end
121                         16'b???1000000000000: begin
122                         end
123                         16'b??10000000000000: begin
124                         end
125                         16'b?100000000000000: begin
126                         end
127                         16'b1000000000000000: begin
128                         end
129                         default: begin
130                                 next_inc_next = 1'b1;
131                         end
132                         endcase
133                 end
134                 default: begin end
135                 endcase
136         end
137
138
139         always @(posedge clk)
140         begin
141                 outpc <= pc;
142                 outbubble <= rw_wait;
143                 writeback <= next_writeback;
144                 regsel <= next_regsel;
145                 regdata <= next_regdata;
146                 notdone <= next_notdone;
147                 inc_next <= next_inc_next;
148                 regs <= next_regs;
149         end
150
151 endmodule
This page took 0.026165 seconds and 4 git commands to generate.