// MIT License | |
// Copyright (c) [2022] [Yonga Technology Microelectronics R&D] | |
// Permission is hereby granted, free of charge, to any person obtaining a copy | |
// of this software and associated documentation files (the "Software"), to deal | |
// in the Software without restriction, including without limitation the rights | |
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
// copies of the Software, and to permit persons to whom the Software is | |
// furnished to do so, subject to the following conditions: | |
// The above copyright notice and this permission notice shall be included in all | |
// copies or substantial portions of the Software. | |
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
// SOFTWARE. | |
// DESCRIPTION | |
// The yonga_can_controller module manages the operations in CAN peripheral | |
module yonga_can_controller( | |
input wire i_controller_clk, | |
input wire i_controller_rst, | |
input wire i_pulse_gen_synced, | |
input wire i_packetizer_rdy, | |
input wire i_ack_slot, | |
output reg o_packetizer_en, | |
output reg o_pulse_gen_en, | |
input wire i_packetizer_message_bit, | |
input wire i_message_bit, | |
output reg o_message_bit, | |
input wire i_drive_pulse, | |
input wire i_sample_pulse, | |
input wire i_config_enable, | |
input wire i_sys_ctrl_sts_send, | |
output reg [2:0] o_sts_code | |
); | |
parameter STATE_RESET = 0, STATE_SYNC = 1, STATE_CHECK_IDLE = 2, STATE_DRIVE_DATA = 3, STATE_SAMPLE_DATA = 4, STATE_IFS = 5, STATE_ERROR = 6, STATE_EN_PACKETIZER = 7; | |
reg done_tx; | |
reg [2:0] state_reg; | |
reg bit_transmitted; | |
reg [5:0] bitcounter_reg; | |
reg prev_bit_reg; | |
reg [3:0] consecutive_ones_reg; | |
reg [3:0] zeros_reg; | |
reg is_extended, is_standart; | |
reg is_idle; | |
always @(posedge i_controller_clk) begin | |
if(i_controller_rst) begin | |
state_reg <= STATE_RESET; | |
o_packetizer_en <= 1'b0; | |
o_pulse_gen_en <= 1'b0; | |
o_sts_code <= 3'b0; | |
o_message_bit <= 1'b1; | |
done_tx <= 1'b0; | |
bitcounter_reg <= 6'd0; | |
consecutive_ones_reg <= 4'd0; | |
is_standart <= 1'b1; | |
is_extended <= 1'b0; | |
zeros_reg <= 4'd0; | |
prev_bit_reg <= 1'b0; | |
is_idle <= 1'b0; | |
end | |
else begin | |
case(state_reg) | |
STATE_RESET: begin | |
o_sts_code <= 3'b0; | |
o_message_bit <= 1'b1; | |
done_tx <= 1'b0; | |
bitcounter_reg <= 6'd0; | |
is_standart <= 1'b1; | |
is_extended <= 1'b0; | |
if((i_config_enable == 0) && (i_sys_ctrl_sts_send == 1)) begin | |
state_reg <= STATE_SYNC; | |
o_pulse_gen_en <= 1'b1; | |
end | |
end | |
STATE_SYNC: begin | |
if(i_pulse_gen_synced) begin | |
state_reg <= STATE_CHECK_IDLE; | |
end | |
end | |
STATE_CHECK_IDLE: begin | |
o_sts_code <= 3'b0; | |
if(i_sample_pulse) begin | |
if(~is_idle) begin | |
prev_bit_reg <= i_message_bit; | |
if(prev_bit_reg) begin | |
if(i_message_bit) begin | |
consecutive_ones_reg <= consecutive_ones_reg + 1; | |
end | |
else begin | |
consecutive_ones_reg <= 4'd0; | |
end | |
if(consecutive_ones_reg == 4'd9) begin | |
consecutive_ones_reg = 4'd0; | |
state_reg <= STATE_EN_PACKETIZER; | |
is_idle <= 1'b0; | |
end | |
end | |
end | |
else begin | |
state_reg <= STATE_EN_PACKETIZER; | |
is_idle <= 1'b0; | |
end | |
end | |
end | |
STATE_EN_PACKETIZER: begin | |
o_packetizer_en <= 1'b1; | |
if(i_drive_pulse == 1) begin | |
state_reg <= STATE_DRIVE_DATA; | |
end | |
end | |
STATE_DRIVE_DATA: begin | |
if(i_drive_pulse == 1) begin | |
state_reg <= STATE_SAMPLE_DATA; | |
if(bitcounter_reg == 13 && i_packetizer_message_bit == 0) begin | |
is_standart <= 1'b1; | |
is_extended <= 1'b0; | |
end | |
else if(bitcounter_reg == 13 && i_packetizer_message_bit == 1) begin | |
is_standart <= 1'b0; | |
is_extended <= 1'b1; | |
end | |
bit_transmitted <= i_packetizer_message_bit; | |
o_message_bit <= i_packetizer_message_bit; | |
end | |
end | |
STATE_SAMPLE_DATA: begin | |
if(i_sample_pulse == 1) begin | |
bitcounter_reg <= bitcounter_reg + 1; | |
prev_bit_reg <= i_message_bit; | |
if(prev_bit_reg) begin | |
if(i_message_bit) begin | |
consecutive_ones_reg <= consecutive_ones_reg + 1; | |
end | |
else begin | |
consecutive_ones_reg <= 4'd0; | |
end | |
end | |
if(bit_transmitted == i_message_bit) begin | |
if(i_ack_slot) begin | |
o_sts_code <= 3'h3; | |
bitcounter_reg <= 0; | |
o_packetizer_en <= 0; | |
state_reg <= STATE_IFS; | |
end | |
else if(i_packetizer_rdy) begin // EOF flag | |
o_packetizer_en <= 0; | |
bitcounter_reg <= 0; | |
state_reg <= STATE_IFS; | |
end | |
else begin | |
state_reg <= STATE_DRIVE_DATA; | |
end | |
end | |
else begin | |
if(i_ack_slot == 1) begin | |
o_sts_code <= 3'h1; | |
state_reg <= STATE_DRIVE_DATA; | |
end | |
else begin | |
if(is_standart) begin | |
if(bitcounter_reg < 6'd14) begin // Why 14? SOF + 11 bit standart arbitration field + RTR. | |
o_sts_code <= 3'h2; | |
o_packetizer_en <= 0; | |
state_reg <= STATE_CHECK_IDLE; // Sampled data and transmitted data does not match. Arbitration is lost to another node. STANDART FORMAT | |
bitcounter_reg <= 6'd0; | |
end | |
else begin | |
o_sts_code <= 3'h2; | |
o_packetizer_en <= 0; | |
bitcounter_reg <= 6'd0; // Sampled data and data on bus does not match. Bit error occured. Push eror frame to bus. | |
state_reg <= STATE_ERROR; | |
end | |
end | |
if(is_extended) begin | |
if(bitcounter_reg < 6'd34) begin // Why 34? SOF + 32 bit extended arbitration field. | |
o_sts_code <= 3'h2; | |
o_packetizer_en <= 0; | |
state_reg <= STATE_CHECK_IDLE; // Sampled data and transmitted data does not match. Arbitration is lost to another node. EXTENDED FORMAT | |
bitcounter_reg <= 6'd0; | |
end | |
else begin | |
o_sts_code <= 3'h2; | |
o_packetizer_en <= 0; | |
state_reg <= STATE_ERROR; // Sampled data and data on bus does not match. Bit error occured. Push eror frame to bus. | |
bitcounter_reg <= 6'd0; | |
end | |
end | |
end | |
end | |
end | |
end | |
STATE_IFS: begin | |
if(i_drive_pulse == 1'b1) begin | |
if(bitcounter_reg == 6'd2) begin | |
bitcounter_reg <= 6'd0; | |
o_message_bit <= 1; | |
is_idle <= 1'b1; | |
consecutive_ones_reg <= consecutive_ones_reg + 1; | |
done_tx <= 1'b1; | |
state_reg <= STATE_RESET; | |
end | |
else begin | |
state_reg <= STATE_IFS; | |
consecutive_ones_reg <= consecutive_ones_reg + 1; | |
o_message_bit <= 1; | |
bitcounter_reg <= bitcounter_reg + 1; | |
end | |
end | |
end | |
STATE_ERROR: begin | |
state_reg <= STATE_ERROR; | |
// FILL HERE | |
end | |
endcase | |
end | |
end | |
endmodule |