URL
https://opencores.org/ocsvn/forwardcom/forwardcom/trunk
Subversion Repositories forwardcom
Compare Revisions
- This comparison shows the changes necessary to convert path
/forwardcom/trunk
- from Rev 9 to Rev 10
- ↔ Reverse comparison
Rev 9 → Rev 10
/top.sv
0,0 → 1,1046
/****************************************************************************** |
* Engineer: Agner Fog |
* |
* Create date: 2020-05-03 |
* Last modified: 2021-08-05 |
* Module name: top |
* Project name: ForwardCom soft core |
* Tool versions: Vivado 2020.1 |
* License: CERN-OHL-W version 2 or later |
* Description: Top level module of ForwardCom softcore |
* |
* The pipeline stages are connected here: |
* 1. fetch: Fetch code words from code memory |
* 2. decoder Decode instruction code |
* 3. register_read Read registers. The register file is included in this stage |
* 4. addressgenerator Calculate address of any memory operand |
* 5. dataread Wait for data being read from data RAM |
* 6a. alu Execute the instruction and calculate the result |
* 6b. in_out_ports Input and output instructions etc. go here instead of into alu |
* |
* Other modules connected here: |
* clock_generator: Controls the clock frequency of the global clock |
* code_memory: Code memory or cache |
* data_memory: Data memory or cache |
* call_stack: Call stack for function return addresses |
* debug_display: Shows contents of each pipeline stage on LCD display |
* debugger.vh: Displays values of any signals anywhere in system on LED displays |
* |
******************************************************************************/ |
`include "defines.vh" |
|
/* |
Signals have name prefixes indicating the modules that generate them. |
Handshaking signals between pipeline stages: |
valid_in: Preceding stage has valid data ready |
valid_out: Valid data are ready for next stage |
stall_in: Keep your data for the next clock cycle |
stall_out: Unable to receive new data |
stall_predict_out: Predict that the next stage in pipeline will stall in next clock cycle |
There is currently no contention for result buses, but future implementation may need handshaking for this: |
result_bus_require_out: Needs result bus in next clock cycle |
result_bus_acknowledge_in: No unit with higher privilege is taking the result bus |
result_bus_enable_out: A result is on the result bus |
*/ |
|
module top ( |
input clock100, // board input clock 100 MHz |
input switch0, // switches for debug modes |
input switch1, // switches for debug modes |
input switch2, // switches for debug modes |
input switch3, // switches for debug modes |
input switch4, // switches for debug modes |
input switch5, // switches for debug modes |
input switch6, // switches for debug modes |
input switch7, // switches for debug modes |
input switch8, // switches for debug modes |
input switch15, // disables error stop |
|
input step_button, // Single stepping (RIGHT BUTTON) |
input run_button, // Stop single stepping and start free running (UP BUTTON) |
input reset_button, // Reset to start of program (DOWN BUTTON) |
input load_button, // Load program throung serial interfase (!CPU RESET BUTTON) |
|
input step_button_x, // Single stepping (external button) |
input run_button_x, // Stop single stepping and start free running (external button) |
input reset_button_x, // Reset to start of program (external button) |
input load_button_x, // Loader (external button) |
input external_connected_x, // high if external debug interface is connected |
|
input debug1_switch, // enable single-stepping, pipeline mode |
input debug2_switch, // enable single-stepping, instruction mode |
input uart_txd_in, // UART transmit from PC |
input uart_rts_in, // UART RTS from PC |
output reg [7:0] segment7seg, // segment output, active low |
output reg [7:0] digit7seg, // digit select output, active low |
output reg [3:0] lcd_data, // data to LCD display |
output reg lcd_rs, // control signal for LCD display |
output reg [1:0] lcd_e, // enable signals for LCD displays |
output uart_rxd_out, // UART receive to PC |
output uart_cts_out, // UART CTS to PC |
output led0, // use of led's: see below |
output led1, |
output led2, |
output led3, |
output led4, |
output led5, |
output led6, |
output led7, |
output led12, |
output led13, |
output led14, |
output led15, |
output led16R, // RGB led |
output led16G, |
output led16B |
); |
|
|
// generate clock (Xilinx specific. Generated by Clocking Wizard) |
clock_generator clock_generator_inst ( |
.clk_in(clock100), // board input clock, 100 MHz |
.clk_out(clock), // synthesized clock, frequency is `CLOCK_FREQUENCY |
.locked() // clock frequency has stabilized |
); |
|
// control single stepping |
reg single_step_mode; |
reg step_button_debounced; |
reg run_button_debounced; |
reg reset_button_debounced; |
reg load_button_debounced; |
reg step_button_pulse; |
reg run_button_pulse; |
reg reset_button_pulse; |
reg load_button_pulse; |
|
reg [2:0] reset_step = 3'b111; // shift register for system reset clock cycles |
reg clock_enable = 0; |
reg system_reset = 1; // reset everything. load program |
reg program_restart = 0; // restart loaded program |
|
|
// pushbutton debouncers |
// on-board buttons are always enabled, external buttons are enabled by external_connected_x |
logic[3:0] input_buttons; |
logic[3:0] debounced_buttons; |
logic[3:0] button_pulse; |
|
assign input_buttons[0] = step_button | (step_button_x & external_connected_x); |
assign input_buttons[1] = run_button | (run_button_x & external_connected_x); |
assign input_buttons[2] = reset_button | (reset_button_x & external_connected_x); |
assign input_buttons[3] = (~load_button) | (load_button_x & external_connected_x); |
assign debounced_buttons[0] = step_button_debounced; |
assign debounced_buttons[1] = run_button_debounced; |
assign debounced_buttons[2] = reset_button_debounced; |
assign debounced_buttons[3] = load_button_debounced; |
assign button_pulse[0] = step_button_pulse; |
assign button_pulse[1] = run_button_pulse; |
assign button_pulse[2] = reset_button_pulse; |
assign button_pulse[3] = load_button_pulse; |
|
debounce #(.num(4) ) debounce_inst |
(.clock(clock), |
.buttons_in (input_buttons), |
.buttons_out(debounced_buttons), |
.pulse_out(button_pulse)); |
|
|
|
/*************************************************** |
Signals connecting the stages |
***************************************************/ |
|
// code memory |
logic [`CODE_DATA_WIDTH-1:0] code_memory_data; // Data out |
logic [31:0] code_memory_debug; |
|
// data memory |
logic [`RB1:0] data_memory_data; |
|
// call stack |
logic [`CODE_ADDR_WIDTH-1:0] call_stack_pop_data; // return address popped from call stack |
logic call_stack_overflow; // call stack overflow or underflow or error |
|
// register file input |
logic [5:0] debug_reada; // read port for debugger |
|
// signals from each pipeline stage |
|
// fetch stage |
logic fetch_valid; |
logic fetch_jump; // jump instruction bypassing pipeline |
logic fetch_call_e; // executing call instruction |
logic fetch_return_e; // executing return instruction |
logic [95:0] fetch_instruction; |
logic [`CODE_ADDR_WIDTH-1:0] fetch_instruction_pointer; // point to current instruction |
logic fetch_read_enable; |
logic [`CODE_ADDR_WIDTH-2:0] fetch_read_addr; // Address for reading from code ram |
logic [`CODE_ADDR_WIDTH-1:0] fetch_call_push_data; // return address pushed to call stack |
logic [31:0] fetch_debug1; // temporary debug output |
|
// decoder |
logic [`TAG_WIDTH-1:0] decoder_tag_val; // instruction tag value |
logic decoder_tag_write; // tag write enable |
logic decoder_read; // read register enable |
logic decoder_valid; // An instruction is ready for output to next stage |
logic [`CODE_ADDR_WIDTH-1:0] decoder_instruction_pointer; // address of current instruction |
logic [95:0] decoder_instruction; // first word of instruction |
logic decoder_stall; // Not ready to receive next instruction |
logic [5:0] decoder_tag_a; // register number for instruction tag |
logic decoder_vector; // this is a vector instruction |
logic [1:0] decoder_category; // 00: multiformat, 01: single format, 10: jump |
logic [1:0] decoder_format; // 00: format A, 01: format E, 10: format B, 11: format C (format D never goes through decoder) |
logic [2:0] decoder_rs_status; // use of RS |
logic [2:0] decoder_rt_status; // use of RT |
logic [1:0] decoder_ru_status; // 1: RU is used |
logic [1:0] decoder_rd_status; // 1: RD is used as input |
logic [1:0] decoder_mask_status; // what the mask register is used for |
logic decoder_mask_options; // 1: mask register may contain options |
logic decoder_mask_alternative; // mask register and fallback register used for alternative purposes |
logic [2:0] decoder_fallback_use; // 0: no fallback, 1: same as first source operand, 2-4: RU, RS, RT |
logic [1:0] decoder_num_operands; // number of source operands |
logic [1:0] decoder_result_type; // type of result: 0: register, 1: system register, 2: memory, 3: other or nothing |
logic [1:0] decoder_offset_field; // address offset. 0: none, 1: 8 bit, possibly scaled, 2: 16 bit, 3: 32 bit |
logic [1:0] decoder_immediate_field; // immediate data field. 0: none, 1: 8 bit, 2: 16 bit, 3: 32 or 64 bit |
logic [1:0] decoder_scale_factor; // 00: index is not scaled, 01: index is scaled by operand size, 10: index is scaled by -1 |
logic decoder_index_limit; // index has a limit |
logic [31:0] decoder_debug1; // temporary debug output |
|
// register read stage |
logic registerread_valid; // An instruction is ready for output to next stage |
logic [`CODE_ADDR_WIDTH-1:0] registerread_instruction_pointer; // address of current instruction |
logic [95:0] registerread_instruction; // first word of instruction |
logic registerread_stall_predict; // predict next stage will stall |
logic [`TAG_WIDTH-1:0] registerread_tag_val; // instruction tag value |
logic registerread_vector; // this is a vector instruction |
logic [1:0] registerread_category; // 00: multiformat, 01: single format, 10: jump |
logic [1:0] registerread_format; // 00: format A, 01: format E, 10: format B, 11: format C (format D never goes through decoder) |
logic [1:0] registerread_num_operands; // number of source operands |
logic [1:0] registerread_result_type; // type of result: 0: register, 1: system register, 2: memory, 3: other or nothing |
logic [1:0] registerread_offset_field; // address offset. 0: none, 1: 8 bit, possibly scaled, 2: 16 bit, 3: 32 bit |
logic [1:0] registerread_immediate_field; // immediate data field. 0: none, 1: 8 bit, 2: 16 bit, 3: 32 or 64 bit |
logic [1:0] registerread_scale_factor; // 00: index is not scaled, 01: index is scaled by operand size, 10: index is scaled by -1 |
logic registerread_index_limit; // The field indicated by offset_field contains a limit to the index |
logic [`RB:0] registerread_rd_val; // value of register operand RD, bit `RB indicates missing |
logic [`RB:0] registerread_rs_val; // value of register operand RS, bit `RB indicates missing |
logic [`RB:0] registerread_rt_val; // value of register operand RT, bit `RB indicates missing |
logic [`RB:0] registerread_ru_val; // value of register operand RU, bit `RB indicates missing |
logic [`MASKSZ:0] registerread_regmask_val; // value of mask register, bit 32 indicates missing |
logic [1:0] registerread_rd_status; // RD is used as input |
logic [2:0] registerread_rs_status; // use of RS |
logic [2:0] registerread_rt_status; // use of RT |
logic [1:0] registerread_ru_status; // RU is used |
logic [1:0] registerread_mask_status; // mask register is used |
logic registerread_mask_alternative; // mask register and fallback register used for alternative purposes |
logic [2:0] registerread_fallback_use; // 0: no fallback, 1: same as first source operand, 2-4: RU, RS, RT |
logic [32:0] registerread_debugport; // register read by debugger |
|
// address generator |
logic [`COMMON_ADDR_WIDTH-1:0] addrgen_read_write_address; // address of memory operand |
logic addrgen_read_enable; // read from data memory |
logic [1:0] addrgen_read_data_size; |
logic [7:0] addrgen_write_enable; |
logic [63:0] addrgen_write_data; // Any part of the 64 bits write bus can be used when the operand size is less than 64 bits |
logic addrgen_valid; // An instruction is ready for output to next stage |
logic [`CODE_ADDR_WIDTH-1:0] addrgen_instruction_pointer; // address of current instruction |
logic [63:0] addrgen_instruction; // first word of instruction |
logic addrgen_stall_next; // address generator waiting for an operand |
logic [`TAG_WIDTH-1:0] addrgen_tag_val; // instruction tag value |
logic [`RB:0] addrgen_operand1; // value of first register operand |
logic [`RB:0] addrgen_operand2; // value of second register operand |
logic [`RB:0] addrgen_operand3; // value of last operand |
logic [`MASKSZ:0] addrgen_regmask_val; // value of mask register, bit 32 indicates valid |
logic addrgen_vector; // this is a vector instruction |
logic [1:0] addrgen_category; // instruction category: multiformat, single format, jump |
logic [1:0] addrgen_format; // instruction format: A, E, B, D |
logic addrgen_mask_status; // mask register is used |
logic addrgen_mask_alternative; // mask register and fallback register used for alternative purposes |
logic [2:0] addrgen_fallback_use; // 0: no fallback, 1: same as first source operand, 2-4: RU, RS, RT |
logic [1:0] addrgen_num_operands; // number of source operands |
logic [1:0] addrgen_result_type; // type of result: 0: register, 1: system register, 2: memory, 3: other or nothing |
logic [1:0] addrgen_offset_field; // unused |
logic [1:0] addrgen_immediate_field; // immediate data field. 0: none, 1: 8 bit, 2: 16 bit, 3: 32 or 64 bit |
logic [1:0] addrgen_scale_factor; // 00: index is not scaled, 01: index is scaled by operand size, 10: index is scaled by -1 |
logic addrgen_memory_operand; // The instruction has a memory operand |
logic addrgen_array_error; // Array index exceeds limit |
|
logic [31:0] addrgen_debug1; // temporary debug output |
logic [31:0] addrgen_debug2; // temporary debug output |
logic [31:0] addrgen_debug3; // temporary debug output |
|
// data read stage |
logic dataread_valid; // An instruction is ready for output to next stage |
logic [`CODE_ADDR_WIDTH-1:0] dataread_instruction_pointer; // address of current instruction |
logic [31:0] dataread_instruction; // first word of instruction |
logic dataread_stall_predict; // predict next stage will stall |
logic [`TAG_WIDTH-1:0] dataread_tag_val; // instruction tag value |
logic [`RB:0] dataread_operand1; // value of first operand |
logic [`RB:0] dataread_operand2; // value of second operand |
logic [`RB:0] dataread_operand3; // value of last operand |
logic [`MASKSZ:0] dataread_mask_val; // value of mask, bit 32 is 0 if valid |
logic dataread_opr2_from_ram; // value of operand 2 comes from data memory |
logic dataread_opr3_from_ram; // value of last operand comes from data memory |
logic dataread_vector; // this is a vector instruction |
logic [1:0] dataread_category; // 00: multiformat, 01: single format, 10: jump |
logic [1:0] dataread_format; // 00: format A, 01: format E, 10: format B, 11: format C (format D never goes through decoder) |
logic [1:0] dataread_num_operands; // number of source operands |
logic dataread_opr1_used; // opr1_val_out is needed |
logic dataread_opr2_used; // opr2_val_out is needed |
logic dataread_opr3_used; // opr3_val_out is needed |
logic dataread_regmask_used; // regmask_val_out is needed |
logic dataread_mask_alternative; // mask register and fallback register used for alternative purposes |
logic [1:0] dataread_result_type; // type of result: 0: register, 1: system register, 2: memory, 3: other or nothing |
logic [3:0] dataread_exe_unit; // each bit enables a particular execution unit |
// 1: ALU, 10: MUL, 100: DIV, 1000: IN/OUT |
logic [6:0] dataread_opx; // operation ID in execution unit. This is mostly equal to op1 for multiformat instructions |
logic [5:0] dataread_opj; // operation ID for conditional jump instructions |
logic [2:0] dataread_ot; // operand type |
logic [5:0] dataread_option_bits; // option bits from IM3 or mask |
logic [15:0] dataread_im2_bits; // constant bits from IM2 as extra operand |
logic dataread_trap; // trap instruction detected. enable single step mode |
logic dataread_array_error; // array index out of bounds |
logic dataread_read_address_error; // invalid read memory address |
logic dataread_write_address_error; // invalid write memory address |
logic dataread_misaligned_address_error; // misaligned read/write memory address |
logic [31:0] dataread_debug; // output for debugging |
|
// alu stage |
logic alu_valid; // for debug display: alu is active |
logic alu_write_en; // write value to register file |
logic [5:0] alu_register_a; // register to write |
logic [`RB1:0] alu_result; // result to write |
logic [`TAG_WIDTH-1:0] alu_tag; // instruction tag value |
logic alu_jump; // jump instruction: jump taken |
logic alu_nojump; // jump instruction: jump not taken |
logic [`CODE_ADDR_WIDTH-1:0] alu_jump_pointer; // jump target to fetch unit |
logic alu_stall; |
logic alu_stall_next; |
logic alu_error; // unknown instruction |
logic alu_error_parm; // wrong parameter for instruction |
logic [31:0] alu_debug1; // output for debugger |
logic [31:0] alu_debug2; // output for debugger |
|
// mul/div alu |
logic muldiv_valid; // for debug display: alu is active |
logic muldiv_write_en; // write value to register file |
logic [4:0] muldiv_register_a; // register to write |
logic [`RB1:0] muldiv_result; // result to write |
logic [`TAG_WIDTH-1:0] muldiv_tag; // instruction tag value |
logic muldiv_stall; |
logic muldiv_stall_next; |
logic muldiv_error; // unknown instruction |
logic muldiv_error_parm; // wrong parameter for instruction |
logic [31:0] muldiv_debug1; // output for debugger |
logic [31:0] muldiv_debug2; // output for debugger |
|
// in_out_ports |
logic inout_valid; // for debug display: in_out is active |
logic inout_write_en; // write value to register file |
logic [5:0] inout_register_a; // register to write |
logic [`RB1:0] inout_result; // result to write |
logic [`TAG_WIDTH-1:0] inout_tag; // instruction tag value |
logic inout_nojump; // serializing instruction read_perf gives jump not taken signal to resume pipeline |
logic inout_stall; |
logic inout_stall_next; |
logic inout_error; // unknown instruction |
logic inout_error_parm; // wrong parameter for instruction |
logic [`N_ERROR_TYPES-1:0] inout_capab_disable_errors; // capab2 register: disable errors |
logic [3:0] inout_first_error; // error type for first error, stored in inout module |
logic [`CODE_ADDR_WIDTH-1:0] inout_first_error_address; // code address of first error |
logic [31:0] inout_debug; // output for debugger |
|
// error handling |
logic [`N_ERROR_TYPES-1:0] errors_detect; // one bit for each type of error detected |
logic clear_error; // clear error on debug display |
reg show_error; // show error on debug display |
|
|
/*************************************************** |
Top level logic signals |
***************************************************/ |
// result bus 1 |
logic bus1_write_en; // write value to register file |
logic [5:0] bus1_register_a; // register to write (includes system registers) |
logic [`RB1:0] bus1_value; // value to write |
logic [`TAG_WIDTH-1:0] bus1_tag; // result tag for value on bus 1 |
|
// result bus 2 |
logic bus2_write_en; // write value to register file |
logic [4:0] bus2_register_a; // register to write |
logic [`RB1:0] bus2_value; // value to write |
logic [`TAG_WIDTH-1:0] bus2_tag; // result tag for value on bus 2 |
|
// signals for predicting when a result will be available |
logic [`TAG_WIDTH-1:0] predict_tag1; // result tag value on bus 1 in next clock cycle |
logic [`TAG_WIDTH-1:0] predict_tag2; // result tag value on bus 2 in next clock cycle |
|
logic [`CODE_ADDR_WIDTH-2:0] code_read_addr; // Address for reading from ram |
|
reg [2:0] color_led16; // RGB led |
|
always_comb begin |
// result bus 1 |
// There are no tri-state buffers inside the FPGA so we have to simulate the buses by OR'ing results: |
bus1_write_en = alu_write_en | inout_write_en; // write value to register file |
bus1_register_a = alu_register_a | inout_register_a; // register to write |
bus1_value = alu_result | inout_result; // value to write |
bus1_tag = alu_tag | inout_tag; // tag for result on bus 1 |
|
// result bus 2 not yet used |
bus2_write_en = muldiv_write_en; // write value to register file |
bus2_register_a = muldiv_register_a; // register to write |
bus2_value = muldiv_result; // value to write |
bus2_tag = muldiv_tag; // tag for result on bus 2 |
|
// read address for code memory. comes from fetch unit, except for taken conditional or indirect jumps/calls |
code_read_addr = alu_jump ? (alu_jump_pointer >> 1) : fetch_read_addr; |
// predict next tag on bus 1 |
predict_tag1 = (dataread_exe_unit[0] | dataread_exe_unit[3]) ? dataread_tag_val : 0; |
// predict next tag on bus 2. To do: insert propagation delay !! |
predict_tag2 = (dataread_exe_unit[1] | dataread_exe_unit[2]) ? dataread_tag_val : 0; |
|
// error detection |
errors_detect[0] = alu_error | muldiv_error | inout_error; // unknown instruction |
errors_detect[1] = alu_error_parm | muldiv_error_parm | inout_error_parm | call_stack_overflow; // wrong parameter for instruction |
errors_detect[2] = dataread_array_error; // array index out of bounds |
errors_detect[3] = dataread_read_address_error; // read address violation |
errors_detect[4] = dataread_write_address_error; // write address violation |
errors_detect[5] = dataread_misaligned_address_error; // misaligned memory address |
clear_error = reset_button_debounced | step_button_pulse | run_button_pulse | load_button_debounced; // clear error on debug display |
|
end |
|
// single step and reset control |
always_ff @(posedge clock) begin |
reset_step[2:0] <= {reset_step[1:0],(reset_button_debounced|load_button_debounced)}; // shift register delaying reset button |
if (reset_button_debounced) begin |
clock_enable <= 1; // enable clock while resetting |
system_reset <= 1; // reset everything for 3 clock cycles |
program_restart <= 1; |
single_step_mode <= 0; |
end else if (load_button_debounced) begin |
clock_enable <= 1; // enable clock while resetting |
system_reset <= 1; // reset everything for 3 clock cycles |
program_restart <= 0; |
single_step_mode <= 0; |
end else if (reset_step != 0) begin |
clock_enable <= 1; // enable clock while resetting |
system_reset <= 1; // reset everything for 3 clock cycles |
single_step_mode <= 0; // start in single step mode |
end else if (single_step_mode) begin // single-stepping for debugging |
clock_enable <= step_button_pulse; // enable for one clock cycle |
system_reset <= 0; |
program_restart <= 0; |
end else begin // not single_step_mode |
clock_enable <= 1; |
system_reset <= 0; |
program_restart <= 0; |
end |
|
// set or clear single step mode |
if (run_button_pulse) single_step_mode <= 0; |
if (step_button_pulse) single_step_mode <= 1; |
if (dataread_trap) single_step_mode <= 1; // breakpoint sets single step mode |
if (|(errors_detect & ~inout_capab_disable_errors) && !switch15) single_step_mode <= 1; // error detected |
|
if (clear_error) show_error <= 0; |
if (|(errors_detect & ~inout_capab_disable_errors)) show_error <= 1; |
end |
|
|
/*************************************************** |
Memory modules |
***************************************************/ |
|
// code memory |
code_memory code_memory_inst( |
.clock(clock), // clock |
.clock_enable(clock_enable), |
.read_enable(fetch_read_enable | alu_jump), // read enable |
.write_enable(addrgen_write_enable), |
.write_addr_in(addrgen_read_write_address), |
.write_data_in(addrgen_write_data), // Data in |
.read_addr_in(code_read_addr), // Address for reading from code ram |
.data_out(code_memory_data), // Data out |
.debug_out(code_memory_debug) |
); |
|
|
// read/write data memory |
data_memory data_memory_inst ( |
.clock(clock), // clock |
.clock_enable(clock_enable), // clock enable. Used when single-stepping |
.read_write_addr(addrgen_read_write_address), // Address for reading from ram |
.read_enable(addrgen_read_enable), // read enable |
.read_data_size(addrgen_read_data_size), |
.write_enable(addrgen_write_enable), // write enable for each byte separately |
.write_data_in(addrgen_write_data), |
.read_data_out(data_memory_data) // Data out |
); |
|
// call stack |
call_stack call_stack_instance( |
.clock(clock), // clock |
.clock_enable(clock_enable), // clock enable |
.reset(system_reset), // reset |
.call_e(fetch_call_e), // Executing call instruction |
.return_e(fetch_return_e), // Executing return instruction |
.push_data(fetch_call_push_data), // Return address pushed at call instruction |
.pop_data(call_stack_pop_data), // Return address popped at return instruction |
.overflow(call_stack_overflow)); // stack overflow or underflow or error |
|
|
/*************************************************** |
Pipeline stages |
***************************************************/ |
|
// code fetch module |
fetch fetch_inst( |
.clock(clock), // system clock (100 MHz) |
.clock_enable(clock_enable), // clock enable. Used when single-stepping |
.reset(system_reset), // system reset. |
.restart(program_restart), // restart loaded program |
.valid_in(1), // data from code memory ready |
.stall_in(registerread_stall_predict | addrgen_stall_next | dataread_stall_predict | alu_stall_next | muldiv_stall_next | inout_stall_next), // pipeline is stalled |
.jump_in(alu_jump), // a jump target is coming from the ALU. |
.nojump_in(alu_nojump | inout_nojump), // jump target is next instruction |
.jump_pointer(alu_jump_pointer), // jump target from ALU. jump_pointer is also sent to the code memory |
.read_data(code_memory_data), // data from code memory |
.return_pop_data(call_stack_pop_data), // Return address popped here at return instruction |
.read_addr_out(fetch_read_addr), // code read address relative to code memory start |
.read_enable_out(fetch_read_enable), // code memory read enable |
.valid_out(fetch_valid), // An instruction is ready for output to decoder |
.jump_out(fetch_jump), // Jump instruction bypassing pipeline |
.instruction_pointer_out(fetch_instruction_pointer), // address of current instruction |
.instruction_out(fetch_instruction), // current instruction, up to 3 32-bit words long |
.call_e_out(fetch_call_e), // Executing call instruction. push_data contains return address |
.return_e_out(fetch_return_e), // Executing return instruction. return address is available in advance on pop_data |
.stall_predict_out(), // predict stall in decoder |
.call_push_data_out(fetch_call_push_data) , // Return address pushed here at call instruction |
.debug1_out(fetch_debug1) // temporary debug output |
); |
|
decoder decoder_inst ( |
.clock(clock), // system clock (100 MHz) |
.clock_enable(clock_enable), // clock enable. Used when single-stepping |
.reset(system_reset), // system reset. |
.valid_in(fetch_valid), // data from fetch module ready |
.stall_in(registerread_stall_predict | addrgen_stall_next | dataread_stall_predict | alu_stall_next | muldiv_stall_next | inout_stall_next), // pipeline is stalled |
.instruction_pointer_in(fetch_inst.instruction_pointer_out), // address of current instruction |
.instruction_in(fetch_instruction), // current instruction, up to 3 words long |
.write_en1(bus1_write_en), // a result is written to bus 1 |
.write_tag1(bus1_tag), // tag of result in bus 1 |
.write_en2(bus2_write_en), // a result is written to bus 2 |
.write_tag2(bus2_tag), // tag of result in bus 2 |
|
.valid_out(decoder_valid), // An instruction is ready for output to next stage |
.instruction_pointer_out(decoder_instruction_pointer), // address of current instruction |
.instruction_out(decoder_instruction), // first word of instruction |
.stall_out(decoder_stall), // Not ready to receive next instruction |
.tag_a_out(decoder_tag_a), // register number for instruction tag |
.tag_val_out(decoder_tag_val), // instruction tag value |
.tag_write_out(decoder_tag_write), // instruction tag write enable |
.vector_out(decoder_vector), // this is a vector instruction |
.category_out(decoder_category), // 00: multiformat, 01: single format, 10: jump |
.format_out(decoder_format), // 00: format A, 01: format E, 10: format B, 11: format C (format D never goes through decoder) |
.rs_status_out(decoder_rs_status), // use of RS |
.rt_status_out(decoder_rt_status), // use of RT |
.ru_status_out(decoder_ru_status), // 1: RU is used |
.rd_status_out(decoder_rd_status), // 1: RD is used as input |
.mask_status_out(decoder_mask_status), // What the mask register is used for |
.mask_options_out(decoder_mask_options), // 1: mask register may contain options |
.mask_alternative_out(decoder_mask_alternative), // mask register and fallback register used for alternative purposes |
.fallback_use_out(decoder_fallback_use), // 0: no fallback, 1: same as first source operand, 2-4: RU, RS, RT |
.num_operands_out(decoder_num_operands), // number of source operands |
.result_type_out(decoder_result_type), // type of result: 0: register, 1: system register, 2: memory, 3: other or nothing |
.offset_field_out(decoder_offset_field), // address offset. 0: none, 1: 8 bit, possibly scaled, 2: 16 bit, 3: 32 bit |
.immediate_field_out(decoder_immediate_field), // immediate data field. 0: none, 1: 8 bit, 2: 16 bit, 3: 32 or 64 bit |
.scale_factor_out(decoder_scale_factor), // 00: index is not scaled, 01: index is scaled by operand size, 10: index is scaled by -1 |
.index_limit_out(decoder_index_limit), // The field indicated by offset_field contains a limit to the index |
.debug1_out(decoder_debug1) // temporary debug output |
); |
|
register_read register_read_inst ( |
.clock(clock), // system clock |
.clock_enable(clock_enable), // clock enable. Used when single-stepping |
.reset(system_reset), // system reset. |
.valid_in(decoder_valid), // data from fetch module ready |
.stall_in(registerread_stall_predict | addrgen_stall_next | dataread_stall_predict | alu_stall_next | muldiv_stall_next | inout_stall_next), // pipeline is stalled |
.instruction_pointer_in(decoder_instruction_pointer), // address of current instruction |
.instruction_in(decoder_instruction), // current instruction, up to 3 words long |
.tag_write_in(decoder_tag_write), // write tag |
.tag_val_in(decoder_tag_val), // instruction tag value |
.vector_in(decoder_vector), // this is a vector instruction |
.category_in(decoder_category), // 00: multiformat, 01: single format, 10: jump |
.format_in(decoder_format), // 00: format A, 01: format E, 10: format B, 11: format C (format D never goes through decoder) |
.rs_status_in(decoder_rs_status), // 1: RS is register operand |
.rt_status_in(decoder_rt_status), // 1: RT is register operand |
.ru_status_in(decoder_ru_status), // 1: RU is used |
.rd_status_in(decoder_rd_status), // 1: RD is used as input |
.mask_status_in(decoder_mask_status), // use of mask |
.mask_options_in(decoder_mask_options), // 1: mask register may contain options |
.mask_alternative_in(decoder_mask_alternative), // mask register and fallback register used for alternative purposes |
.fallback_use_in(decoder_fallback_use), // 0: no fallback, 1: same as first source operand, 2-4: RU, RS, RT |
.num_operands_in(decoder_num_operands), // number of source operands |
.result_type_in(decoder_result_type), // type of result: 0: register, 1: system register, 2: memory, 3: other or nothing |
.offset_field_in(decoder_offset_field), // address offset. 0: none, 1: 8 bit, possibly scaled, 2: 16 bit, 3: 32 bit |
.immediate_field_in(decoder_immediate_field), // immediate data field. 0: none, 1: 8 bit, 2: 16 bit, 3: 32 or 64 bit |
.scale_factor_in(decoder_scale_factor), // 00: index is not scaled, 01: index is scaled by operand size, 10: index is scaled by -1 |
.index_limit_in(decoder_index_limit), // The field indicated by offset_field contains a limit to the index |
.writeport1(bus1_value), // result bus 1 |
.writea1(bus1_register_a), // address input for bus 1 |
.write_en1(bus1_write_en), // a result is written to bus 1 |
.write_tag1(bus1_tag), // tag of result in bus 1 |
.writeport2(bus2_value), // result bus 2 |
.writea2(bus2_register_a), // address input for bus 2 |
.write_en2(bus2_write_en), // a result is written to bus 2 |
.write_tag2(bus2_tag), // tag of result in bus 2 |
.debug_reada(debug_reada), // register read port for debugger |
|
.valid_out(registerread_valid), // An instruction is ready for output to next stage |
.instruction_pointer_out(registerread_instruction_pointer), // address of current instruction |
.instruction_out(registerread_instruction), // first word of instruction |
.stall_predict_out(registerread_stall_predict), // predict next stage will stall |
.tag_val_out(registerread_tag_val), // instruction tag value |
.vector_out(registerread_vector), // this is a vector instruction |
.category_out(registerread_category), // 00: multiformat, 01: single format, 10: jump |
.format_out(registerread_format), // 00: format A, 01: format E, 10: format B, 11: format C (format D never goes through decoder) |
.num_operands_out(registerread_num_operands), // number of source operands |
.result_type_out(registerread_result_type), // type of result: 0: register, 1: system register, 2: memory, 3: other or nothing |
.offset_field_out(registerread_offset_field), // address offset. 0: none, 1: 8 bit, possibly scaled, 2: 16 bit, 3: 32 bit |
.immediate_field_out(registerread_immediate_field), // immediate data field. 0: none, 1: 8 bit, 2: 16 bit, 3: 32 or 64 bit |
.scale_factor_out(registerread_scale_factor), // 00: index is not scaled, 01: index is scaled by operand size, 10: index is scaled by -1 |
.index_limit_out(registerread_index_limit), // The field indicated by offset_field contains a limit to the index |
.rd_val_out(registerread_rd_val), // value of register operand RD, bit `RB indicates missing |
.rs_val_out(registerread_rs_val), // value of register operand RS, bit `RB indicates missing |
.rt_val_out(registerread_rt_val), // value of register operand RT, bit `RB indicates missing |
.ru_val_out(registerread_ru_val), // value of register operand RU, bit `RB indicates missing |
.regmask_val_out(registerread_regmask_val), // value of mask register, bit 32 indicates missing |
.rd_status_out(registerread_rd_status), // 1: RD is used as input |
.rs_status_out(registerread_rs_status), // use of RS |
.rt_status_out(registerread_rt_status), // use of RT |
.ru_status_out(registerread_ru_status), // 1: RU is used |
.mask_status_out(registerread_mask_status), // 1: mask register is used |
.mask_alternative_out(registerread_mask_alternative), // mask register and fallback register used for alternative purposes |
.fallback_use_out(registerread_fallback_use), // 0: no fallback, 1: same as first source operand, 2-4: RU, RS, RT |
.debugport_out(registerread_debugport) // read for debugging purpose |
); |
|
addressgenerator addressgenerator_inst ( |
.clock(clock), // system clock (100 MHz) |
.clock_enable(clock_enable), // clock enable. Used when single-stepping |
.reset(system_reset), // system reset. |
.valid_in(registerread_valid), // data from fetch module ready |
.stall_in(dataread_stall_predict | alu_stall_next | muldiv_stall_next | inout_stall_next), // pipeline is stalled |
.instruction_pointer_in(registerread_instruction_pointer), // address of current instruction |
.instruction_in(registerread_instruction), // current instruction, up to 3 words long |
.tag_val_in(registerread_tag_val), // instruction tag value |
.vector_in(registerread_vector), // this is a vector instruction |
.category_in(registerread_category), // 00: multiformat, 01: single format, 10: jump |
.format_in(registerread_format), // 00: format A, 01: format E, 10: format B, 11: format C (format D never goes through decoder) |
.rs_status_in(registerread_rs_status), // use of RS |
.rt_status_in(registerread_rt_status), // use of RT |
.ru_status_in(registerread_ru_status), // RU is used |
.rd_status_in(registerread_rd_status), // RD is used as input |
.mask_status_in(registerread_mask_status), // mask register used |
.mask_alternative_in(registerread_mask_alternative), // mask register and fallback register used for alternative purposes |
.fallback_use_in(registerread_fallback_use), // 0: no fallback, 1: same as first source operand, 2-4: RU, RS, RT |
.num_operands_in(registerread_num_operands), // number of source operands |
.result_type_in(registerread_result_type), // type of result: 0: register, 1: system register, 2: memory, 3: other or nothing |
.offset_field_in(registerread_offset_field), // address offset. 0: none, 1: 8 bit, possibly scaled, 2: 16 bit, 3: 32 bit |
.immediate_field_in(registerread_immediate_field), // immediate data field. 0: none, 1: 8 bit, 2: 16 bit, 3: 32 or 64 bit |
.scale_factor_in(registerread_scale_factor), // 00: index is not scaled, 01: index is scaled by operand size, 10: index is scaled by -1 |
.index_limit_in(registerread_index_limit), // The field indicated by offset_field contains a limit to the index |
.rd_val_in(registerread_rd_val), // value of register operand RD, bit `RB indicates missing |
.rs_val_in(registerread_rs_val), // value of register operand RS, bit `RB indicates missing |
.rt_val_in(registerread_rt_val), // value of register operand RT, bit `RB indicates missing |
.ru_val_in(registerread_ru_val), // value of register operand RU, bit `RB indicates missing |
.regmask_val_in(registerread_regmask_val), // mask register |
.write_en1(bus1_write_en), // a result is written to bus 1 |
.write_tag1_in(bus1_tag), // tag of result in bus 1 |
.writeport1_in(bus1_value), // result bus 1 |
.write_en2(bus2_write_en), // a result is written to bus 2 |
.write_tag2_in(bus2_tag), // tag of result in bus 2 |
.writeport2_in(bus2_value), // result bus 2 |
.predict_tag1_in(predict_tag1), // tag on result bus 1 in next clock cycle |
.predict_tag2_in(predict_tag2), // tag on result bus 2 in next clock cycle |
.read_write_address_out(addrgen_read_write_address), // address of read memory operand |
.read_enable_out(addrgen_read_enable), // enable read from data memory |
.read_data_size_out(addrgen_read_data_size), // data size for memory read |
.write_enable_out(addrgen_write_enable), // write enable for each byte separately |
.write_data_out(addrgen_write_data), // data to write |
.valid_out(addrgen_valid), // An instruction is ready for output to next stage |
.instruction_pointer_out(addrgen_instruction_pointer), // address of current instruction |
.instruction_out(addrgen_instruction), // first word of instruction |
.stall_predict_out(addrgen_stall_next), // will be waiting for an operand |
.tag_val_out(addrgen_tag_val), // instruction tag value |
.operand1_out(addrgen_operand1), // value of first operand, bit `RB indicates invalid |
.operand2_out(addrgen_operand2), // value of second operand, bit `RB indicates invalid |
.operand3_out(addrgen_operand3), // value of last, bit `RB indicates valid |
.regmask_val_out(addrgen_regmask_val), // value of mask register, bit 32 indicates valid |
.vector_out(addrgen_vector), // this is a vector instruction |
.category_out(addrgen_category), // 00: multiformat, 01: single format, 10: jump |
.format_out(addrgen_format), // 00: format A, 01: format E, 10: format B, 11: format C (format D never goes through decoder) |
.mask_status_out(addrgen_mask_status), // 1: mask register used |
.mask_alternative_out(addrgen_mask_alternative), // mask register and fallback register used for alternative purposes |
.fallback_use_out(addrgen_fallback_use), // 0: no fallback, 1: same as first source operand, 2-4: RU, RS, RT |
.num_operands_out(addrgen_num_operands), // number of source operands |
.result_type_out(addrgen_result_type), // type of result: 0: register, 1: system register, 2: memory, 3: other or nothing |
.offset_field_out(addrgen_offset_field), // address offset. 0: none, 1: 8 bit, possibly scaled, 2: 16 bit, 3: 32 bit |
.immediate_field_out(addrgen_immediate_field), // immediate data field. 0: none, 1: 8 bit, 2: 16 bit, 3: 32 or 64 bit |
.scale_factor_out(addrgen_scale_factor), // 00: index is not scaled, 01: index is scaled by operand size, 10: index is scaled by -1 |
.memory_operand_out(addrgen_memory_operand), // The instruction has a memory operand |
.array_error_out(addrgen_array_error), // Array index exceeds limit |
.options3_out(addrgen_options3), // IM3 containts option bits |
.debug1_out(addrgen_debug1), // Temporary output for debugging purpose |
.debug2_out(addrgen_debug2), // Temporary output for debugging purpose |
.debug3_out(addrgen_debug3) // Temporary output for debugging purpose |
); |
|
dataread dataread_inst ( |
.clock(clock), // system clock |
.clock_enable(clock_enable), // clock enable. Used when single-stepping |
.reset(system_reset), // system reset. |
.valid_in(addrgen_valid), // data from fetch module ready |
.stall_in(dataread_stall_predict | alu_stall_next | muldiv_stall_next | inout_stall_next), // pipeline is stalled |
.instruction_pointer_in(addrgen_instruction_pointer), // address of current instruction |
.instruction_in(addrgen_instruction), // current instruction, up to 3 words long |
.tag_val_in(addrgen_tag_val), // instruction tag value |
.vector_in(addrgen_vector), // this is a vector instruction |
.category_in(addrgen_category), // 00: multiformat, 01: single format, 10: jump |
.format_in(addrgen_format), // 00: format A, 01: format E, 10: format B, 11: format C (format D never goes through decoder) |
.mask_status_in(addrgen_mask_status), // 1: mask register used |
.mask_alternative_in(addrgen_mask_alternative), // mask register and fallback register used for alternative purposes |
.num_operands_in(addrgen_num_operands), // number of source operands |
.result_type_in(addrgen_result_type), // type of result: 0: register, 1: system register, 2: memory, 3: other or nothing |
.immediate_field_in(addrgen_immediate_field), // immediate data field. 0: none, 1: 8 bit, 2: 16 bit, 3: 32 or 64 bit |
.memory_operand_in(addrgen_memory_operand), // the instruction has a memory operand |
.array_error_in(addrgen_array_error), // Array index exceeds limit |
.options3_in(addrgen_options3), // IM3 containts option bits |
.write_en1(bus1_write_en), // a result is written to bus 1 |
.write_tag1_in(bus1_tag), // tag of result in bus 1 |
.writeport1_in(bus1_value), // result bus 1 |
.write_en2(bus2_write_en), // a result is written to bus 2 |
.write_tag2_in(bus2_tag), // tag of result in bus 2 |
.writeport2_in(bus2_value), // result bus 2 |
.predict_tag1_in(predict_tag1), // result tag value on bus 1 in next clock cycle |
.predict_tag2_in(predict_tag2), // result tag value on bus 2 in next clock cycle |
.operand1_in(addrgen_operand1), // value of first operand |
.operand2_in(addrgen_operand2), // value of second operand |
.operand3_in(addrgen_operand3), // value of last operand |
.regmask_val_in(addrgen_regmask_val), // mask register |
.address_in(addrgen_read_write_address), // address of memory operand |
.ram_data_in(data_memory_data), // memory operand from data memory |
.valid_out(dataread_valid), // An instruction is ready for output to next stage |
.instruction_pointer_out(dataread_instruction_pointer),// address of current instruction |
.instruction_out(dataread_instruction), // first word of instruction |
.stall_predict_out(dataread_stall_predict), // predict next stage will stall |
.tag_val_out(dataread_tag_val), // instruction tag value |
.operand1_out(dataread_operand1), // value of first operand for 3-op instructions, bit `RB is 0 if valid |
.operand2_out(dataread_operand2), // value of second operand, bit `RB is 0 if valid |
.operand3_out(dataread_operand3), // value of last operand, bit `RB is 0 if valid |
.mask_val_out(dataread_mask_val), // value of mask, bit 32 is 0 if valid |
.opr2_from_ram_out(dataread_opr2_from_ram), // value of operand 2 comes from data memory |
.opr3_from_ram_out(dataread_opr3_from_ram), // value of last operand comes from data memory |
.vector_out(dataread_vector), // this is a vector instruction |
.category_out(dataread_category), // 00: multiformat, 01: single format, 10: jump |
.format_out(dataread_format), // 00: format A, 01: format E, 10: format B, 11: format C (format D never goes through decoder) |
.num_operands_out(dataread_num_operands), // number of source operands |
.result_type_out(dataread_result_type), // type of result: 0: register, 1: system register, 2: memory, 3: other or nothing |
.opr1_used_out(dataread_opr1_used), // operand1 is needed |
.opr2_used_out(dataread_opr2_used), // operand2 is needed |
.opr3_used_out(dataread_opr3_used), // operand3 is needed |
.regmask_used_out(dataread_regmask_used), // regmask_val_out is needed |
.mask_alternative_out(dataread_mask_alternative), // mask register and fallback register used for alternative purposes |
.exe_unit_out(dataread_exe_unit), // each bit enables a particular execution unit |
.opx_out(dataread_opx), // operation ID in execution unit. This is mostly equal to op1 for multiformat instructions |
.opj_out(dataread_opj), // operation ID for conditional jump instructions |
.ot_out(dataread_ot), // operand type |
.option_bits_out(dataread_option_bits), // instruction option bits |
.im2_bits_out(dataread_im2_bits), // constant bits from IM2 as extra operand |
.trap_out(dataread_trap), // trap instruction detected |
.array_error_out(dataread_array_error), // array index out of bounds |
.read_address_error_out(dataread_read_address_error), // invalid read memory address |
.write_address_error_out(dataread_write_address_error),// invalid write memory address |
.misaligned_address_error_out(dataread_misaligned_address_error), // misaligned read/write memory address |
.debug_out(dataread_debug) // output for debugging |
); |
|
alu alu_inst ( |
.clock(clock), // system clock |
.clock_enable(clock_enable), // clock enable. Used when single-stepping |
.reset(system_reset), // system reset. |
.valid_in(dataread_valid & dataread_exe_unit[0]), // data from previous stage ready |
.stall_in(alu_stall_next | muldiv_stall_next | inout_stall_next),// pipeline is stalled |
.instruction_pointer_in(dataread_instruction_pointer), // address of current instruction |
.instruction_in(dataread_instruction), // current instruction, first word only |
.tag_val_in(dataread_tag_val), // instruction tag value |
.category_in(dataread_category), // 00: multiformat, 01: single format, 10: jump |
.mask_alternative_in(dataread_mask_alternative), // mask register and fallback register used for alternative purposes |
.result_type_in(dataread_result_type), // type of result: 0: register, 1: system register, 2: memory, 3: other or nothing |
.vector_in(dataread_vector), // vector instruction |
.opx_in(dataread_opx), // operation ID in execution unit. This is mostly equal to op1 for multiformat instructions |
.opj_in(dataread_opj), // operation ID for conditional jump instructions |
.ot_in(dataread_ot), // operand type |
.option_bits_in(dataread_option_bits), // option bits from IM3 or mask |
.im2_bits_in(dataread_im2_bits), // constant bits from IM2 as extra operand |
|
// monitor result buses: |
.write_en1(bus1_write_en), // a result is written to bus 1 |
.write_tag1_in(bus1_tag), // tag of result in bus 1 |
.writeport1_in(bus1_value), // result bus 1 |
.write_en2(bus2_write_en), // a result is written to bus 2 |
.write_tag2_in(bus2_tag), // tag of result in bus 2 |
.writeport2_in(bus2_value), // result bus 2 |
.predict_tag1_in(predict_tag1), // result tag value on bus 1 in next clock cycle |
.predict_tag2_in(predict_tag2), // result tag value on bus 2 in next clock cycle |
// Register values sampled from result bus in previous stages |
.operand1_in(dataread_operand1), // first operand or fallback value |
.operand2_in(dataread_operand2), // second operand value |
.operand3_in(dataread_operand3), // last operand value |
.regmask_val_in(dataread_mask_val), // mask register |
.ram_data_in(data_memory_data), // memory operand from data memory |
.opr2_from_ram_in(dataread_opr2_from_ram), // value of operand 2 comes from data memory |
.opr3_from_ram_in(dataread_opr3_from_ram), // value of last operand comes from data memory |
.opr1_used_in(dataread_opr1_used), // opr1_val_in is needed |
.opr2_used_in(dataread_opr2_used), // opr2_val_in is needed |
.opr3_used_in(dataread_opr3_used), // opr3_val_in is needed |
.regmask_used_in(dataread_regmask_used), // regmask_val_in is needed |
.valid_out(alu_valid), // alu is active |
.register_write_out(alu_write_en), // write enable for bus 1 |
.register_a_out(alu_register_a), // register to write |
.result_out(alu_result), // |
.tag_val_out(alu_tag), // instruction tag value |
.jump_out(alu_jump), // jump instruction: jump taken |
.nojump_out(alu_nojump), // jump instruction: jump not taken |
.jump_pointer_out(alu_jump_pointer), // jump target to fetch unit |
.stall_out(alu_stall), // alu is waiting for an operand or not ready to receive a new instruction |
.stall_next_out(alu_stall_next), // alu will be waiting in next clock cycle |
.error_out(alu_error), // unknown instruction |
.error_parm_out(alu_error_parm), // wrong parameter for instruction |
.debug1_out(alu_debug1), // debug information |
.debug2_out(alu_debug2) // debug information |
); |
|
mul_div muldiv_inst ( |
.clock(clock), // system clock |
.clock_enable(clock_enable), // clock enable. Used when single-stepping |
.reset(system_reset), // system reset. |
.valid_in(dataread_valid & (dataread_exe_unit[1] | dataread_exe_unit[2])), // data from previous stage ready |
.stall_in(alu_stall_next | muldiv_stall_next | inout_stall_next),// pipeline is stalled |
.instruction_in(dataread_instruction[31:0]), // current instruction, up to 3 words long |
.tag_val_in(dataread_tag_val), // instruction tag value |
.category_in(dataread_category), // 00: multiformat, 01: single format, 10: jump |
.mask_alternative_in(dataread_mask_alternative), // mask register and fallback register used for alternative purposes |
.result_type_in(dataread_result_type), // type of result: 0: register, 1: system register, 2: memory, 3: other or nothing |
.vector_in(dataread_vector), // vector instruction |
.opx_in(dataread_opx), // operation ID in execution unit. This is mostly equal to op1 for multiformat instructions |
.ot_in(dataread_ot), // operand type |
.option_bits_in(dataread_option_bits), // option bits from IM3 or mask |
|
// monitor result buses: |
.write_en1(bus1_write_en), // a result is written to bus 1 |
.write_tag1_in(bus1_tag), // tag of result in bus 1 |
.writeport1_in(bus1_value), // result bus 1 |
.write_en2(bus2_write_en), // a result is written to bus 2 |
.write_tag2_in(bus2_tag), // tag of result in bus 2 |
.writeport2_in(bus2_value), // result bus 2 |
.predict_tag1_in(predict_tag1), // result tag value on bus 1 in next clock cycle |
.predict_tag2_in(predict_tag2), // result tag value on bus 2 in next clock cycle |
// Register values sampled from result bus in previous stages |
.operand1_in(dataread_operand1), // first operand or fallback value |
.operand2_in(dataread_operand2), // second operand value |
.operand3_in(dataread_operand3), // last operand value |
.regmask_val_in(dataread_mask_val), // mask register |
.ram_data_in(data_memory_data), // memory operand from data memory |
.opr2_from_ram_in(dataread_opr2_from_ram), // value of operand 2 comes from data memory |
.opr3_from_ram_in(dataread_opr3_from_ram), // value of last operand comes from data memory |
.opr1_used_in(dataread_opr1_used), // opr1_val_in is needed |
.opr2_used_in(dataread_opr2_used), // opr2_val_in is needed |
.opr3_used_in(dataread_opr3_used), // opr3_val_in is needed |
.regmask_used_in(dataread_regmask_used), // regmask_val_in is needed |
|
.valid_out(muldiv_valid), // alu is active |
.register_write_out(muldiv_write_en), // write enable for bus 1 |
.register_a_out(muldiv_register_a), // register to write |
.result_out(muldiv_result), // |
.tag_val_out(muldiv_tag), // instruction tag value |
.stall_out(muldiv_stall), // alu is waiting for an operand or not ready to receive a new instruction |
.stall_next_out(muldiv_stall_next), // alu will be waiting in next clock cycle |
.error_out(muldiv_error), // unknown instruction |
.error_parm_out(muldiv_error_parm), // wrong parameter for instruction |
.debug1_out(muldiv_debug1), // debug information |
.debug2_out(muldiv_debug2) // debug information |
); |
|
/*************************************************** |
Input and output ports |
***************************************************/ |
|
in_out_ports in_out_ports_inst ( |
.clock(clock), // system clock |
.clock_enable(clock_enable), // clock enable. Used when single-stepping |
.reset(system_reset), // system reset |
.valid_in(dataread_valid & dataread_exe_unit[3]), // data from previous stage ready |
.stall_in(alu_stall_next | muldiv_stall_next | inout_stall_next),// pipeline is stalled |
.instruction_in(dataread_instruction[31:0]), // current instruction, up to 3 words long |
.tag_val_in(dataread_tag_val), // instruction tag value |
.category_in(dataread_category), // 00: multiformat, 01: single format, 10: jump |
.result_type_in(dataread_result_type), // type of result: 0: register, 1: system register, 2: memory, 3: other or nothing |
.mask_alternative_in(dataread_mask_alternative), // mask register and fallback register used for alternative purposes |
.vector_in(dataread_vector), // vector instruction |
.opx_in(dataread_opx), // operation ID in execution unit. This is mostly equal to op1 for multiformat instructions |
.opj_in(dataread_opj), // operation ID for conditional jump instructions |
.ot_in(dataread_ot), // operand type |
.regmask_used_in(dataread_regmask_used), // regmask_val_in is needed |
|
// connections to UART |
.uart_bit_in(uart_txd_in), // serial input |
.uart_rts_in(uart_rts_in), // ready to send input |
|
// monitor result buses: |
.write_en1(bus1_write_en), // a result is written to bus 1 |
.write_tag1_in(bus1_tag), // tag of result in bus 1 |
.writeport1_in(bus1_value), // result bus 1 |
.write_en2(bus2_write_en), // a result is written to bus 2 |
.write_tag2_in(bus2_tag), // tag of result in bus 2 |
.writeport2_in(bus2_value), // result bus 2 |
.predict_tag1_in(predict_tag1), // result tag value on bus 1 in next clock cycle |
.predict_tag2_in(predict_tag2), // result tag value on bus 2 in next clock cycle |
|
// Register values sampled from result bus in previous stages |
.operand1_in(dataread_operand1), // first operand or fallback value |
.operand2_in(dataread_operand2), // second operand |
.operand3_in(dataread_operand3), // last operand |
.regmask_val_in(dataread_mask_val), // mask register |
.opr1_used_in(dataread_opr1_used), // opr1_val_in is needed |
|
// signals used for performance monitoring |
.instruction_valid_in(dataread_valid), // instruction is valid but possibly going to a different exe unit |
.fast_jump_in(fetch_jump), // a jump is bypassing the pipeline |
.errors_detect_in(errors_detect), // one bit for each type of error detected |
.fetch_instruction_pointer(fetch_instruction_pointer), |
.dataread_instruction_pointer(dataread_instruction_pointer), |
.dataread_valid(dataread_valid), // used when reconstructing alu_instruction_pointer |
.call_stack_overflow(call_stack_overflow), // used for differentiating errors_detect_in[1] |
.clear_error_in(clear_error), // debug clear error |
|
// outputs |
.valid_out(inout_valid), // in_out is active |
.register_write_out(inout_write_en), |
.register_a_out(inout_register_a), // register to write |
.result_out(inout_result), |
.tag_val_out(inout_tag), // instruction tag value |
.nojump_out(inout_nojump), // serializing instruction finished |
.stall_out(inout_stal), // alu is waiting for an operand or not ready to receive a new instruction |
.stall_next_out(inout_stall_next), // alu will be waiting in next clock cycle |
.error_out(inout_error), // unknown instruction |
.error_parm_out(inout_error_parm), // wrong parameter for instruction |
.uart_bit_out(uart_rxd_out), // serial output |
.uart_cts_out(uart_cts_out), // clear to send output |
.capab_disable_errors(inout_capab_disable_errors), // capab2 register: disable errors |
.first_error(inout_first_error), // error type for first error |
.first_error_address(inout_first_error_address), // code address of first error |
.debug_out(inout_debug) // debug information |
); |
|
/*************************************************** |
Debugging signals |
***************************************************/ |
|
// debug display |
debug_display debug_display_inst ( |
.clock(clock), // system clock (50 - 100 MHz) |
.clock_enable(clock_enable), // clock enable. Used when single-stepping |
.reset_button_debounced(reset_button_debounced), // reset button |
|
// from fetch stage |
.fetch_instruction(fetch_instruction[63:0]), // first words of instruction |
.fetch_instruction_pointer(fetch_instruction_pointer), // point to current instruction |
.fetch_valid(fetch_valid), // output from fetch is ready |
.fetch_jump(fetch_jump), // jump instruction bypassing pipeline |
.fetch_call_e(fetch_call_e), // executing call instruction |
.fetch_return_e(fetch_return_e), // executing return instruction |
.registerread_stall_predict(registerread_stall_predict),// address generation stalled next |
.addrgen_stall_next(addrgen_stall_next), |
.dataread_stall_predict(dataread_stall_predict), // alu stalled next |
.alu_stall_next(alu_stall_next), // alu stalled next |
.muldiv_stall_next(muldiv_stall_next), // muldiv stalled next |
.inout_stall_next(inout_stall_next), // in_out_ports stalled next |
// from decoder |
.decoder_instruction(decoder_instruction[63:0]), // first words of instruction |
.decoder_instruction_pointer(decoder_instruction_pointer), // address of current instruction |
.decoder_valid(decoder_valid), // output from decoder is ready |
// from register_read |
.registerread_instruction(registerread_instruction[63:0]), // first words of instruction |
.registerread_instruction_pointer(registerread_instruction_pointer), // address of current instruction |
.registerread_valid(registerread_valid), // output from decode_wait is ready |
// from address generator |
.addrgen_instruction(addrgen_instruction[63:0]), // first words of instruction |
.addrgen_instruction_pointer(addrgen_instruction_pointer), // address of current instruction |
.addrgen_valid(addrgen_valid), // output from addrgen is ready |
// from address_wait |
.dataread_instruction(dataread_instruction), // first words of instruction |
.dataread_instruction_pointer(dataread_instruction_pointer), // address of current instruction |
.dataread_opx(dataread_opx), // operation ID in execution unit. This is mostly equal to op1 for multiformat instructions |
.dataread_valid(dataread_valid), // output from addrwait is ready |
.dataread_operand1(dataread_operand1), // first register operand RD or RU |
.dataread_operand2(dataread_operand2), // second register operand RS |
.dataread_operand3(dataread_operand3), // last register operand RT |
.dataread_mask_val(dataread_mask_val), // mask register value |
.ram_data_in(data_memory_data[15:0]), // memory operand from data memory |
.dataread_opr2_from_ram(dataread_opr2_from_ram), // value of operand 2 comes from data ram |
.dataread_opr3_from_ram(dataread_opr3_from_ram), // value of last operand comes from data ram |
|
// from ALU |
//.writea1(bus1_register_a), // register to write |
.alu_result(bus1_value[31:0]), // |
.write_tag1(bus1_tag), |
.alu_valid(alu_valid | muldiv_valid | inout_valid), // alu or in_out is ready |
.alu_jump(alu_jump), // jump instruction: jump taken |
//.alu_nojump(alu_nojump), // jump instruction: jump not taken |
.alu_jump_pointer(alu_jump_pointer), |
|
// from result buses |
.writeport2(bus2_value[31:0]), |
.write_en2(bus2_write_en), |
.write_tag2(bus2_tag), |
|
// output to display |
.lcd_rs(lcd_rs), // LCD RS pin |
.lcd_e(lcd_e), // enable pins for two LCD displays |
.lcd_data(lcd_data) // LCD data, 4 bit bus |
); |
|
|
`include "debugger.vh" |
|
assign led0 = load_button_debounced; |
assign led1 = reset_button_debounced; |
assign led2 = run_button_debounced; |
assign led3 = step_button_debounced; |
|
assign led4 = fetch_call_e; // vacant. connected to something just to avoid warning |
assign led5 = fetch_return_e; |
assign led6 = fetch_valid; |
assign led7 = system_reset; |
|
/* |
assign led12 = registerread_stall_predict; |
assign led13 = addrgen_stall_next; |
assign led14 = dataread_stall_predict; |
assign led15 = alu_stall_next; |
*/ |
// temporary led assignments |
assign led12 = call_stack_overflow; |
assign led13 = alu_error_parm | muldiv_error_parm; |
assign led14 = inout_error_parm; |
assign led15 = show_error; |
|
// RGB led |
assign led16R = color_led16[0]; |
assign led16G = color_led16[1]; |
assign led16B = color_led16[2]; |
|
endmodule |