|  | // File name:   ECU.sv | 
|  | // Created:     5/22/2021 | 
|  | // Author:      Zachary Ellis | 
|  | // Version:     1.0  Initial Design Entry | 
|  | // Description: CAN error control unit | 
|  |  | 
|  | module ECU ( | 
|  | input bitstrobe, | 
|  | input tx_strobe, | 
|  | input nRST, | 
|  | input curr_sample, | 
|  | input rx_bitstuff_error, | 
|  | input rx_form_error, | 
|  | input rx_crc_error, | 
|  | input tx_bit_error, | 
|  | input tx_ack_error, | 
|  | input [1:0] rx_code, | 
|  | input [1:0]tx_code, | 
|  | output start_err_tx, | 
|  | output reg [8:0] TEC, | 
|  | output reg [8:0] REC, | 
|  | output [1:0] error_state, | 
|  | output reg [2:0] LEC | 
|  | ); | 
|  |  | 
|  | assign error_state[0] = REC[7] | TEC[7]; | 
|  | assign error_state[1] = TEC[8]; | 
|  |  | 
|  | assign start_err_tx = rx_bitstuff_error | rx_form_error | rx_crc_error | | 
|  | tx_bit_error | tx_ack_error; | 
|  |  | 
|  | wire [4:0] error_vec = {rx_bitstuff_error, rx_form_error, rx_crc_error, | 
|  | tx_bit_error, tx_ack_error}; | 
|  |  | 
|  | always @(posedge tx_strobe, negedge nRST) begin | 
|  | if(nRST == 0) LEC <= '0; | 
|  | else begin | 
|  | casez(error_vec) | 
|  | 5'b00001: LEC <= 3'd1; | 
|  | 5'b00010: LEC <= 3'd2; | 
|  | 5'b00100: LEC <= 3'd3; | 
|  | 5'b01?00: LEC <= 3'd4; //weird ACK rules I may have interpreted backwards but function is not impeded | 
|  | 5'b10000: LEC <= 3'd5; | 
|  | endcase | 
|  | end | 
|  | end | 
|  |  | 
|  | reg [8:0] next_REC; | 
|  | wire idle_period, long_idle; | 
|  |  | 
|  | always_ff @(posedge bitstrobe, negedge nRST) begin | 
|  | if(nRST == 0) REC <= 0; | 
|  | else REC <= next_REC; | 
|  | end | 
|  |  | 
|  | always_comb begin | 
|  | next_REC = REC; | 
|  | case(rx_code) | 
|  | 2'b00: next_REC = REC; | 
|  | 2'b01: next_REC = REC + 1; | 
|  | 2'b10: next_REC = REC + 8; | 
|  | 2'b11: begin | 
|  | if(REC[7]) next_REC = 9'd120; | 
|  | else if(|REC) next_REC = REC - 1; | 
|  | end | 
|  | endcase | 
|  | if(error_state[1] && long_idle) next_REC = 0; | 
|  | end | 
|  |  | 
|  | reg [8:0] next_TEC; | 
|  |  | 
|  | always_ff @(posedge tx_strobe, negedge nRST) begin | 
|  | if(nRST == 0) TEC <= 0; | 
|  | else TEC <= next_TEC; | 
|  | end | 
|  |  | 
|  | always_comb begin | 
|  | next_TEC = TEC; | 
|  | case(tx_code) | 
|  | 2'b00: next_TEC = TEC; | 
|  | 2'b01: next_TEC = TEC + 1; | 
|  | 2'b10: next_TEC = TEC + 8; | 
|  | 2'b11: if(|TEC) next_TEC = TEC - 1; | 
|  | endcase | 
|  | if(TEC[8]) begin | 
|  | next_TEC = 9'b100000000; | 
|  | if(long_idle) next_TEC = 0; | 
|  | end | 
|  | end | 
|  |  | 
|  | flex_counter #( | 
|  | .NUM_CNT_BITS(4) | 
|  | ) | 
|  | U1 ( | 
|  | .clk(bitstrobe), | 
|  | .n_rst(nRST), | 
|  | .clear(curr_sample), | 
|  | .count_enable(1'b1), | 
|  | .rollover_val(4'd11), | 
|  | .count_out(), | 
|  | .rollover_flag(idle_period) | 
|  | ); | 
|  |  | 
|  | flex_counter #( | 
|  | .NUM_CNT_BITS(8) | 
|  | ) | 
|  | U2 ( | 
|  | .clk(idle_period), | 
|  | .n_rst(nRST), | 
|  | .clear(curr_sample), | 
|  | .count_enable(1'b1), | 
|  | .rollover_val(11'd128), | 
|  | .count_out(), | 
|  | .rollover_flag(long_idle) | 
|  | ); | 
|  |  | 
|  | endmodule |