alu_2.v 7.12 KB
Newer Older
Antoine Kaufmann's avatar
Antoine Kaufmann committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
`timescale 1ns / 1ps

module alu_2 #(
    parameter STAGE_ID = 0,
    parameter ACTION_LEN = 25,
    parameter DATA_WIDTH = 32,  //data width of the ALU
    parameter ACTION_ID = 3,

	parameter C_S_AXIS_DATA_WIDTH = 512,
	parameter C_S_AXIS_TUSER_WIDTH = 128
)
(
    input clk,
    input rst_n,

    //input from sub_action
    input [ACTION_LEN-1:0]            action_in,
    input                             action_valid,
    input [DATA_WIDTH-1:0]            operand_1_in,
    input [DATA_WIDTH-1:0]            operand_2_in,
    input [DATA_WIDTH-1:0]            operand_3_in,
	output reg 						  ready_out,

	input [15:0]						page_tbl_out,
	input								page_tbl_out_valid,

    //output to form PHV
    output [DATA_WIDTH-1:0]				container_out_w,
    output reg							container_out_valid,
	input								ready_in

);

reg  [3:0]           action_type, action_type_next;

//regs for RAM access
reg                         store_en, store_en_next;
reg  [4:0]                  store_addr, store_addr_next;
wire [31:0]					store_din_w;
reg  [31:0]                 store_din, store_din_next;

wire [31:0]                 load_data;
wire [4:0]					load_addr;
// reg [4:0]                  load_addr, load_addr_next;

reg  [2:0]                  alu_state, alu_state_next;
reg [DATA_WIDTH-1:0]		container_out, container_out_next;
reg							container_out_valid_next;

//regs/wires for isolation
wire [7:0]                  base_addr;
wire [7:0]                  addr_len;

assign {addr_len, base_addr} = page_tbl_out;

reg                         overflow, overflow_next;
reg 						ready_out_next;


/********intermediate variables declared here********/

//support tenant isolation
// assign load_addr = store_addr[4:0] + base_addr;
assign load_addr = operand_2_in[4:0] + base_addr;

assign store_din_w = (action_type==4'b1000)?store_din:
						((action_type==4'b0111)?(load_data+1):0);

assign container_out_w = (action_type==4'b1011)?load_data:
							(action_type==4'b0111)?(load_data+1):
							container_out;

/*
7 operations to support:

1,2. add/sub:   0001/0010
              extract 2 operands from pkt header, add(sub) and write back.

3,4. addi/subi: 1001/1010
              extract op1 from pkt header, op2 from action, add(sub) and write back.

5: load:      0101
              load data from RAM, write to pkt header according to addr in action.

6. store:     0110
              read data from pkt header, write to ram according to addr in action.

7. loadd:     0111
              load data from RAM, increment by 1 write it to container, and write it
              back to the RAM. 
8. set:		  1110
			  set to an immediate value
*/

localparam  IDLE_S = 3'd0,
            EMPTY1_S = 3'd1,
            OB_ADDR_S = 3'd2,
            EMPTY2_S = 3'd3,
            OUTPUT_S = 3'd4,
			HALT_S = 3'd5;

always @(*) begin
	alu_state_next = alu_state;

	action_type_next = action_type;
	container_out_next = container_out;

	store_addr_next = store_addr;
	store_din_next = store_din;
	store_en_next = 0;
	// load_addr_next = load_addr;
    overflow_next = overflow;

	container_out_valid_next = 0;

	ready_out_next = ready_out;
	
	case (alu_state)
		IDLE_S: begin
			
            if (action_valid) begin
				action_type_next = action_in[24:21];
                overflow_next = 0;
				alu_state_next = EMPTY1_S;
				ready_out_next = 1'b0;

                
                case(action_in[24:21])
                    //add/addi ops 
                    4'b0001, 4'b1001: begin
                        container_out_next = operand_1_in + operand_2_in;
                    end 
                    //sub/subi ops
                    4'b0010, 4'b1010: begin
                        container_out_next = operand_1_in - operand_2_in;
                    end
                    //store op (interact with RAM)
                    4'b1000: begin
                        container_out_next = operand_3_in;
                        //store_en_r = 1;
                        store_addr_next = operand_2_in[4:0];
                        store_din_next = operand_1_in;
                    end
                    // load op (interact with RAM)
                    4'b1011: begin
                        container_out_next = operand_3_in;
                    end
					// loadd op
                    4'b0111: begin
                        // do nothing now
                        //checkme
                        container_out_next = operand_3_in;
                        store_addr_next = operand_2_in[4:0];
                    end
					// set operation
					4'b1110: begin
						container_out_next = operand_2_in;
					end
                    //cannot go back to IDLE since this
                    //might be a legal action.
                    default: begin
                        container_out_next = operand_3_in;
                    end
				endcase

				//ok, if its `load` op, needs to check overflow.
            	if(action_in[24:21] == 4'b1011 || action_in[24:21] == 4'b0111 || action_in[24:21] == 4'b1000) begin
            	    if(operand_2_in[4:0] > addr_len) begin
            	        overflow_next = 1'b1;
            	    end
            	    else begin
            	        overflow_next = 1'b0;
            	        //its the right time to write for `store`
            	        if(action_in[24:21] == 4'b1000 || action_in[24:21] == 4'b0111) begin
            	            store_addr_next = base_addr + operand_2_in[4:0];
            	            //store_din_r = operand_1_in;
            	            //store_en_next = 1'b1;
            	        end
            	    end
            	end
				// 
				// load_addr_next = operand_2_in[4:0] + base_addr;
				alu_state_next = EMPTY2_S;
			end
		end
        EMPTY2_S: begin
            //wait for the result of RAM
			if (ready_in) begin
				alu_state_next = IDLE_S;
				container_out_valid_next = 1;
				ready_out_next = 1;

				// action_type
				if ((action_type==4'b1000 || action_type==4'b0111) &&
						overflow==0) begin
					store_en_next = 1'b1;
				end
			end
			else begin
				alu_state_next = HALT_S;
			end
        end
		HALT_S: begin
			if (ready_in) begin
				alu_state_next = IDLE_S;
				container_out_valid_next = 1;
				ready_out_next = 1;

				// action_type
				if ((action_type==4'b1000 || action_type==4'b0111) &&
						overflow==0) begin
					store_en_next = 1'b1;
				end
			end
		end
	endcase
end

always @(posedge clk) begin
	if (~rst_n) begin
		alu_state <= IDLE_S;

		action_type <= 0;
		container_out <= 0;
		container_out_valid <= 0;

		store_en <= 0;
		store_addr <= 0;
		store_din <= 0;
		// load_addr <= 0;

        overflow <= 0;

		ready_out <= 1'b1;

	end
	else begin
		alu_state <= alu_state_next;
		action_type <= action_type_next;
		container_out <= container_out_next;
		container_out_valid <= container_out_valid_next;

		store_en <= store_en_next;
		store_addr <= store_addr_next;
		store_din <= store_din_next;
		// load_addr <= load_addr_next;

        overflow <= overflow_next;

		ready_out <= ready_out_next;

	end
end



blk_mem_gen_0
data_ram_32w_32d
(
    //store-related
    .addra(store_addr),
    .clka(clk),
    .dina(store_din_w),
    .ena(1'b1),
    .wea(store_en),

    //load-related
    .addrb(load_addr),
    .clkb(clk),
    .doutb(load_data),
    .enb(1'b1)
);


endmodule