使用FPGA+SJA 1000芯片实现CAN通信。核心思路是对集成CAN协议的芯片尽心配置,来进行CAN通信。核心顶层代码:
//-- Company:
//-- Engineer:
//--
//-- Create Date: 11:18:25 12/01/2021
//-- Design Name:
//-- Module Name: con_port - Behavioral
//-- Project Name:
//-- Target Devices:
//-- Tool versions:
//-- Description: peliCAN
//-- Dependencies:
//-- -- Revision date author description
//-- v1.0 12/01/2021 HLC File Created
// ???sja1000???????? FPGA up?????sja1000 up?????????????????
//2020?12?26?14:43:01
//???????????????????????????????
//??????????????
//2021?1?14?11:17:04 ??????????????
module can_port (
input clk_in ,//clk==40m
input reset ,
input re_config ,//????? ????????????????sja1000
input can_auto_reset ,//CAN????? 5s?????????????sja1000
/*input [7:0] CAN_ID0_tx ,//ID1-4???????ID?
input [7:0] CAN_ID1_tx ,//ID0????(frame information)
input [7:0] CAN_ID2_tx ,
input [7:0] CAN_ID3_tx ,//EFF
input [7:0] CAN_ID4_tx ,//EFF
input [7:0] CAN_DATA1_tx ,//?????8????
input [7:0] CAN_DATA2_tx ,
input [7:0] CAN_DATA3_tx ,
input [7:0] CAN_DATA4_tx ,
input [7:0] CAN_DATA5_tx ,
input [7:0] CAN_DATA6_tx ,
input [7:0] CAN_DATA7_tx ,
input [7:0] CAN_DATA8_tx ,*/
output reg[7:0]CAN_ID0_rx ,//ID1-4???????ID?
output reg[7:0]CAN_ID1_rx ,//ID0????(frame information)
output reg[7:0]CAN_ID2_rx ,
output reg[7:0]CAN_ID3_rx ,//EFF
output reg[7:0]CAN_ID4_rx ,//EFF
output reg[7:0]CAN_DATA1_rx ,//????8????
output reg[7:0]CAN_DATA2_rx ,
output reg[7:0]CAN_DATA3_rx ,
output reg[7:0]CAN_DATA4_rx ,
output reg[7:0]CAN_DATA5_rx ,
output reg[7:0]CAN_DATA6_rx ,
output reg[7:0]CAN_DATA7_rx ,
output reg[7:0]CAN_DATA8_rx ,
//ATTENTION! The real CAN_ID received, is equal to
//{3'b000, CAN_ID1_rx, CAN_ID2_rx, CAN_ID3_rx, CAN_ID4_rx[7:3]};
//which seems like right shift 3 bits.
input CAN_DATA_SEND_EN ,//?????? ???????????
output reg CAN_DATA_SEND_DONE ,//???????? ?????????????
output reg CAN_DATA_RECV_DONE ,//???????? ?????????CAN_DATA_rx???
output reg DATA_RECEIVE_DO ,//????????????????
output CAN_ALE ,//??sja1000?????
output CAN_WR ,//??sja1000?????
output CAN_RD ,//??sja1000?????
output CAN_CS ,//??sja1000?????
output reg CAN_RST ,//??sja1000?????
// CAN_clk_in ,//??sja1000?????
inout [7:0] DATA_CAN ,//??sja1000???ad??
output en //?????? DATA_CAN????SJA1000??????? en?????????
);
//for watching
(*KEEP = "TRUE"*) reg[7:0]tmp_CAN_ID0_rx;
(*KEEP = "TRUE"*) reg[7:0]tmp_CAN_ID1_rx;
(*KEEP = "TRUE"*) reg[7:0]tmp_CAN_ID2_rx;
(*KEEP = "TRUE"*) reg[7:0]tmp_CAN_ID3_rx;
(*KEEP = "TRUE"*) reg[7:0]tmp_CAN_ID4_rx;
(*KEEP = "TRUE"*) reg[7:0]tmp_CAN_DATA1_rx;
(*KEEP = "TRUE"*) reg[7:0]tmp_CAN_DATA2_rx;
(*KEEP = "TRUE"*) reg[7:0]tmp_CAN_DATA3_rx;
(*KEEP = "TRUE"*) reg[7:0]tmp_CAN_DATA4_rx;
(*KEEP = "TRUE"*) reg[7:0]tmp_CAN_DATA5_rx;
(*KEEP = "TRUE"*) reg[7:0]tmp_CAN_DATA6_rx;
(*KEEP = "TRUE"*) reg[7:0]tmp_CAN_DATA7_rx;
(*KEEP = "TRUE"*) reg[7:0]tmp_CAN_DATA8_rx;
always @ (posedge clk_in or posedge reset) begin
if (reset) begin
tmp_CAN_ID0_rx <= 8'h00;
tmp_CAN_ID1_rx <= 8'h00;
tmp_CAN_ID2_rx <= 8'h00;
tmp_CAN_ID3_rx <= 8'h00;
tmp_CAN_ID4_rx <= 8'h00;
tmp_CAN_DATA1_rx <= 8'h00;
tmp_CAN_DATA2_rx <= 8'h00;
tmp_CAN_DATA3_rx <= 8'h00;
tmp_CAN_DATA4_rx <= 8'h00;
tmp_CAN_DATA5_rx <= 8'h00;
tmp_CAN_DATA6_rx <= 8'h00;
tmp_CAN_DATA7_rx <= 8'h00;
tmp_CAN_DATA8_rx <= 8'h00;
end
else if (DATA_RECEIVE_DO) begin
tmp_CAN_ID0_rx <= CAN_ID0_rx;
tmp_CAN_ID1_rx <= CAN_ID1_rx;
tmp_CAN_ID2_rx <= CAN_ID2_rx;
tmp_CAN_ID3_rx <= CAN_ID3_rx;
tmp_CAN_ID4_rx <= CAN_ID4_rx;
tmp_CAN_DATA1_rx <= CAN_DATA1_rx;
tmp_CAN_DATA2_rx <= CAN_DATA2_rx;
tmp_CAN_DATA3_rx <= CAN_DATA3_rx;
tmp_CAN_DATA4_rx <= CAN_DATA4_rx;
tmp_CAN_DATA5_rx <= CAN_DATA5_rx;
tmp_CAN_DATA6_rx <= CAN_DATA6_rx;
tmp_CAN_DATA7_rx <= CAN_DATA7_rx;
tmp_CAN_DATA8_rx <= CAN_DATA8_rx;
end
else begin
tmp_CAN_ID0_rx <= tmp_CAN_ID0_rx ;
tmp_CAN_ID1_rx <= tmp_CAN_ID1_rx ;
tmp_CAN_ID2_rx <= tmp_CAN_ID2_rx ;
tmp_CAN_ID3_rx <= tmp_CAN_ID3_rx ;
tmp_CAN_ID4_rx <= tmp_CAN_ID4_rx ;
tmp_CAN_DATA1_rx <= tmp_CAN_DATA1_rx ;
tmp_CAN_DATA2_rx <= tmp_CAN_DATA2_rx ;
tmp_CAN_DATA3_rx <= tmp_CAN_DATA3_rx ;
tmp_CAN_DATA4_rx <= tmp_CAN_DATA4_rx ;
tmp_CAN_DATA5_rx <= tmp_CAN_DATA5_rx ;
tmp_CAN_DATA6_rx <= tmp_CAN_DATA6_rx ;
tmp_CAN_DATA7_rx <= tmp_CAN_DATA7_rx ;
tmp_CAN_DATA8_rx <= tmp_CAN_DATA8_rx ;
end
end
//===================================================================================
//??ID???????? at 2021?1?13?14:35:51
//SJA1000T????29??ID28-ID0????ID????ID??3bit?
//?CAN???????ID?????????????3bit??????? ID_test ??
//CAN?????ID??SJA1000T????ID???3bit?????ID????3bit??
//real_recv_id = {3'b000, CAN_ID1_rx, CAN_ID2_rx, CAN_ID3_rx, CAN_ID4_rx[7:3]};
//====================================================================================
reg [31:0] real_recv_id;
//wire real_recv_id = CAN_DATA_RECV_DONE ? {3'b000, CAN_ID1_rx, CAN_ID2_rx, CAN_ID3_rx, CAN_ID4_rx[7:3]} : 32'b0;
always @ (posedge clk_in or posedge reset) begin
if (reset)
real_recv_id <= 32'b0;
else if (CAN_DATA_RECV_DONE)
real_recv_id <= {3'b000, CAN_ID1_rx, CAN_ID2_rx, CAN_ID3_rx, CAN_ID4_rx[7:3]};
else
real_recv_id <= real_recv_id;
end
//?????????????IO banks??????????input???????
//???????????????
//?????????
parameter ID_test = 32'h0C080C00; //ID_test[31:0];
parameter CAN_ID0_tx = 8'b1000_1000;//{FF, RTR, 0, 0, DLC3, DLC2, DLC1, DLC0};
parameter CAN_ID1_tx = ID_test[28:21];
parameter CAN_ID2_tx = ID_test[20:13];
parameter CAN_ID3_tx = ID_test[12:05];
parameter CAN_ID4_tx = {ID_test[4:0], 3'b000};//this seems like left shift 3 bits.
parameter CAN_DATA1_tx = 8'h90; //??DYT??????3547200ms, ?'h8A90
parameter CAN_DATA2_tx = 8'h8A; //????????????????
parameter CAN_DATA3_tx = 8'h06; //??'h90_8A_00_00_00_00_00_00
parameter CAN_DATA4_tx = 8'h05; //????????CAN_DATA?????00???
parameter CAN_DATA5_tx = 8'h04;
parameter CAN_DATA6_tx = 8'h03;
parameter CAN_DATA7_tx = 8'h02;
parameter CAN_DATA8_tx = 8'h01;
parameter INIT_RESET =5'b00001,
INIT =5'b00010,
IDLE =5'b00100,
DATA_READ =5'b01000,
DATA_SEND =5'b10000;
reg [4:0] state_c,state_n;
//********************************************
reg read_act_path;
reg read_write0 ;
reg [7:0] read_addr_path;
reg [7:0] read_data_path;
reg [3:0] read_state ;
reg [3:0] read_cnt ;
reg read_finish ;//********************************************
//**************************************************************************************
reg act ;
reg write0 ;
wire recv_done_path ;
wire send_done_path ;
reg [7:0] need_addr_path ;
wire[7:0] recv_data_path ;
reg [7:0] s_data_path ;
//new adding at 2021?1?14?11:18:01
(*KEEP = "TRUE"*) reg [3:0] tx_DLC; //tx data length counter
(*KEEP = "TRUE"*) reg [3:0] rx_DLC; //rx data length counter
always @ (posedge clk_in or posedge reset) begin
if (reset)
tx_DLC <= 4'h0;
else if (state_n == DATA_SEND) begin
tx_DLC <= ((CAN_ID0_tx[3] << 3) + (CAN_ID0_tx[2] << 2) + (CAN_ID0_tx[1] << 1) + CAN_ID0_tx[0]);
end
else
tx_DLC <= 4'h0;
end
always @ (posedge clk_in or posedge reset) begin
if (reset)
rx_DLC <= 4'h0;
else if ((state_n == DATA_READ)) begin
if ((read_cnt == 4'd1) && recv_done_path)
rx_DLC <= ((CAN_ID0_rx[3] << 3) + (CAN_ID0_rx[2] << 2) + (CAN_ID0_rx[1] << 1) + CAN_ID0_rx[0]);
else
rx_DLC <= rx_DLC;
end
else
rx_DLC <= 4'h0;
end
//========================================================
//for watching
//========================================================
(*KEEP = "TRUE"*) reg[7:0]CAN_ID_rx_r[4:0] ;
(*KEEP = "TRUE"*) reg[7:0]CAN_DATA_r[7:0];
reg [7:0] init_addr[13:0];
reg [7:0] init_data[13:0];
reg [7:0] rx_tx_addr[12:0]; //SFF
reg [7:0] tx_data[10:0] ;//SFF
//reg [7:0] rx_tx_addr[14:0];//EFF
//reg [7:0] tx_data[12:0];//EFF
(*KEEP = "TRUE"*) reg [7:0] CAN_RXERR_rx,CAN_TXERR_rx;
reg send_flag ;
//******************************************
reg [15:0] cnt ;
reg init_restf ;//initialize reset finish ???????
//****************************************
wire need_reset;
reg [31:0] reset_cnt;
//***************************************************
reg [3:0] init_cnt;
reg init_act_path;
reg init_write0 ;
reg init_finish ;
reg [7:0] init_addr_path;
reg [7:0] init_data_path;
reg [2:0] init_state ;
//******************************************
reg idle_act_path;
reg idle_write0 ;
reg [7:0] idle_addr_path;
(*KEEP = "TRUE"*) reg [7:0] idle_sr_data;
(*KEEP = "TRUE"*) reg [2:0] idle_state ;
reg need_read ;
reg need_send ;
//***************************************************
reg send_act_path ;
reg send_write0 ;
(*KEEP = "TRUE"*) reg [7:0] send_addr_path;
(*KEEP = "TRUE"*) reg [7:0] send_data_path;
reg [3:0] send_state ;
reg [3:0] send_cnt ;
reg send_finish ;
reg idle_sr_data3;
reg idle_sr_data5;
(*KEEP = "TRUE"*) wire sr3_AND_sr5;
assign sr3_AND_sr5 = idle_sr_data3 && idle_sr_data5;
always @ (posedge clk_in) begin
if (reset)
idle_sr_data5 <= 1'b0;
else
idle_sr_data5 <= idle_sr_data[5];
end
always @ (posedge clk_in) begin
if (reset)
idle_sr_data3 <= 1'b0;
else
idle_sr_data3 <= idle_sr_data[3];
end
//********************** ???????? ??????????sja1000***************************************************************
always @(posedge clk_in) begin //?14?addr
if (reset) begin
init_addr[0 ]<=8'h00 ; //MOD ????SJA1000??????
init_addr[1 ]<=8'h00 ; //TIMER0
init_addr[2 ]<=8'h00 ; //TIMER1
init_addr[3 ]<=8'h00 ; //OCT or OCR Output Control Register
init_addr[4 ]<=8'h00 ; //CDR Clock Driver Register
init_addr[5 ]<=8'h00 ; //ACRN0 Acceptance Code Registers
init_addr[6 ]<=8'h00 ; //ACRN1
init_addr[7 ]<=8'h00 ; //ACRN2
init_addr[8 ]<=8'h00 ; //ACRN3
init_addr[9 ]<=8'h00 ; //AMR0 Acceptance Mask Registers
init_addr[10]<=8'h00 ; //AMR1
init_addr[11]<=8'h00 ; //AMR2
init_addr[12]<=8'h00 ; //AMR3
init_addr[13]<=8'h00 ; //MOD
end
else begin
init_addr[0 ]<=8'h00 ; //MOD ????SJA1000??????
init_addr[1 ]<=8'h06 ; //TIMER0
init_addr[2 ]<=8'h07 ; //TIMER1
init_addr[3 ]<=8'h08 ; //OCT or OCR Output Control Register
init_addr[4 ]<=8'h1F ; //CDR Clock Driver Register
init_addr[5 ]<=8'h10 ; //ACRN0 Acceptance Code Registers
init_addr[6 ]<=8'h11 ; //ACRN1
init_addr[7 ]<=8'h12 ; //ACRN2
init_addr[8 ]<=8'h13 ; //ACRN3
init_addr[9 ]<=8'h14 ; //AMR0 Acceptance Mask Registers
init_addr[10]<=8'h15 ; //AMR1
init_addr[11]<=8'h16 ; //AMR2
init_addr[12]<=8'h17 ; //AMR3
init_addr[13]<=8'h00 ; //MOD
end
end
always @(posedge clk_in) begin //?14?data
if (reset) begin
init_data[0 ]<=8'h00 ; //reset_model
init_data[1 ]<=8'h00 ; // bps1/2 clk_in=40mhz
init_data[2 ]<=8'h5c ; // cycle da20 500kbps
//init_data[1] <= 8'h00; //bps Fosc = 16MHz
//init_data[2] <= 8'h00; //800kbps //??T_seg1 = 7 ? T_seg2 = 2??
init_data[3]<=8'h00; // oct output 8'h0001_1010
init_data[4 ]<=8'h00; // CDR.7=1 pelican model CDR.3=1 close out_clk_in
//init_data[5 ]<=8'h04 ; // receive only ID=04 frame
//??? receive only ID=04 frame
init_data[5 ]<=8'h00 ;
init_data[6 ]<=8'h00 ; //???????????? ?sja1000?ID?? ????sja1000??
init_data[7 ]<=8'h00 ; //???????????? ?sja1000?ID?? ????sja1000??
init_data[8 ]<=8'h00 ; //???????????? ?sja1000?ID?? ????sja1000??
//init_data[9 ]<=8'h03 ; //???????????? ?sja1000?ID?? ????sja1000??
init_data[9 ]<=8'h00 ; //???????????? ?sja1000?ID?? ????sja1000??
init_data[10]<=8'h00 ; //???????????? ?sja1000?ID?? ????sja1000??
init_data[11]<=8'h00 ; //???????????? ?sja1000?ID?? ????sja1000??
init_data[12]<=8'h00 ; //???????????? ?sja1000?ID?? ????sja1000??
init_data[13]<=8'h00 ; // normal model
end
else begin
init_data[0 ]<=8'h09 ; //reset_model
init_data[1 ]<=8'h00 ; // bps1/2 clk_in=40mhz
init_data[2 ]<=8'h5c ; // cycle da20 500kbps
//init_data[1] <= 8'h00; //bps Fosc = 16MHz
//init_data[2] <= 8'h16; //800kbps //??T_seg1 = 7 ? T_seg2 = 2??
init_data[3 ]<=8'h1A ; // oct output 8'h0001_1010
init_data[4 ]<=8'hC8 ; // CDR.7=1 pelican model CDR.3=1 close out_clk_in
//init_data[5 ]<=8'h04 ; // receive only ID=04 frame
//??? receive only ID=04 frame
init_data[5 ]<=8'h04 ; // receive ID=04 frame ID 10:3
init_data[6 ]<=8'hE0 ; //receive ID=04 frame ID 2:0 ID?0000_0100_111 RTR?0
init_data[7 ]<=8'h00 ; //???????????? ?sja1000?ID?? ????sja1000??
init_data[8 ]<=8'h00 ; //???????????? ?sja1000?ID?? ????sja1000??
//init_data[9 ]<=8'h03 ; //???????????? ?sja1000?ID?? ????sja1000??
init_data[9 ]<=8'h00 ; //???????????? ?sja1000?ID?? ????sja1000??
init_data[10]<=8'h1F ; //???????????? ?sja1000?ID?? ????sja1000??
init_data[11]<=8'hFF ; //???????????? ?sja1000?ID?? ????sja1000??
init_data[12]<=8'hFF ; //???????????? ?sja1000?ID?? ????sja1000??
init_data[13]<=8'h08 ; // normal model
end
end
//
always @(posedge clk_in) begin //??13?addr
//14-26 //??14 15bit(?8'h0E, 8'h0F)?rx?tx?error counter??op mode??????
//?????(EFF)?????rx_tx_addr???8'h1C
if (reset) begin
rx_tx_addr[0 ]<=8'h00;
rx_tx_addr[1 ]<=8'h00;
rx_tx_addr[2 ]<=8'h00;
rx_tx_addr[3 ]<=8'h00;
rx_tx_addr[4 ]<=8'h00;
rx_tx_addr[5 ]<=8'h00;
rx_tx_addr[6 ]<=8'h00;
rx_tx_addr[7 ]<=8'h00;
rx_tx_addr[8 ]<=8'h00;
rx_tx_addr[9 ]<=8'h00;
rx_tx_addr[10]<=8'h00;
rx_tx_addr[11]<=8'h00;
rx_tx_addr[12]<=8'h00;
rx_tx_addr[13]<=8'h00;
rx_tx_addr[14]<=8'h00;
end
else begin
rx_tx_addr[0 ]<=8'h10 ;
rx_tx_addr[1 ]<=8'h11 ;
rx_tx_addr[2 ]<=8'h12 ;
rx_tx_addr[3 ]<=8'h13 ;
rx_tx_addr[4 ]<=8'h14 ;
rx_tx_addr[5 ]<=8'h15 ;
rx_tx_addr[6 ]<=8'h16 ;
rx_tx_addr[7 ]<=8'h17 ;
rx_tx_addr[8 ]<=8'h18 ;
rx_tx_addr[9 ]<=8'h19 ;
rx_tx_addr[10]<=8'h1A ;
rx_tx_addr[11]<=8'h1B ;
rx_tx_addr[12]<=8'h1C ;
rx_tx_addr[13]<=8'h0E ;
rx_tx_addr[14]<=8'h0F ;
//rx_tx_addr[11]<=8'h0E ;
//rx_tx_addr[12]<=8'h0F ;
end
end
//???EFF?????????
always @(posedge clk_in) begin
if (reset)
send_flag <= 1'b0;
else if(CAN_DATA_SEND_DONE)
send_flag <=1'b0;
else if(CAN_DATA_SEND_EN) begin
send_flag <= 1'b1;
//SFF
tx_data[0 ] <= CAN_ID0_tx ;
tx_data[1 ] <= CAN_ID1_tx ;
tx_data[2 ] <= CAN_ID2_tx ;
tx_data[3 ] <= CAN_DATA1_tx ;
tx_data[4 ] <= CAN_DATA2_tx ;
tx_data[5 ] <= CAN_DATA3_tx ;
tx_data[6 ] <= CAN_DATA4_tx ;
tx_data[7 ] <= CAN_DATA5_tx ;
tx_data[8 ] <= CAN_DATA6_tx ;
tx_data[9 ] <= CAN_DATA7_tx ;
tx_data[10] <= CAN_DATA8_tx ;
//EFF
/*tx_data[0 ] <= CAN_ID0_tx ;
tx_data[1 ] <= CAN_ID1_tx ;
tx_data[2 ] <= CAN_ID2_tx ;
tx_data[3 ] <= CAN_ID3_tx ;
tx_data[4 ] <= CAN_ID4_tx ;
tx_data[5 ] <= CAN_DATA1_tx ;
tx_data[6 ] <= CAN_DATA2_tx ;
tx_data[7 ] <= CAN_DATA3_tx ;
tx_data[8 ] <= CAN_DATA4_tx ;
tx_data[9 ] <= CAN_DATA5_tx ;
tx_data[10] <= CAN_DATA6_tx ;
tx_data[11] <= CAN_DATA7_tx ;
tx_data[12] <= CAN_DATA8_tx ;*/
end
else
send_flag <= send_flag;
end
(*KEEP = "TRUE"*) reg send_flag_r;
(*KEEP = "TRUE"*) wire pos = (send_flag && (!send_flag_r)) ; //for watching
always @ (posedge clk_in) begin
if (reset)
send_flag_r <= 1'b0;
else
send_flag_r <= send_flag;
end
//ALL state //?????
//parameter INIT_RESET =5'b00001,
// INIT =5'b00010,
// IDLE =5'b00100,
// DATA_READ =5'b01000,
// DATA_SEND =5'b10000;
//reg [4:0] state_c,state_n;
always @(posedge clk_in ) begin
if((reset)||(!init_restf))
begin
state_c<=INIT_RESET;
end
else
begin
state_c<=state_n;
end
end
always @(*) begin
if((reset)||(!init_restf))
state_n<=INIT_RESET;
else
case(state_c)
//init_restf ?????????FPGA up?? SJA1000???up
//init_restf means initialize reset finished
INIT_RESET: if(init_restf)
state_n<=INIT;
else
state_n<=INIT_RESET;
//?????????(initialize)
INIT : if(init_finish)
state_n<=IDLE;
else
state_n<=INIT;
IDLE :if(need_reset)
state_n<=INIT_RESET;
else if(need_read)
state_n<=DATA_READ;
else
if(need_send)
state_n<=DATA_SEND;
else
state_n<=IDLE;
DATA_READ : if(read_finish)//????need_reset
state_n<=IDLE;
else
state_n<=DATA_READ;
DATA_SEND :if(need_reset)
state_n<=INIT_RESET;
else if(send_finish)
state_n<=IDLE;
else
state_n<=DATA_SEND;
default : state_n<=INIT_RESET;
endcase
end
//*************************************************state=INIT_RESET**********************************
//*******************************???????????sja1000????***************************************************************************
parameter WAIT_FOR_SJA_UP = 16'd20000; //400
parameter AFTER_WAIT = 16'd30000; //420
always @(posedge clk_in ) begin
if(reset||(re_config))
begin
init_restf<=1'b0;
//cnt <=10'd0;
cnt <= 16'd0;
CAN_RST <=1'b0;
end
//????state_n????????state_c?????????????
else if (state_n == INIT_RESET) begin
if (cnt < WAIT_FOR_SJA_UP) begin
cnt<=cnt+1'b1;
CAN_RST<=1'b0;
init_restf<=1'b0;
end
else if ((cnt >= WAIT_FOR_SJA_UP ) && (cnt < AFTER_WAIT)) begin
cnt<=cnt+1'b1;
CAN_RST<=1'b1;
init_restf<=1'b0;
end
else begin
cnt <= cnt;
CAN_RST<=1'b1;
init_restf<=1'b1;
end
end
else begin
cnt <= cnt;
CAN_RST<=1'b1;
init_restf<=1'b1;
end
end
//***********************************************************************************************************
//??5s????sja1000??? or sja1000??????????90?
//or ???????? ?????sja1000
assign need_reset = (
(reset_cnt>=32'd200000000) || //?????????????????
(idle_sr_data[7]) || //SR.7 == 0 ?? bus on
(CAN_RXERR_rx>=8'd90) ||
(CAN_TXERR_rx>=8'd90) ); // ? 1'b1 : 1'b0;
always @(posedge clk_in ) begin
if(reset||(re_config)||(!init_restf))
reset_cnt<=32'd0;
else if((state_n==DATA_READ)||(state_n==INIT_RESET))
reset_cnt<=32'd0;
else if(can_auto_reset)
reset_cnt<=reset_cnt+1'b1;
else
reset_cnt<=32'd0;
end
//*************************************************************************************************************
//init_state initial all sja1000 registers
//*************************************************************************************************************
always @(posedge clk_in ) begin
if((reset)||(!init_restf))
begin
init_act_path <=1'b0;
init_state <=3'b001;
init_cnt <=4'd0;
init_write0 <=1'b0;
init_finish <=1'b0;
init_addr_path<=8'h00;
init_data_path<=8'h00;
end
else case(init_state)
3'b001: if(state_n==INIT)
begin
init_state<=3'b010;
init_finish<=1'b0;
end
else
begin
init_cnt<=4'd0;
init_state<=3'b001;
init_act_path<=1'b0;
init_write0<=1'b0 ;
init_finish<=1'b0;
end
3'b010: if(send_done_path)
begin
init_act_path<=1'b0;
init_cnt<=init_cnt+1'b1;
init_state<=3'b100;
init_write0<=1'b0;
end
else
begin
//? rs_port ??act ? write0 ???????????
init_act_path<=1'b1;
init_addr_path<=init_addr[init_cnt];
init_data_path<=init_data[init_cnt];
init_write0<=1'b1;
init_state<=3'b010;
end
3'b100:if(init_cnt<14)
begin
init_finish<=1'b0;
init_state<=3'b010;
end
else
begin
init_state<=3'b001;
init_finish<=1'b1;
end
default : begin
init_cnt<=4'd0;
init_state<=3'b001;
init_act_path<=1'b0;
init_write0<=1'b0 ;
init_finish<=1'b0;
end
endcase
end
//*************************************************************************************************************
//IDLE state read sr_register and judge read or write
//*************************************************************************************************************
always @(posedge clk_in ) begin
if((reset)||(!init_restf))
begin
idle_act_path<=1'b0 ;
idle_state <=3'b001;
need_read <=1'b0 ;
need_send <=1'b0 ;
idle_write0 <=1'b0 ;
idle_sr_data <=8'h00 ;
end
else case(idle_state)
3'b001: if(state_n==IDLE)//???idle???????SR
begin
idle_state<=3'b010;
idle_act_path<=1'b1;//act=1,write0=0 means read
idle_write0<=1'b0 ;
idle_addr_path<=8'h02;
idle_sr_data <=8'h00 ;
need_read<=1'b0;
need_send<=1'b0;
end
else
begin
idle_state<=3'b001;
idle_act_path<=1'b0;
idle_write0<=1'b0 ;
idle_addr_path<=8'h02;
need_read<=1'b0;
need_send<=1'b0;
end
3'b010: if(recv_done_path)
begin
idle_act_path<=1'b0;
idle_state<=3'b100;
idle_write0<=1'b0;
idle_sr_data<=recv_data_path;
end
else
begin
idle_act_path<=1'b1;
idle_write0<=1'b0;
idle_state<=3'b010;
idle_addr_path<=8'h02;
end
//judge
3'b100: if(idle_sr_data[0])
//SR.0 == 1 means receive buffer is full
begin
need_read<=1'b1;
need_send<=1'b0;
idle_state<=3'b001;
end
else if({idle_sr_data[5],idle_sr_data[4],idle_sr_data[2],send_flag}==4'b0011)
//??????????????
//SR.5 == 1 means transmitting a message, 0 is IDLE
//SR.4 == 1 means receiving a message, 0 is IDLE
//SR.2 == 1 means note that the CPU may write a message into the transmit buffer
begin
need_read<=1'b0;
need_send<=1'b1;
idle_state<=3'b001;
end
else
begin
need_read<=1'b0;
need_send<=1'b0;
idle_state<=3'b001;
end
default : idle_state<=3'b001;
endcase
end
//******************************************************************************************************************************************
//*************************************************************************************************************
//DATA_READ state do read and clear fifo
//*************************************************************************************************************
//**************************************************************
always @(posedge clk_in ) begin
if((reset)||(!init_restf))
begin
read_act_path<=1'b0;
read_state <=3'b001;
read_write0 <=1'b0 ;
CAN_DATA_RECV_DONE<=1'b0;
read_finish <=1'b0 ;
read_cnt <=4'd0;
//read_data_path<=8'h04; //clear receive buffer
CAN_RXERR_rx<=8'h00;
CAN_TXERR_rx<=8'h00;
DATA_RECEIVE_DO<=1'b0;
read_addr_path <= 8'h00;
read_data_path <= 8'h00;
end
else case(read_state)
3'b001: if(state_n==DATA_READ)begin
read_state<=3'b010;
read_act_path<=1'b1;
read_write0<=1'b0 ;
read_addr_path<=rx_tx_addr[read_cnt];
CAN_DATA_RECV_DONE<=1'b0;
read_finish <=1'b0 ;
end
else begin
read_state<=3'b001;
read_act_path<=1'b0;
read_write0<=1'b0 ;
read_addr_path<=rx_tx_addr[read_cnt];
read_data_path<=8'h00;//new adding
read_cnt <=4'd0;
CAN_DATA_RECV_DONE<=1'b0;
read_finish <=1'b0 ;
end
3'b010: if(recv_done_path)
begin
read_act_path<=1'b0;
read_state<=3'b100;
read_write0<=1'b0;
read_cnt <= read_cnt + 1'b1;//????1
end
else
begin
read_act_path<=1'b1;
read_write0<=1'b0;
read_state<=3'b010;
end
3'b100: //if (read_cnt < 15)
if (read_cnt < (rx_DLC + 6)) begin //rx_DLC + 6 ?????14
case (rx_DLC)
'd0 : begin
case (read_cnt)
'd1 : begin CAN_ID0_rx <= recv_data_path; end
'd2 : begin CAN_ID1_rx <= recv_data_path; end
'd3 : begin CAN_ID2_rx <= recv_data_path; end
'd4 : begin CAN_ID3_rx <= recv_data_path; end
'd5 : begin CAN_ID4_rx <= recv_data_path; DATA_RECEIVE_DO <= 1'b1; read_cnt<=4'd13;end
default: read_state<=3'b001;
endcase
end
'd1: begin
case (read_cnt)
'd1 : begin CAN_ID0_rx <= recv_data_path; end
'd2 : begin CAN_ID1_rx <= recv_data_path; end
'd3 : begin CAN_ID2_rx <= recv_data_path; end
'd4 : begin CAN_ID3_rx <= recv_data_path; end
'd5 : begin CAN_ID4_rx <= recv_data_path; end
'd6 : begin CAN_DATA1_rx <= recv_data_path; DATA_RECEIVE_DO <= 1'b1;read_cnt<=4'd13;end
default:read_state<=3'b001;
endcase
end
'd2: begin
case (read_cnt)
'd1 : begin CAN_ID0_rx <= recv_data_path; end
'd2 : begin CAN_ID1_rx <= recv_data_path; end
'd3 : begin CAN_ID2_rx <= recv_data_path; end
'd4 : begin CAN_ID3_rx <= recv_data_path; end
'd5 : begin CAN_ID4_rx <= recv_data_path; end
'd6 : begin CAN_DATA1_rx <= recv_data_path; end
'd7 : begin CAN_DATA2_rx <= recv_data_path; DATA_RECEIVE_DO <= 1'b1; read_cnt<=4'd13;end
default:read_state<=3'b001;
endcase
end
'd3 : begin
case (read_cnt)
'd1 : begin CAN_ID0_rx <= recv_data_path; end
'd2 : begin CAN_ID1_rx <= recv_data_path; end
'd3 : begin CAN_ID2_rx <= recv_data_path; end
'd4 : begin CAN_ID3_rx <= recv_data_path; end
'd5 : begin CAN_ID4_rx <= recv_data_path; end
'd6 : begin CAN_DATA1_rx <= recv_data_path; end
'd7 : begin CAN_DATA2_rx <= recv_data_path; end
'd8 : begin CAN_DATA3_rx <= recv_data_path; DATA_RECEIVE_DO <= 1'b1;read_cnt<=4'd13;end
default:read_state<=3'b001;
endcase
end
'd4 : begin
case (read_cnt)
'd1 : begin CAN_ID0_rx <= recv_data_path; end
'd2 : begin CAN_ID1_rx <= recv_data_path; end
'd3 : begin CAN_ID2_rx <= recv_data_path; end
'd4 : begin CAN_ID3_rx <= recv_data_path; end
'd5 : begin CAN_ID4_rx <= recv_data_path; end
'd6 : begin CAN_DATA1_rx <= recv_data_path; end
'd7 : begin CAN_DATA2_rx <= recv_data_path; end
'd8 : begin CAN_DATA3_rx <= recv_data_path; end
'd9 : begin CAN_DATA4_rx <= recv_data_path; DATA_RECEIVE_DO <= 1'b1;read_cnt<=4'd13; end
default:read_state<=3'b001;
endcase
end
'd5 : begin
case (read_cnt)
'd1 : begin CAN_ID0_rx <= recv_data_path; end
'd2 : begin CAN_ID1_rx <= recv_data_path; end
'd3 : begin CAN_ID2_rx <= recv_data_path; end
'd4 : begin CAN_ID3_rx <= recv_data_path; end
'd5 : begin CAN_ID4_rx <= recv_data_path; end
'd6 : begin CAN_DATA1_rx <= recv_data_path; end
'd7 : begin CAN_DATA2_rx <= recv_data_path; end
'd8 : begin CAN_DATA3_rx <= recv_data_path; end
'd9 : begin CAN_DATA4_rx <= recv_data_path; end
'd10: begin CAN_DATA5_rx <= recv_data_path; DATA_RECEIVE_DO <= 1'b1; read_cnt<=4'd13;end
default:read_state<=3'b001;
endcase
end
'd6 : begin
case (read_cnt)
'd1 : begin CAN_ID0_rx <= recv_data_path; end
'd2 : begin CAN_ID1_rx <= recv_data_path; end
'd3 : begin CAN_ID2_rx <= recv_data_path; end
'd4 : begin CAN_ID3_rx <= recv_data_path; end
'd5 : begin CAN_ID4_rx <= recv_data_path; end
'd6 : begin CAN_DATA1_rx <= recv_data_path; end
'd7 : begin CAN_DATA2_rx <= recv_data_path; end
'd8 : begin CAN_DATA3_rx <= recv_data_path; end
'd9 : begin CAN_DATA4_rx <= recv_data_path; end
'd10: begin CAN_DATA5_rx <= recv_data_path; end
'd11: begin CAN_DATA6_rx <= recv_data_path; DATA_RECEIVE_DO <= 1'b1; read_cnt<=4'd13;end
default:read_state<=3'b001;
endcase
end
'd7 : begin
case (read_cnt)
'd1 : begin CAN_ID0_rx <= recv_data_path; end
'd2 : begin CAN_ID1_rx <= recv_data_path; end
'd3 : begin CAN_ID2_rx <= recv_data_path; end
'd4 : begin CAN_ID3_rx <= recv_data_path; end
'd5 : begin CAN_ID4_rx <= recv_data_path; end
'd6 : begin CAN_DATA1_rx <= recv_data_path; end
'd7 : begin CAN_DATA2_rx <= recv_data_path; end
'd8 : begin CAN_DATA3_rx <= recv_data_path; end
'd9 : begin CAN_DATA4_rx <= recv_data_path; end
'd10: begin CAN_DATA5_rx <= recv_data_path; end
'd11: begin CAN_DATA6_rx <= recv_data_path; end
'd12: begin CAN_DATA7_rx <= recv_data_path; DATA_RECEIVE_DO <= 1'b1; read_cnt<=4'd13;end
default:read_state<=3'b001;
endcase
end
'd8 : begin
case (read_cnt)
'd1 : begin CAN_ID0_rx <= recv_data_path; end
'd2 : begin CAN_ID1_rx <= recv_data_path; end
'd3 : begin CAN_ID2_rx <= recv_data_path; end
'd4 : begin CAN_ID3_rx <= recv_data_path; end
'd5 : begin CAN_ID4_rx <= recv_data_path; end
'd6 : begin CAN_DATA1_rx <= recv_data_path; end
'd7 : begin CAN_DATA2_rx <= recv_data_path; end
'd8 : begin CAN_DATA3_rx <= recv_data_path; end
'd9 : begin CAN_DATA4_rx <= recv_data_path; end
'd10: begin CAN_DATA5_rx <= recv_data_path; end
'd11: begin CAN_DATA6_rx <= recv_data_path; end
'd12: begin CAN_DATA7_rx <= recv_data_path; end
'd13: begin CAN_DATA8_rx <= recv_data_path; DATA_RECEIVE_DO <= 1'b1; read_cnt<=4'd13;end
default:read_state<=3'b001;
endcase
end
default : read_state <= 3'b001;
endcase
//read_cnt <= 4'd13;
read_state <= 3'b001;
end
else if (read_cnt == 4'd14) begin
CAN_RXERR_rx <= recv_data_path;
read_state <= 3'b001;
end
else begin //??SFF??read_cnt = 13, ???rx_tx_addr[12] = 8'h0F;
//????????TXERR????????...
read_state<=3'b101;
read_cnt<=4'd0 ;
read_addr_path<=8'h01; //write cmd to clear RB(receive buffer)
read_data_path<=8'h04; //clear receive buffer
read_write0<=1'b1;
read_act_path<=1'b1;
CAN_TXERR_rx<=recv_data_path;//TXERR
CAN_DATA_RECV_DONE<=1'b1;//?? DATA_RECEIVE_DO = 1
end
3'b101: if(send_done_path)
begin
read_state<=3'b001;
CAN_DATA_RECV_DONE<=1'b0;
DATA_RECEIVE_DO<=1'b0;
read_finish<=1'b1;
read_act_path<=1'b0;
read_write0 <=1'b0;
end
else begin read_state<=3'b101;
CAN_DATA_RECV_DONE<=1'b0;
DATA_RECEIVE_DO<=1'b0;
read_finish<=1'b0;
read_write0<=1'b1;
read_act_path<=1'b1;
end
default : read_state<=3'b001;
endcase
end
//******************************************************************************************************************************************
//******************************************************************************************************************************************
//*************************************************************************************************************
//send
//*************************************************************************************************************
always @(posedge clk_in) begin
if((reset)||(!init_restf))
begin
send_act_path<=1'b0;
send_state <=3'b001;
send_write0 <=1'b0 ;
CAN_DATA_SEND_DONE<=1'b0;
send_finish <=1'b0 ;
send_cnt <=4'd0 ;
send_addr_path <= 8'h00;
send_data_path <= 8'h00;
end
else case(send_state)
3'b001: if(state_n==DATA_SEND)
begin
send_state<=3'b010;
send_act_path<=1'b1;
send_write0<=1'b1 ;
send_addr_path<=rx_tx_addr[send_cnt];
send_data_path<=tx_data[send_cnt];
CAN_DATA_SEND_DONE<=1'b0;
send_finish <=1'b0 ;
end
else begin
send_state<=3'b001;
send_act_path<=1'b0;
send_write0<=1'b1 ;
send_addr_path<=rx_tx_addr[send_cnt];
send_data_path<=tx_data[send_cnt];
send_cnt <=4'd0;
CAN_DATA_SEND_DONE<=1'b0;
send_finish <=1'b0 ;
end
3'b010: if(send_done_path)
begin
send_act_path<=1'b0;
send_state<=3'b100;
send_write0<=1'b0;
send_cnt <=send_cnt+1'b1;
end
else
begin
send_act_path<=1'b1;
send_write0<=1'b1;
send_state<=3'b010;
end
3'b100: //if(send_cnt<11)//SFF
//if (send_cnt < 13)//EFF //??
if (send_cnt < (tx_DLC + 5))
send_state<=3'b001;
else
begin
send_cnt<=4'd0;//tx_data
CAN_DATA_SEND_DONE<=1'b0;
send_state<=3'b101;
send_act_path<=1'b1;
send_write0<=1'b1;
send_addr_path<=8'h01;
send_data_path<=8'h01; //send cmd//????????SJA1000??????
end
//send_addr_path<=8'h01; send_data_path<=8'h01; ???????????TX buffer????????CMR???????
3'b101: if(send_done_path)
begin send_state<=3'b001;
CAN_DATA_SEND_DONE<=1'b1;
send_finish <=1'b1;
send_act_path<=1'b0;
send_write0<=1'b1;
end
else begin send_state<=3'b101;
CAN_DATA_SEND_DONE<=1'b0;
send_finish <=1'b0;
send_act_path<=1'b1;
send_write0<=1'b1;
end
default : send_state<=3'b001;
endcase
end
//******************************************************************************************
//MUX the data_path
//*******************************************************************************************
//*******************************************************************************************
always @(*) begin
if((reset)||(!init_restf))
begin
act <=1'b0;
write0 <=1'b0;
need_addr_path <=8'd0;
s_data_path <=8'd0;
end
else case(state_n)
INIT_RESET : begin
act <=1'b0;
write0 <=1'b0;
need_addr_path <=8'd0;
s_data_path <=8'd0;
end
INIT : begin
act <=init_act_path;
write0 <=init_write0 ;
need_addr_path<=init_addr_path;
s_data_path <=init_data_path;
end
IDLE : begin
act <= idle_act_path;
write0 <= idle_write0 ;
need_addr_path<= idle_addr_path;
s_data_path <= 8'd0;
end
DATA_READ : begin
act <= read_act_path;
write0 <= read_write0 ;
need_addr_path<= read_addr_path;
s_data_path <= read_data_path;
end
DATA_SEND :begin
act <= send_act_path ;
write0 <= send_write0 ;
need_addr_path <= send_addr_path;
s_data_path <= send_data_path;
end
default :begin
act <=1'b0;
write0 <=1'b0;
need_addr_path <=8'd0;
s_data_path <=8'd0;
end
endcase
end
//module rs_port list
rs_port u1(
.clk (clk_in ),
.reset (((reset)|(!init_restf))),
.act (act ),
.write0 (write0 ),
.need_addr (need_addr_path),
.recv_data (recv_data_path),
.recv_done (recv_done_path),
.send_data (s_data_path ),
.send_done (send_done_path),
.ALE (CAN_ALE ),
.WR (CAN_WR ),
.RD (CAN_RD ),
.CS (CAN_CS ),
.DATA_CAN (DATA_CAN ),
.en (en )
);
endmodule