FPGA 实现CAN通信

使用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 
相关推荐
szxinmai主板定制专家3 小时前
【国产NI替代】基于全国产FPGA的16振动+2转速+8路IO口输入输出(24bits)256k采样率,高精度终端采集板卡
大数据·人工智能·fpga开发
高性能服务器3 小时前
《异构计算:多元算力聚变,点燃高性能计算新引擎 – CPU、GPU与FPGA算力融合》
深度学习·fpga开发·gpu算力·hpc·高性能计算·异构计算·通用计算
9527华安8 小时前
FPGA多路红外相机视频拼接输出,提供2套工程源码和技术支持
图像处理·fpga开发·视频拼接·红外相机
可知可知不可知10 小时前
详解VHDL如何编写Testbench
fpga开发
szxinmai主板定制专家1 天前
【国产NI替代】32振动/电压(配置复合型)高精度终端采集板卡,应用于复杂的大型测量场景
fpga开发
9527华安1 天前
FPGA实时红外相机采集输出系统,提供工程源码和技术支持
图像处理·fpga开发·红外相机
博览鸿蒙1 天前
FPGA自学之路:到底有多崎岖?
fpga开发
搬砖的小码农_Sky1 天前
硬件设计:RS485电平标准
单片机·嵌入式硬件·fpga开发
搬砖的小码农_Sky1 天前
硬件设计:LVDS电平标准
嵌入式硬件·fpga开发
∑狸猫不是猫1 天前
(15)CT137A- 按键消抖设计
fpga开发