Merge nyus:/storage/git/firearm
[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] base,
9         input [31:0] offset,
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
41         reg notdone = 1'b0;
42         reg inc_next = 1'b0;
43         assign outstall = rw_wait | notdone;
44
45         always @(*)
46         begin
47                 addr = 32'hxxxxxxxx;
48                 raddr = 32'hxxxxxxxx;
49                 rd_req = 1'b0;
50                 wr_req = 1'b0;
51                 wr_data = 32'hxxxxxxxx;
52                 busaddr = 32'hxxxxxxxx;
53                 outstall = 1'b0;
54                 next_notdone = 1'b0;
55                 next_regsel = 4'hx;
56                 next_regdata = 32'hxxxxxxxx;
57                 next_inc_next = 1'b0;
58                 casez(insn)
59                 `DECODE_LDRSTR_UNDEFINED: begin end
60                 `DECODE_LDRSTR: begin
61                         addr = insn[23] ? base + offset : base - offset; /* up/down select */
62                         raddr = insn[24] ? base : addr;
63                         busaddr = {raddr[31:2], 2'b0}; /* pre/post increment */
64                         rd_req = insn[20];
65                         wr_req = ~insn[20];
66
67                         /* rotate to correct position */
68                         align_s1 = raddr[1] ? {rd_data[15:0], rd_data[31:16]} : rd_data;
69                         align_s2 = raddr[0] ? {align_s1[7:0], align_s1[31:8]} : align_s1;
70                         /* select byte or word */
71                         align_rddata = insn[22] ? {24'b0, align_s2[7:0]} : align_s2;
72
73                         if(!insn[20]) begin
74                                 st_read = insn[15:12];
75                                 wr_data = insn[22] ? {4{st_data[7:0]}} : st_data; /* XXX need to actually store just a byte */
76                         end
77                         else if(!inc_next) begin
78                                 next_writeback = 1'b1;
79                                 next_regsel = insn[15:12];
80                                 next_regdata = align_rddata;
81                                 next_inc_next = 1'b1;
82                         end
83                         else if(insn[21]) begin
84                                 next_writeback = 1'b1;
85                                 next_regsel = insn[19:16];
86                                 next_regdata = addr;
87                         end
88                         next_notdone = rw_wait & insn[20] & insn[21];
89                 end
90                 `DECODE_LDMSTM: begin
91                 end
92                 default: begin end
93                 endcase
94         end
95
96
97         always @(posedge clk)
98         begin
99                 outpc <= pc;
100                 outbubble <= rw_wait;
101                 writeback <= next_writeback;
102                 regsel <= next_regsel;
103                 regdata <= next_regdata;
104                 notdone <= next_notdone;
105                 inc_next <= next_inc_next;
106         end
107
108 endmodule
This page took 0.0254 seconds and 4 git commands to generate.