blob: 4360b1ca20dd127725d5a0c580ee88f115ffd89a [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/** Compute
*
* Add-by-one procedure:
*
* 1. Wait for launch to be asserted
* 2. Issue a read request for 8-byte value at inp_baddr address
* 3. Wait for the value
* 4. Issue a write request for 8-byte value at out_baddr address
* 5. Increment read-address and write-address for next value
* 6. Check if counter (cnt) is equal to length to assert finish,
* otherwise go to step 2.
*/
module Compute #
(
parameter MEM_LEN_BITS = 8,
parameter MEM_ADDR_BITS = 64,
parameter MEM_DATA_BITS = 64,
parameter HOST_DATA_BITS = 32
)
(
input clock,
input reset,
output mem_req_valid,
output mem_req_opcode,
output [MEM_LEN_BITS-1:0] mem_req_len,
output [MEM_ADDR_BITS-1:0] mem_req_addr,
output mem_wr_valid,
output [MEM_DATA_BITS-1:0] mem_wr_bits,
input mem_rd_valid,
input [MEM_DATA_BITS-1:0] mem_rd_bits,
output mem_rd_ready,
input launch,
output finish,
output event_counter_valid,
output [HOST_DATA_BITS-1:0] event_counter_value,
input [HOST_DATA_BITS-1:0] constant,
input [HOST_DATA_BITS-1:0] length,
input [MEM_ADDR_BITS-1:0] inp_baddr,
input [MEM_ADDR_BITS-1:0] out_baddr
);
typedef enum logic [2:0] {IDLE,
READ_REQ,
READ_DATA,
WRITE_REQ,
WRITE_DATA} state_t;
state_t state_n, state_r;
logic [31:0] cnt;
logic [MEM_DATA_BITS-1:0] data;
logic [MEM_ADDR_BITS-1:0] raddr;
logic [MEM_ADDR_BITS-1:0] waddr;
always_ff @(posedge clock) begin
if (reset) begin
state_r <= IDLE;
end else begin
state_r <= state_n;
end
end
always_comb begin
state_n = IDLE;
case (state_r)
IDLE: begin
if (launch) begin
state_n = READ_REQ;
end
end
READ_REQ: begin
state_n = READ_DATA;
end
READ_DATA: begin
if (mem_rd_valid) begin
state_n = WRITE_REQ;
end else begin
state_n = READ_DATA;
end
end
WRITE_REQ: begin
state_n = WRITE_DATA;
end
WRITE_DATA: begin
if (cnt == (length - 1'b1)) begin
state_n = IDLE;
end else begin
state_n = READ_REQ;
end
end
default: begin
end
endcase
end
logic last;
assign last = (state_r == WRITE_DATA) & (cnt == (length - 1'b1));
// cycle counter
logic [HOST_DATA_BITS-1:0] cycle_counter;
always_ff @(posedge clock) begin
if (reset | state_r == IDLE) begin
cycle_counter <= '0;
end else begin
cycle_counter <= cycle_counter + 1'b1;
end
end
assign event_counter_valid = last;
assign event_counter_value = cycle_counter;
// calculate next address
always_ff @(posedge clock) begin
if (reset | state_r == IDLE) begin
raddr <= inp_baddr;
waddr <= out_baddr;
end else if (state_r == WRITE_DATA) begin
raddr <= raddr + 'd8;
waddr <= waddr + 'd8;
end
end
// create request
assign mem_req_valid = (state_r == READ_REQ) | (state_r == WRITE_REQ);
assign mem_req_opcode = state_r == WRITE_REQ;
assign mem_req_len = 'd0; // one-word-per-request
assign mem_req_addr = (state_r == READ_REQ)? raddr : waddr;
// read
always_ff @(posedge clock) begin
if ((state_r == READ_DATA) & mem_rd_valid) begin
data <= mem_rd_bits + {32'd0, constant};
end
end
assign mem_rd_ready = state_r == READ_DATA;
// write
assign mem_wr_valid = state_r == WRITE_DATA;
assign mem_wr_bits = data;
// count read/write
always_ff @(posedge clock) begin
if (reset | state_r == IDLE) begin
cnt <= 'd0;
end else if (state_r == WRITE_DATA) begin
cnt <= cnt + 1'b1;
end
end
// done when read/write are equal to length
assign finish = last;
endmodule