| 1 |
13 |
Agner |
//////////////////////////////////////////////////////////////////////////////////
|
| 2 |
|
|
// Engineer: Agner Fog
|
| 3 |
|
|
//
|
| 4 |
|
|
// Create Date: 2020-05-05
|
| 5 |
|
|
// Last modified: 2021-07-27
|
| 6 |
|
|
// Module Name: call_stack
|
| 7 |
|
|
// Project Name: ForwardCom soft core
|
| 8 |
|
|
// Target Devices: Artix 7
|
| 9 |
|
|
// Tool Versions: Vivado v. 2020.1
|
| 10 |
|
|
// License: CERN-OHL-W v. 2 or later
|
| 11 |
|
|
// Description: on-chip call stack. controls call and return instructions
|
| 12 |
|
|
//
|
| 13 |
|
|
//////////////////////////////////////////////////////////////////////////////////
|
| 14 |
|
|
`include "defines.vh"
|
| 15 |
|
|
|
| 16 |
|
|
// call stack, 1024*32 bits, used for function return addresses but not for parameters or local data
|
| 17 |
|
|
// On call instruction: put return address on push_data and set call_e high for one clock cycle.
|
| 18 |
|
|
// On return instruction: the return address is pre-loaded into pop_data for early read.
|
| 19 |
|
|
// Set return_e high for one clock cycle to make next return address ready.
|
| 20 |
|
|
|
| 21 |
|
|
// It is not allowed to have call_e and return_e in the same clock cycle.
|
| 22 |
|
|
// It is not allowed to have return_e in the first clock cycle after call_e
|
| 23 |
|
|
// or return_e. This is not a problem in the current design because consecutive
|
| 24 |
|
|
// jump, call, and return instructions are delayed by the access time to the code cache.
|
| 25 |
|
|
// If the design is improved with more efficient branch prediction then it may be
|
| 26 |
|
|
// necessary to add precautions to prevent a return_e signal in the first clock cycle
|
| 27 |
|
|
// after another return_e or call_e.
|
| 28 |
|
|
|
| 29 |
|
|
module call_stack (
|
| 30 |
|
|
input clock, // clock
|
| 31 |
|
|
input clock_enable, // clock enable. Used when single-stepping
|
| 32 |
|
|
input reset, // clock enable. Used when single-stepping
|
| 33 |
|
|
input call_e, // Executing call instruction. push_data contains return address
|
| 34 |
|
|
input return_e, // Executing return instruction. return address is available in advance on pop_data
|
| 35 |
|
|
input [`CODE_ADDR_WIDTH-1:0] push_data, // Return address pushed here at call instruction
|
| 36 |
|
|
output reg [`CODE_ADDR_WIDTH-1:0] pop_data, // Return address popped here at return instruction
|
| 37 |
|
|
output reg overflow // stack overflow or underflow or error
|
| 38 |
|
|
);
|
| 39 |
|
|
|
| 40 |
|
|
// site of stack = 2**stack_pointer_bits
|
| 41 |
|
|
parameter integer stack_pointer_bits = `CALL_STACK_POINTER_BITS;
|
| 42 |
|
|
|
| 43 |
|
|
// stack ram, on-chip
|
| 44 |
|
|
reg [`CODE_ADDR_WIDTH-1:0] ram[0:(2**stack_pointer_bits)-1];
|
| 45 |
|
|
|
| 46 |
|
|
// call stack pointer
|
| 47 |
|
|
reg [stack_pointer_bits-1:0] call_stack_pointer = 0;
|
| 48 |
|
|
|
| 49 |
|
|
// call and return operations = push and pop of function return addresses:
|
| 50 |
|
|
always_ff @(posedge clock) if (clock_enable) begin
|
| 51 |
|
|
overflow <= 0;
|
| 52 |
|
|
if (reset) begin
|
| 53 |
|
|
call_stack_pointer <= 0;
|
| 54 |
|
|
pop_data <= 0;
|
| 55 |
|
|
overflow <= 0;
|
| 56 |
|
|
|
| 57 |
|
|
end else if (call_e) begin
|
| 58 |
|
|
if (call_stack_pointer == (2**stack_pointer_bits)-1 || return_e) begin
|
| 59 |
|
|
overflow <= 1; // overflow or other error
|
| 60 |
|
|
end else begin
|
| 61 |
|
|
ram[call_stack_pointer] <= push_data; // push return address on stack
|
| 62 |
|
|
pop_data <= push_data; // make next return address ready
|
| 63 |
|
|
call_stack_pointer <= call_stack_pointer + 1;
|
| 64 |
|
|
end
|
| 65 |
|
|
|
| 66 |
|
|
end else if (return_e) begin
|
| 67 |
|
|
if (call_stack_pointer == 0) begin
|
| 68 |
|
|
overflow <= 1; // stack underflow
|
| 69 |
|
|
end else if (call_stack_pointer == 1) begin
|
| 70 |
|
|
pop_data <= 0; // stack empty
|
| 71 |
|
|
call_stack_pointer <= call_stack_pointer - 1;
|
| 72 |
|
|
end else begin
|
| 73 |
|
|
pop_data <= ram[call_stack_pointer-2]; // make next return address ready
|
| 74 |
|
|
call_stack_pointer <= call_stack_pointer - 1;
|
| 75 |
|
|
end
|
| 76 |
|
|
end
|
| 77 |
|
|
end
|
| 78 |
|
|
|
| 79 |
|
|
endmodule
|