1 |
22 |
Agner |
//////////////////////////////////////////////////////////////////////////////////
|
2 |
|
|
// Engineer: Agner Fog
|
3 |
|
|
//
|
4 |
|
|
// Create date: 2020-05-25
|
5 |
|
|
// Last modified: 2021-08-03
|
6 |
|
|
// Module name: debugger
|
7 |
|
|
// Project name: ForwardCom soft core
|
8 |
|
|
// Tool versions: Vivado 2020.1
|
9 |
|
|
// License: CERN-OHL-W
|
10 |
|
|
// Description: Debug feature giving access to any signal in the pipeline.
|
11 |
|
|
// The signal to show is selected with input switches and shown on 7-segment displays
|
12 |
|
|
//////////////////////////////////////////////////////////////////////////////////
|
13 |
|
|
|
14 |
|
|
// debug output on 7-segment display
|
15 |
|
|
// switch 8:0: select what to show on display, according to the cases below.
|
16 |
|
|
|
17 |
|
|
logic [8:0] debug_out_select ; // select what to show on debug display
|
18 |
|
|
reg [7:0] enable_digits; // enable each digit
|
19 |
|
|
reg [31:0] debugOut; // output to debug display
|
20 |
|
|
reg [26:0] clock_counter = 0; // divide clock by 100E6
|
21 |
|
|
reg [15:0] clock_1 = 0; // second counter for testing clock frequency
|
22 |
|
|
|
23 |
|
|
always_ff @(posedge clock) begin
|
24 |
|
|
|
25 |
|
|
// divide clock for testing
|
26 |
|
|
if (clock_counter == 100000000) begin
|
27 |
|
|
clock_counter <= 0;
|
28 |
|
|
clock_1 <= clock_1 + 1;
|
29 |
|
|
end else begin
|
30 |
|
|
clock_counter <= clock_counter + 1;
|
31 |
|
|
end
|
32 |
|
|
|
33 |
|
|
enable_digits <= 8'b11111111;
|
34 |
|
|
color_led16 <= 0;
|
35 |
|
|
|
36 |
|
|
/* List the signals you want to be available on the display. You may change this list.
|
37 |
|
|
If you want to see local signals within a module, then the best way is as follows:
|
38 |
|
|
Make one or more debug output registers in the module. Local variables that are not
|
39 |
|
|
register variables are clocked out to the debug output register. Local variables that
|
40 |
|
|
are already registered should be assigned to the debug output rather than be clocked
|
41 |
|
|
out in order to prevent an extra clock cycle delay. See fetch.sv for an example.
|
42 |
|
|
All debug signals should apply to the same clock cycle in order to prevent confusion.
|
43 |
|
|
You may comment out some signals in order to save resources.
|
44 |
|
|
*/
|
45 |
|
|
debug_out_select <= {switch8,switch7,switch6,switch5,switch4,switch3,switch2,switch1,switch0};
|
46 |
|
|
case (debug_out_select)
|
47 |
|
|
|
48 |
|
|
// fetch unit
|
49 |
|
|
8'b00000000: debugOut <= fetch_instruction[31:0];
|
50 |
|
|
8'b00000001: debugOut <= fetch_instruction[63:32];
|
51 |
|
|
8'b00000010: debugOut <= fetch_instruction[95:64];
|
52 |
|
|
8'b00000011: debugOut <= fetch_instruction_pointer;
|
53 |
|
|
8'b00000100: debugOut <= {fetch_read_enable,{(27-`CODE_ADDR_WIDTH){1'b0}},fetch_read_addr,1'b0}; // fetch_read_addr = half value
|
54 |
|
|
8'b00000101: debugOut <= code_memory_data[31:0];
|
55 |
|
|
8'b00000110: debugOut <= code_memory_data[63:32];
|
56 |
|
|
8'b00000111: debugOut <= {fetch_valid,2'b0,fetch_jump};
|
57 |
|
|
//8'b00001111: debugOut <= call_stack_pop_data;
|
58 |
|
|
8'b00001000: debugOut <= fetch_debug1;
|
59 |
|
|
|
60 |
|
|
// decoder
|
61 |
|
|
//8'b00010000: debugOut <= decoder_instruction[31:0];
|
62 |
|
|
//8'b00010001: debugOut <= decoder_instruction[63:32];
|
63 |
|
|
8'b00010010: debugOut <= decoder_instruction_pointer;
|
64 |
|
|
8'b00010100: debugOut <= {decoder_num_operands, 3'b0,decoder_mask_options, 2'b0,decoder_rd_status, 2'b0,decoder_ru_status, 1'b0,decoder_rt_status, 1'b0,decoder_rs_status};
|
65 |
|
|
8'b00010101: debugOut <= {decoder_index_limit, 2'b0,decoder_scale_factor, 2'b0,decoder_offset_field, 2'b0,decoder_result_type};
|
66 |
|
|
8'b00010110: debugOut <= {decoder_num_operands, 2'b0,decoder_format, 2'b0,decoder_category};
|
67 |
|
|
8'b00011000: debugOut <= {decoder_read,decoder_tag_write, 3'b0,decoder_tag_val, 2'b0,decoder_tag_a};
|
68 |
|
|
8'b00011110: debugOut <= { 2'b0,decoder_result_type};
|
69 |
|
|
8'b00011111: debugOut <= decoder_debug1;
|
70 |
|
|
|
71 |
|
|
// register read stage
|
72 |
|
|
//8'b00100000: debugOut <= registerread_instruction[31:0];
|
73 |
|
|
8'b00100010: debugOut <= registerread_instruction_pointer;
|
74 |
|
|
8'b00100011: debugOut <= {registerread_num_operands, 2'b0,registerread_rd_status, 2'b0,registerread_ru_status, 1'b0,registerread_rt_status, 1'b0,registerread_rs_status};
|
75 |
|
|
8'b00100100: debugOut <= registerread_fallback_use;
|
76 |
|
|
8'b00100110: debugOut <= {registerread_stall_predict, 3'b0,registerread_valid};
|
77 |
|
|
8'b00101000: debugOut <= {registerread_rd_val[`RB], 3'b0,registerread_rd_val[27:0]};
|
78 |
|
|
8'b00101001: debugOut <= {registerread_rs_val[`RB], 3'b0,registerread_rs_val[27:0]};
|
79 |
|
|
8'b00101010: debugOut <= {registerread_rt_val[`RB], 3'b0,registerread_rt_val[27:0]};
|
80 |
|
|
8'b00101011: debugOut <= {registerread_ru_val[`RB], 3'b0,registerread_ru_val[27:0]};
|
81 |
|
|
8'b00101100: debugOut <= {registerread_regmask_val[`MASKSZ],3'b0,registerread_rd_val[`RB],3'b0,registerread_rs_val[`RB],3'b0,registerread_rt_val[`RB]};
|
82 |
|
|
8'b00101110: debugOut <= registerread_tag_val;
|
83 |
|
|
|
84 |
|
|
// address generator
|
85 |
|
|
//8'b00110000: debugOut <= addrgen_instruction[31:0];
|
86 |
|
|
8'b00110001: debugOut <= addrgen_read_write_address;
|
87 |
|
|
8'b00110011: debugOut <= addrgen_instruction_pointer;
|
88 |
|
|
8'b00110100: debugOut <= {addrgen_stall_next, 3'b0,addrgen_valid};
|
89 |
|
|
8'b00110101: debugOut <= addrgen_result_type;
|
90 |
|
|
8'b00110110: debugOut <= addrgen_write_enable;
|
91 |
|
|
8'b00110111: debugOut <= addrgen_write_data;
|
92 |
|
|
8'b00111000: debugOut <= {addrgen_operand1[`RB], 3'b0,addrgen_operand1[27:0]};
|
93 |
|
|
8'b00111001: debugOut <= {addrgen_operand2[`RB], 3'b0,addrgen_operand2[27:0]};
|
94 |
|
|
8'b00111010: debugOut <= {addrgen_operand3[`RB], 3'b0,addrgen_operand3[27:0]};
|
95 |
|
|
8'b00111011: debugOut <= addrgen_tag_val;
|
96 |
|
|
8'b00111100: debugOut <= {addrgen_regmask_val[`MASKSZ], 12'b0,addrgen_regmask_val[15:0]};
|
97 |
|
|
8'b00111101: debugOut <= addrgen_debug1;
|
98 |
|
|
8'b00111110: debugOut <= addrgen_debug2;
|
99 |
|
|
8'b00111111: debugOut <= addrgen_debug3;
|
100 |
|
|
|
101 |
|
|
// dataread stage
|
102 |
|
|
//8'b01000000: debugOut <= dataread_instruction[31:0];
|
103 |
|
|
8'b01000010: debugOut <= dataread_instruction_pointer;
|
104 |
|
|
8'b01000011: debugOut <= {dataread_ot, dataread_exe_unit, 2'b0,dataread_format, 2'b0,dataread_num_operands, dataread_vector,1'b0,dataread_category};
|
105 |
|
|
8'b01000100: debugOut <= {2'b0,dataread_option_bits, 2'b0,dataread_opj, 1'b0,dataread_opx};
|
106 |
|
|
8'b01000101: debugOut <= {dataread_mask_alternative,dataread_regmask_used};
|
107 |
|
|
8'b01000110: debugOut <= {2'b0,dataread_num_operands, 1'b0,dataread_opr3_used,dataread_opr2_used,dataread_opr1_used};
|
108 |
|
|
8'b01000111: debugOut <= {dataread_im2_bits, 10'b0,dataread_option_bits};
|
109 |
|
|
8'b01001000: debugOut <= {dataread_operand1[`RB], 3'b0,dataread_operand1[27:0]};
|
110 |
|
|
8'b01001001: debugOut <= {dataread_operand2[`RB], 3'b0,dataread_operand2[27:0]};
|
111 |
|
|
8'b01001010: debugOut <= {dataread_operand3[`RB], 3'b0,dataread_operand3[27:0]};
|
112 |
|
|
8'b01001011: debugOut <= {dataread_mask_val[`MASKSZ], 12'b0,dataread_mask_val[15:0]};
|
113 |
|
|
8'b01001100: debugOut <= {2'b0,dataread_opj, 1'b0,dataread_opx, 2'b0,dataread_instruction[`OP1]};
|
114 |
|
|
8'b01001101: debugOut <= dataread_tag_val;
|
115 |
|
|
8'b01001110: debugOut <= {dataread_opr3_from_ram,dataread_opr2_from_ram, 2'b0,dataread_result_type};
|
116 |
|
|
8'b01001111: debugOut <= dataread_debug;
|
117 |
|
|
|
118 |
|
|
// alu
|
119 |
|
|
8'b01010000: debugOut <= bus1_value[31:0];
|
120 |
|
|
8'b01010001: debugOut <= bus1_register_a;
|
121 |
|
|
8'b01010010: debugOut <= {dataread_opx, dataread_exe_unit, 2'b0,inout_write_en,alu_write_en};
|
122 |
|
|
8'b01010011: debugOut <= {bus1_tag, 3'b0,inout_tag, 3'b0,alu_tag};
|
123 |
|
|
8'b01010100: debugOut <= {inout_write_en,alu_write_en, 2'b0, inout_error,alu_error, 2'b0,alu_nojump,alu_jump};
|
124 |
|
|
8'b01010101: debugOut <= alu_jump_pointer;
|
125 |
|
|
8'b01010110: debugOut <= {inout_stall_next,alu_stall_next, 2'b0,inout_stall,alu_stall, 3'b0,dataread_stall_predict, 3'b0,addrgen_stall_next, 3'b0,registerread_stall_predict};
|
126 |
|
|
8'b01010111: debugOut <= {alu_tag, 2'b0,alu_register_a, 3'b0,alu_write_en};
|
127 |
|
|
8'b01011000: debugOut <= alu_result;
|
128 |
|
|
8'b01011001: debugOut <= alu_debug1;
|
129 |
|
|
8'b01011010: debugOut <= alu_debug2;
|
130 |
|
|
8'b01011011: debugOut <= muldiv_debug1;
|
131 |
|
|
8'b01011100: debugOut <= muldiv_debug2;
|
132 |
|
|
8'b01011111: debugOut <= inout_debug;
|
133 |
|
|
|
134 |
|
|
// pipeline synchronization
|
135 |
|
|
8'b01110000: debugOut <= {inout_stall_next,inout_stall,alu_stall_next,alu_stall, 3'b0,dataread_stall_predict, 3'b0,addrgen_stall_next, 3'b0,registerread_stall_predict};
|
136 |
|
|
8'b01110001: debugOut <= {1'b0,alu_jump,alu_nojump,bus1_write_en, 3'b0,dataread_valid, 1'b0,addrgen_write_enable,addrgen_read_enable,addrgen_valid, 3'b0,registerread_valid, 3'b0,decoder_valid, 3'b0,fetch_valid};
|
137 |
|
|
8'b01110010: debugOut <= {bus1_tag, 10'b0,bus1_register_a};
|
138 |
|
|
8'b01111000: debugOut <= {inout_first_error_address, 2'b0,inout_capab_disable_errors, 4'b0,inout_first_error};
|
139 |
|
|
8'b01111111: debugOut <= clock_1; // Test clock frequency. This will count at CLOCK_FREQUENCY / 10^8
|
140 |
|
|
|
141 |
|
|
// data memory read / write
|
142 |
|
|
8'b10000000: debugOut <= addrgen_read_write_address;
|
143 |
|
|
8'b10000001: debugOut <= {addrgen_read_data_size,3'b0,addrgen_read_enable};
|
144 |
|
|
8'b10000010: debugOut <= data_memory_data;
|
145 |
|
|
8'b10000101: debugOut <= addrgen_write_enable;
|
146 |
|
|
8'b10000110: debugOut <= addrgen_write_data[31:0];
|
147 |
|
|
//8'b10000111: debugOut <= addrgen_write_data[63:32];
|
148 |
|
|
8'b10001000: debugOut <= code_memory_debug;
|
149 |
|
|
|
150 |
|
|
default: debugOut <= 32'hFFFFFFFF;
|
151 |
|
|
endcase
|
152 |
|
|
|
153 |
|
|
color_led16 <= 0;
|
154 |
|
|
if (show_error) begin
|
155 |
|
|
// show error code. this overrides the switch selection
|
156 |
|
|
/* 1: alu_error | muldiv_error | inout_error; // unknown instruction
|
157 |
|
|
2: alu_error_parm | muldiv_error_parm | inout_error_parm | call_stack_overflow; // wrong parameter for instruction
|
158 |
|
|
3: dataread_array_error; // array index out of bounds
|
159 |
|
|
4: dataread_read_address_error; // read address violation
|
160 |
|
|
5: dataread_write_address_error; // write address violation
|
161 |
|
|
6: dataread_misaligned_address_error; // misaligned memory address
|
162 |
|
|
*/
|
163 |
|
|
debugOut[31:28] <= 4'b1110; // "E"
|
164 |
|
|
debugOut[27:24] <= inout_first_error;
|
165 |
|
|
debugOut[23:20] <= 0;
|
166 |
|
|
debugOut[19:0] <= inout_first_error_address;
|
167 |
|
|
enable_digits <= 8'b11011111;
|
168 |
|
|
// blink LED, 25% brightness
|
169 |
|
|
color_led16[0] <= clock_counter[1:0] == 0 && clock_counter[24];
|
170 |
|
|
|
171 |
|
|
end else if (switch8) begin
|
172 |
|
|
// look into register file
|
173 |
|
|
debug_reada <= debug_out_select[5:0];
|
174 |
|
|
debugOut <= {registerread_debugport[32],3'b0,registerread_debugport[27:0]};
|
175 |
|
|
end else begin
|
176 |
|
|
debug_reada <= 0;
|
177 |
|
|
end
|
178 |
|
|
end
|
179 |
|
|
|
180 |
|
|
seg7 seg7_inst(clock, debugOut, enable_digits, segment7seg, digit7seg);
|