国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

FPGA Verilog 控制CAN接收發(fā)送數(shù)據(jù)幀(標準/擴展),遙控幀(標準/擴展)

這篇具有很好參考價值的文章主要介紹了FPGA Verilog 控制CAN接收發(fā)送數(shù)據(jù)幀(標準/擴展),遙控幀(標準/擴展)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

說明

使用Verilog接收發(fā)送,CAN數(shù)據(jù)幀和遠程幀,由于條件有限,并沒有實際下載到辦卡上驗證,只做了仿真驗證,后續(xù)準確性驗證后再行修改。

CAN幀格式

(1)標準數(shù)據(jù)幀:
can標準幀fpga傳輸,CAN,vivado,fpga開發(fā)(2)擴展數(shù)據(jù)幀:
can標準幀fpga傳輸,CAN,vivado,fpga開發(fā)
(3)標準遙控幀
can標準幀fpga傳輸,CAN,vivado,fpga開發(fā)
與數(shù)據(jù)幀的區(qū)別就是沒有數(shù)據(jù)字段;
(4)擴展遙控幀
can標準幀fpga傳輸,CAN,vivado,fpga開發(fā)

系統(tǒng)時鐘為100Mhz,CAN通信頻率是10KHz,在tb處做了分頻得到200Khz的時鐘,為了能夠穩(wěn)定獲取數(shù)據(jù),所以需要在數(shù)據(jù)中間部位取數(shù),所以增加了一個時鐘計數(shù),在cnt=10左右進行取數(shù)。

CAN接收

說明:CAN數(shù)據(jù)幀有直流平衡,即連續(xù)5個0后面必須插入一個1,連續(xù)5個1后面必須插入一個0,所以在接收的時候檢測到連續(xù)5個0或者5個1后需要將后面的一個字節(jié)放棄。
can_ack_out_low	接收端的ACK信號。
`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2022/11/22 11:16:48
// Design Name: 
// Module Name: can_recive
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module can_recive(
	input   	wire		                can_clk	    				,
	input   	wire		                rst_n       				,
	
	input		wire						can_rx						,	

	output		reg			[7:0]			can_mode_o					,
	output		reg							can_ack_out_low				,	//響應幀	2'b01
	
	output		wire						can_id_en_o					,	//	id		輸出使能
	output		wire		[31:0]			can_id_o					,	//	id
	
	output		reg							can_data_out_en				,	//	數(shù)據(jù)	輸出使能
	output		reg			[63:0]			can_data_out					//	數(shù)據(jù)
    );
	
	assign				can_id_en_o		=	can_id_out_en								;
	assign				can_id_o		=	(can_ide == 0) ? can_id_out : can_id_out_ex	;
	
	reg									can_id_out_en					;	//	id		輸出使能
	reg					[31:0]			can_id_out						;	//	id
	reg					[31:0]			can_id_out_ex					;	//	id
	
	reg									can_rx_t						;
	reg									can_rtr							;
	reg									can_ide							;
	
	reg					[4:0]			one_bit_cont					;
	reg					[6:0]			bit_cont						;
	reg									id_en_flag						;
	reg									contral_flag					;
	reg									data_en_flag					;
	reg									crc_en_flag						;
	reg									can_rx_en_flag					;
	reg									can_rx_unen_flag				;
	reg					[4:0]			can_continuity_data				;
	reg									can_continuity_data_flag		;

	reg					[8:0]			can_data_len					;
	reg					[3:0]			can_data_len_buff				;
	
	reg					[15:0]			can_crc_buff					;
	reg					[14:0]			can_crc_data					;
	
	reg									remote_en						;	//遠程幀使能 1 遠程幀,0數(shù)據(jù)幀

	reg	 				   				crc_en							;
	reg									crc_data_i						;
	reg									crc_rst							;
	wire 				[14:0]			crc_data_o						;
	
	reg									crc_success						;
	//CRC校驗結(jié)果
	always @(posedge can_clk or negedge rst_n )begin
		if(rst_n==1'b0) 
			crc_success	<= 'b0							;
		else if(cur_st == st_sof)
			crc_success	<= 'b0							;
		else if((cur_st == st_end)&&(crc_data_o == can_crc_data[14:0]))
			crc_success	<= 'b1							;
		//else	
	end 
	
	always @(posedge can_clk or negedge rst_n )begin
		if(rst_n==1'b0) begin
			can_rx_t	<= 'b0							;
		end else  begin
			can_rx_t	<= can_rx						;
		end	
	end 


	always @(posedge can_clk or negedge rst_n )
	begin
		if(rst_n==1'b0) 
			can_mode_o	<= 'b0							;
		else if(cur_st == st_end) 
		begin
			case({can_ide,can_rtr})
			2'b00:		can_mode_o	<=	8'h00			;	//標準數(shù)據(jù)幀
			2'b10:		can_mode_o	<=	8'h01			;	//擴展數(shù)據(jù)幀
			2'b01:		can_mode_o	<=	8'h02			;	//標準遠程幀
			2'b11:		can_mode_o	<=	8'h03			;	//擴展遠程幀
			default	:	can_mode_o	<=	8'h00			;	//標準數(shù)據(jù)幀
			endcase
		end	
	end 
	
	localparam			st_idle		 			= 11'd0				,	//狀態(tài)機初始化
						st_sof		 			= 11'd1				,	//開始幀頭第一位SOF
						st_id		 			= 11'd2				,	//包ID,仲裁字段
						Extended_id	 			= 11'd3				,	//擴展幀ID
						standard_data_ctrl		= 11'd4				,	//標準幀數(shù)據(jù)段
						remote_ctrl	 			= 11'd5				,	//標準幀控制段
						Extend_remote_ctrl	 	= 11'd6				,	//擴展遠程幀控制段
						st_data		 			= 11'd7				,	//數(shù)據(jù)段
						st_crc		 			= 11'd8				,	//CRC段
						st_ack		 			= 11'd9				,	//ACK段  確認間隙位1bit , 確認定界符1bit
						st_eof		 			= 11'd10			,	//幀結(jié)束段
						st_end		 			= 11'd11			;	//狀態(tài)機結(jié)束狀態(tài)
	reg			[10:0]	cur_st										;	

	parameter			bit_flag_no				= 5'b10011			;	//20分頻	10Kbps
	
	always@(posedge can_clk or negedge rst_n)
	begin
		if(~rst_n)
		begin
			bit_cont					<=	'b0						;
			one_bit_cont				<= 	'b0						;
			id_en_flag					<= 	'b0						;
			contral_flag				<=	'b0						;
			data_en_flag				<= 	'b0						;
			can_data_len				<= 	'b0						;
			crc_en_flag					<= 	'b0						;
			can_ack_out_low				<= 	'b1						;
			can_crc_data				<=	'b0						;
			can_rx_en_flag				<=	'b0						;
			remote_en					<=	'b0						;
			cur_st						<=	st_idle					;
		end
		else
		begin
			case(cur_st)
			st_idle		:
			begin
				if ((can_rx_t == 1'b1)&&(can_rx == 1'b0))					//下降沿 低電平
				begin
					can_rx_en_flag		<=	'b1								;
					cur_st				<=	st_sof							;
				end
				else
					cur_st				<=	st_idle							;
			end
			st_sof		:													//低電平持續(xù)20個周期,一個波特率時間
			begin
				if ((one_bit_cont == bit_flag_no - 1)&&(can_rx == 1'b0))
				begin
					cur_st				<= 	st_id							;
					id_en_flag			<= 	'b1								;
					one_bit_cont		<= 	'b0								;
				end 
				else if ((one_bit_cont < bit_flag_no - 1)&&(can_rx == 1'b0))
				begin
					cur_st				<= 	st_sof							;
					one_bit_cont		<= 	one_bit_cont + 1'b1				;
				end		
				else		
				begin		
					one_bit_cont		<= 	'b0								;
					can_rx_en_flag		<=	'b0								;
					cur_st				<= 	st_idle							;
				end
			end
			st_id		:
			begin
				if ((one_bit_cont == bit_flag_no)&&(bit_cont == 13))		//11bit	ID + RTR/SRR + IDE
				begin
					if(can_ide == 0)										//IDE=0 標準幀
					begin
						id_en_flag		<= 	'b0								;
						contral_flag	<= 	'b1								;
						if(can_rtr == 0)										//標準數(shù)據(jù)幀
							remote_en	<= 	'b0								;
						else												//標準遠程幀
							remote_en	<=	'b1								;
						cur_st			<= 	standard_data_ctrl				;
					end
					else													//IDE=1	擴展幀 進入擴展ID
					begin
						id_en_flag		<= 	'b1								;
						contral_flag	<= 	'b0								;
						cur_st			<= 	Extended_id						;
					end		
					one_bit_cont		<= 	'b0								;
					bit_cont			<= 	'b0								;
				end 
				else if ((one_bit_cont == bit_flag_no)&&(bit_cont < 13)) 
				begin
					cur_st				<= st_id							;
					one_bit_cont		<= 'b0								;
					if(can_rx_unen_flag == 0)
						bit_cont		<= bit_cont + 1'b1					;
					else
						bit_cont		<=	bit_cont						;
				end 		
				else if (one_bit_cont < bit_flag_no) 		
				begin		
					cur_st				<= st_id							;
					one_bit_cont		<= one_bit_cont + 1'b1				;
				end 
			end
			Extended_id			:
			begin
				if ((one_bit_cont == bit_flag_no)&&(bit_cont == 17))		//進入擴展幀的控制段
				begin
					if(can_rtr == 0)										//擴展數(shù)據(jù)幀
						remote_en		<= 	'b0								;
					else													//擴展遠程幀
						remote_en		<=	'b1								;
					id_en_flag			<= 	'b0								;
					contral_flag		<=	'b0								;
					one_bit_cont		<=	'b0								;
					bit_cont			<=	'b0								;
					contral_flag		<=	'b1								;
					cur_st				<=	Extend_remote_ctrl				;
				end 
				else if ((one_bit_cont == bit_flag_no)&&(bit_cont < 17)) 
				begin
					cur_st				<= Extended_id						;
					one_bit_cont		<= 'b0								;
					if(can_rx_unen_flag == 0)
						bit_cont		<= bit_cont + 1'b1					;
					else
						bit_cont		<=	bit_cont						;
				end 		
				else if (one_bit_cont < bit_flag_no) 		
				begin		
					cur_st				<= Extended_id						;
					one_bit_cont		<= one_bit_cont + 1'b1				;
				end 
			end
			standard_data_ctrl	:											//標準幀控制段
			begin
				if ((one_bit_cont == bit_flag_no)&&(bit_cont == 3))	
				begin
					if(remote_en == 0)
					begin
						data_en_flag	<= 	'b1								;
						cur_st			<= 	st_data							;//數(shù)據(jù)幀
					end
					else
					begin
						data_en_flag	<= 	'b0								;
						cur_st			<= 	st_crc							;//遠程幀
					end
					can_data_len		<=	{1'b0,can_data_len_buff[3:0],3'b0}	;
					contral_flag		<= 	'b0								;
					one_bit_cont		<= 	'b0								;
					bit_cont			<= 	'b0								;
				end 
				else if ((one_bit_cont == bit_flag_no)&&(bit_cont < 3)) 
				begin
					cur_st				<= standard_data_ctrl				;
					one_bit_cont		<= 'b0								;
					if(can_rx_unen_flag == 0)
						bit_cont		<= bit_cont + 1'b1					;
					else
						bit_cont		<=	bit_cont						;
				end 
				else if (one_bit_cont < bit_flag_no) 
				begin
					cur_st				<= standard_data_ctrl				;
					one_bit_cont		<= one_bit_cont + 1'b1				;
				end 
			end
			Extend_remote_ctrl	:											//擴展幀控制段
			begin
				if ((one_bit_cont == bit_flag_no)&&(bit_cont == 5))	
				begin
					if(remote_en == 0)
					begin
						data_en_flag	<= 	'b1								;
						cur_st			<= 	st_data							;//數(shù)據(jù)幀
					end
					else
					begin
						data_en_flag	<= 	'b0								;
						cur_st			<= 	st_crc							;//遠程幀
					end
					can_data_len		<=	{1'b0,can_data_len_buff[3:0],3'b0}	;
					contral_flag		<= 	'b0								;
					one_bit_cont		<= 	'b0								;
					bit_cont			<= 	'b0								;
				end 
				else if ((one_bit_cont == bit_flag_no)&&(bit_cont < 5)) 
				begin
					cur_st				<= Extend_remote_ctrl				;
					one_bit_cont		<= 'b0								;
					if(can_rx_unen_flag == 0)
						bit_cont		<= bit_cont + 1'b1					;
					else
						bit_cont		<=	bit_cont						;
				end 
				else if (one_bit_cont < bit_flag_no) 
				begin
					cur_st				<= Extend_remote_ctrl				;
					one_bit_cont		<= one_bit_cont + 1'b1				;
				end
			end
			st_data		:
			begin
				if ((one_bit_cont == bit_flag_no)&&(bit_cont == can_data_len - 1))	
				begin
					cur_st				<= st_crc							;
					one_bit_cont		<= 'b0								;
					bit_cont			<= 'b0								;
					data_en_flag		<= 'b0								;
					crc_en_flag			<= 'b1								;
				end 
				else if ((one_bit_cont == bit_flag_no)&&(bit_cont < can_data_len - 1)) 
				begin
					cur_st				<= st_data							;
					one_bit_cont		<= 'b0								;
					if(can_rx_unen_flag == 0)
						bit_cont		<= bit_cont + 1'b1					;
					else
						bit_cont		<=	bit_cont						;
				end else if (one_bit_cont < bit_flag_no) 
				begin
					cur_st				<= st_data							;
					one_bit_cont		<= one_bit_cont + 1'b1				;
				end 
			end
			st_crc		:
			begin
				if ((one_bit_cont == bit_flag_no)&&(bit_cont == 14))	
				begin
					can_crc_data		<=	can_crc_buff[14:0]				;
					one_bit_cont		<= 	'b0								;
					bit_cont			<= 	'b0								;
					crc_en_flag			<= 	'b0								;
					can_ack_out_low		<= 	'b0								;
					cur_st				<= 	st_ack							;
				end 
				else if ((one_bit_cont == bit_flag_no)&&(bit_cont < 14)) 
				begin
					cur_st				<= 	st_crc							;
					one_bit_cont		<= 	'b0								;
					if(can_rx_unen_flag == 0)
						bit_cont		<= bit_cont + 1'b1					;
					else
						bit_cont		<=	bit_cont						;
				end 
				else if (one_bit_cont < bit_flag_no) 
				begin
					cur_st				<= 	st_crc							;
					one_bit_cont		<= 	one_bit_cont + 1'b1				;
				end 
			end
			st_ack		:
			begin
				if ((one_bit_cont==bit_flag_no)&&(bit_cont==1))	
				begin
					cur_st				<= 	st_eof							;
					can_rx_en_flag		<= 	'b0								;
					one_bit_cont		<= 	'b0								;
					bit_cont			<= 	'b0								;
				end 
				else if ((one_bit_cont==bit_flag_no)&&(bit_cont<1)) 
				begin
					can_ack_out_low		<=	'b1								;
					cur_st				<=	st_ack							;
					one_bit_cont		<=	'b0								;
					if(can_rx_unen_flag == 0)
						bit_cont		<= bit_cont + 1'b1					;
					else
						bit_cont		<=	bit_cont						;
				end 
				else if (one_bit_cont<bit_flag_no) 
				begin
					cur_st				<= 	st_ack							;
					one_bit_cont		<= 	one_bit_cont + 1'b1				;
				end 
			end
			st_eof		:
			begin
				if ((one_bit_cont == bit_flag_no)&&(bit_cont == 6))			//幀結(jié)束7'b111_1111
				begin
					cur_st				<= st_end							;
					one_bit_cont		<= 'b0								;
					bit_cont			<= 'b0								;
				end 
				else if ((one_bit_cont == bit_flag_no)&&(bit_cont < 6)) 
				begin
					cur_st				<= st_eof							;
					one_bit_cont		<= 'b0								;
					bit_cont			<= bit_cont + 1'b1					;
				end 
				else if (one_bit_cont < bit_flag_no) 
				begin
					cur_st				<= st_eof							;
					one_bit_cont		<= one_bit_cont + 1'b1				;
				end 
			end
		    st_end		:
			begin
				cur_st					<=	st_idle							;
				remote_en				<=	'b0								;
				one_bit_cont			<=	'b0								;
				bit_cont				<=	'b0								;
				id_en_flag				<=	'b0								;
				contral_flag        	<=	'b0								;
				data_en_flag			<=	'b0								;
				crc_en_flag	        	<=	'b0								;
				can_rx_en_flag      	<=	'b0								;
				can_ack_out_low			<=	'b1								;
			end
			default		:
			begin
				cur_st					<=	st_idle							;
				one_bit_cont			<=	'b0								;
				bit_cont				<=	'b0								;
				id_en_flag				<=	'b0								;
				contral_flag        	<=	'b0								;
				data_en_flag			<=	'b0								;
				crc_en_flag	        	<=	'b0								;
				can_rx_en_flag      	<=	'b0								;
				can_ack_out_low			<=	'b1								;
				can_crc_data			<=	'b0								;
				can_data_len			<=	'b0								;
			end
			endcase
		end
	end
	//獲取IDE	和	RTR
	always@(posedge can_clk or negedge rst_n)
	begin
		if(~rst_n)
		begin
			can_rtr		<=	0			;
			can_ide		<=	0			;
		end
		else if(cur_st == st_idle)
		begin
			can_rtr		<=	0			;
			can_ide		<=	0			;
		end
		else if(cur_st == st_id && ((one_bit_cont == (bit_flag_no+1)/2)&&(bit_cont == 12))&&(can_rx_unen_flag==0))
			can_ide		<=	can_rx		;
		else if(cur_st == st_id && ((one_bit_cont == (bit_flag_no+1)/2)&&(bit_cont == 11))&&(can_rx_unen_flag==0))
			can_rtr		<=	can_rx		;
		else if(cur_st == Extended_id && ((one_bit_cont == (bit_flag_no+1)/2)&&(bit_cont == 17))&&(can_rx_unen_flag==0))
			can_rtr		<=	can_rx		;
	end
	//判斷連續(xù)5個1 或者連續(xù)5個0
	always @(posedge can_clk or negedge rst_n )
	begin
		if(rst_n==1'b0) 
		begin
			can_continuity_data			<= 5'b11111								;
			can_continuity_data_flag	<= 'b0									;
		end 
		else if (can_rx_en_flag==0) 
		begin
			can_continuity_data			<= 5'b11111								;
			can_continuity_data_flag	<= 'b0									;
		end 
		else if ((one_bit_cont==9)&&(can_rx_en_flag==1)) 
		begin
			can_continuity_data			<= {can_continuity_data[3:0],can_rx}	;
			can_continuity_data_flag	<= 'b0												;
		end	
		else if (((can_continuity_data==0)||(can_continuity_data==5'b11111))&&(one_bit_cont==10)&&(crc_en_flag==0)) 
		begin
			can_continuity_data_flag	<= 'b1									;
		end 
		else if (((can_continuity_data==0)||(can_continuity_data==5'b11111))&&(one_bit_cont==10)&&(crc_en_flag==1)&&(bit_cont<14)) 
		begin
			can_continuity_data_flag	<= 'b1									;
		end 
		else 
		begin
			can_continuity_data_flag	<= 'b0									;
		end
	end 

	always @(posedge can_clk or negedge rst_n )
	begin
		if(rst_n==1'b0) 
		begin
			can_rx_unen_flag	<= 'b0									;
		end 
		else if ((can_rx_en_flag==1)&&(can_continuity_data_flag==1)&&(crc_en_flag==0)) 
		begin
			can_rx_unen_flag	<= 1'b1									;
		end	 
		else if ((can_rx_en_flag==1)&&(can_continuity_data_flag==1)&&(crc_en_flag==1)&&(bit_cont<14)) 
		begin
			can_rx_unen_flag	<= 1'b1									;
		end 
		else if (one_bit_cont==11) 
		begin
			can_rx_unen_flag	<= 1'b0									;
		end 
		else if (can_rx_en_flag==0)
			can_rx_unen_flag	<= 'b0									;
	end 	
	//獲取字段長度
	always@(posedge can_clk or negedge rst_n)
	begin
		if(~rst_n)
			can_data_len_buff		<=	'b0								;
		else if(cur_st == standard_data_ctrl && (one_bit_cont == 9)&&(can_rx_unen_flag==0))
			can_data_len_buff		<=	{can_data_len_buff[2:0],can_rx}	;
		else if(cur_st == Extend_remote_ctrl && (one_bit_cont == 9)&&(can_rx_unen_flag==0))
			can_data_len_buff		<=	{can_data_len_buff[2:0],can_rx}	;
	end
	
	//獲取CRC數(shù)據(jù)
	always@(posedge can_clk or negedge rst_n)
	begin
		if(~rst_n)
			can_crc_buff		<=	'b0									;
		else if(cur_st == st_crc && (one_bit_cont == (bit_flag_no+1)/2) && (bit_cont <= 15)&&(can_rx_unen_flag==0))
			can_crc_buff		<=	{can_crc_buff[14:0],can_rx}			;
	end
	//獲取 can  ID號
	always @(posedge can_clk or negedge rst_n )
	begin
		if(rst_n==1'b0) 
			can_id_out	<= 'b0											;
		else if((cur_st == st_id) && (one_bit_cont == (bit_flag_no+1)/2) &&(bit_cont < 11)&&(can_rx_unen_flag==0)) 
			can_id_out	<= {can_id_out[30:0],can_rx	}					;
	end 
	//獲取 can	擴展ID號
	always @(posedge can_clk or negedge rst_n )
	begin
		if(rst_n==1'b0) 
			can_id_out_ex	<= 'b0										;
		else if((cur_st == st_id) && (one_bit_cont == (bit_flag_no+1)/2) &&((bit_cont < 11) || (bit_cont == 13))&&(can_rx_unen_flag==0)) 
			can_id_out_ex	<= {can_id_out_ex[30:0],can_rx	}			;
		else if(can_ide && (cur_st == Extended_id) && (one_bit_cont == (bit_flag_no+1)/2) &&(bit_cont < 17)&&(can_rx_unen_flag==0))
			can_id_out_ex	<= {can_id_out_ex[30:0],can_rx	}			;
	end 
	//can  id輸出使能
	always @(posedge can_clk or negedge rst_n )
	begin
		if(rst_n==1'b0) 
			can_id_out_en	<= 'b0										;
		else if ((can_ide == 0) && (cur_st == st_id) && (one_bit_cont == bit_flag_no)&&(bit_cont == 12)) 
			can_id_out_en	<= 1'b1										;
		else if ((can_ide == 1) && (cur_st == Extended_id) && (one_bit_cont == bit_flag_no)&&(bit_cont == 17)) 
			can_id_out_en	<= 1'b1										;
		else 
			can_id_out_en	<= 'b0										;
	end 
	//can 接收數(shù)據(jù)字段
	always @(posedge can_clk or negedge rst_n )
	begin
		if(rst_n==1'b0) 
		begin
			can_data_out	<= 'b0										;
		end 
		else if ((cur_st == st_data) && (one_bit_cont == (bit_flag_no+1)/2)&&(can_rx_unen_flag==0)) 
		begin
			can_data_out	<= {can_data_out[62:0],can_rx	}			;
		end	
	end 
	//can 結(jié)束 輸出使能
	always @(posedge can_clk or negedge rst_n )
	begin
		if(rst_n==1'b0) 
		begin
			can_data_out_en	<= 'b0										;
		end 
		else if ((cur_st == st_data) && (one_bit_cont == bit_flag_no) && (bit_cont == can_data_len - 1)) 
		begin
			can_data_out_en	<= 1'b1										;
		end	
		else 
			can_data_out_en	<= 'b0										;
	end 	 		
	
	//crc 校驗使能 
	always@(posedge can_clk or negedge rst_n)
	begin
		if(~rst_n)
			crc_en			<=	'b0					;
		else
		begin
			case(cur_st)
			st_idle		:
				crc_en		<=	'b0					;
			st_sof,st_id,Extended_id,standard_data_ctrl	,
			remote_ctrl,Extend_remote_ctrl,st_data		:
			begin
				if(one_bit_cont == 3 && (can_rx_unen_flag == 0))
					crc_en	<=	'b1					;
				else
					crc_en	<=	'b0					;
			end
			st_crc		:
			begin
				crc_en		<=	'b0					;
			end
			st_ack,	st_eof,	st_end:
				crc_en		<=	'b0					;
			default		:
				crc_en		<=	'b0					;
			endcase
		end
	end
	//crc 數(shù)據(jù)
	always@(posedge can_clk or negedge rst_n)
	begin
		if(~rst_n)
			crc_data_i		<=	'b0					;
		else
		begin
			case(cur_st)
			st_idle		:
				crc_data_i	<=	'b0					;
			st_sof		:
				crc_data_i	<=	'b0					;
			st_sof,st_id,Extended_id,standard_data_ctrl	,
			remote_ctrl,Extend_remote_ctrl,st_data		:
				crc_data_i	<=	can_rx				;
			st_crc		:
				crc_data_i	<=	'b0					;
			st_ack,	st_eof,	st_end	:
				crc_data_i	<=	'b0					;
			default		:
				crc_data_i	<=	'b0					;
			endcase
		end
	end
	//crc 軟復位
	always@(posedge can_clk or negedge rst_n)
	begin
		if(~rst_n)
			crc_rst			<=	'b0					;
		else if(cur_st == st_idle)
			crc_rst			<=	'b1					;//未開始,復位crc
		else if(cur_st == st_sof)
			crc_rst			<=	'b0					;
		else if(cur_st == st_end)
			crc_rst			<=	'b1					;//未開始,復位crc
	end
	can_crc can_crc(	
		.crc_clk_i		(can_clk		)	,
		.rst_i			(rst_n  		)	,
		.en_i			(crc_en			)	,
		.data_i			(crc_data_i		)	,
		.crc_rst_i		(crc_rst		)	,
		.crc_reg_o		(crc_data_o		)	
	);
endmodule

CAN發(fā)送

can_rx	:接收端發(fā)送的ACK信號。
`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2022/11/22 11:17:00
// Design Name: 
// Module Name: can_send
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module can_send(
	input   	wire		  	clk_can	    		,
	input   	wire		  	rst_n       		,
			
	output		reg				can_tx				,
	input		wire			can_rx				,
	
	output		reg				send_finish			,
	output		reg				send_error			,
	
	input		wire			can_send_en			,
	input		wire	[10:0]	can_id				,	//can 	id
	input		wire	[17:0]	Extend_can_id		,	//擴展	id
			
	input		wire	[7:0]	can_mode			,	//幀模式 00 標準數(shù)據(jù)幀;01擴展數(shù)據(jù)幀;02標準遠程幀;03擴展遠程幀
	input		wire	[3:0]	user_data_len		,	//數(shù)據(jù)字段字節(jié)數(shù)
	input		wire	[63:0]	user_data				//數(shù)據(jù)字段
    );
	/*
	標準數(shù)據(jù)幀[107:0]
	擴展數(shù)據(jù)幀[127:0]
	標準遠程幀[43:0]
	擴展遠程幀[63:0]
	*/
	parameter				bit_flag_no	= 5'b10011	;	//20分頻	10Kbps
	reg	 		   			crc_en					;
	reg						crc_data_i				;
	reg						crc_rst					;
	wire 		[14:0]		crc_data_o				;
		
	reg			[82	:0]		data_frame				;
	reg			[102:0]		Ext_data_frame			;
	reg			[18 :0]		remote_frame			;
	reg			[38 :0]		Ext_remote_frame		;
		
	reg			[14 :0]		crc_data_buff			;
		
	
	reg			[7	:0]		can_frame_len			;	//can發(fā)送幀長度
		
	reg			[7	:0]		send_cnt				;
	reg			[7	:0]		one_bit_cont			;
	
	reg						can_tx_en_flag			;
	reg		[4:0]			can_continuity_data		;
	reg						can_continuity_data_flag;
		
	reg						can_send_en1			;
	reg						can_send_en2			;
	always@(posedge clk_can or negedge rst_n)
	begin
		if(~rst_n)
		begin
			can_send_en1	<=	0					;
			can_send_en2	<=	0					;
		end
		else
		begin
			can_send_en1	<=	can_send_en			;
			can_send_en2	<=	can_send_en1		;
		end
	end
	assign	can_send_en_raising	=	~can_send_en2 & can_send_en1	;
	localparam		idle				=	0		,
					init				=	1		,
					data_send			=	2		,
					Ext_data_send		=	3		,
					remote_send			=	4		,
					Ext_remote_send		=	5		,
					crc_send			=	6		,
					over				=	7		;
	reg		[7:0]	cur_st							;
	always@(posedge clk_can or negedge rst_n)
	begin
		if(~rst_n)
		begin
			cur_st						<=	idle			;
		end
		else
		begin
			case(cur_st)
			idle	:
			begin
				if(can_send_en_raising)
					cur_st				<=	init			;
				else
					cur_st				<=	idle			;
			end
			init	:
			begin
				case(can_mode)
				8'h00	:												//標準數(shù)據(jù)幀[82	:0]
					cur_st				<=	data_send					;
				8'h01	:												//擴展數(shù)據(jù)幀[102:0]	
					cur_st				<=	Ext_data_send				;
				8'h02	:												//標準遠程幀[18 :0]
					cur_st				<=	remote_send					;
				8'h03	:												//擴展遠程幀[38 :0]
					cur_st				<=	Ext_remote_send				;
				default	:												//標準數(shù)據(jù)幀[102:0]
					cur_st				<=	idle						;
				endcase	
			end
			data_send		:
			begin
				if((one_bit_cont == bit_flag_no)&& (send_cnt == can_frame_len - 1))
					cur_st				<=	crc_send					;
				else 
					cur_st				<=	data_send					;
			end
			Ext_data_send	:
			begin
				if((one_bit_cont == bit_flag_no)&& (send_cnt == can_frame_len - 1))
					cur_st				<=	crc_send					;
				else 
					cur_st				<=	Ext_data_send				;
			end
			remote_send		:
			begin
				if((one_bit_cont == bit_flag_no)&& (send_cnt == can_frame_len - 1))
					cur_st				<=	crc_send					;
				else 
					cur_st				<=	remote_send					;
			end
			Ext_remote_send	:
			begin
				if((one_bit_cont == bit_flag_no)&& (send_cnt == can_frame_len - 1))
					cur_st				<=	crc_send					;
				else 
					cur_st				<=	Ext_remote_send				;
			end
			crc_send:
			begin
				if((one_bit_cont == bit_flag_no)&& (send_cnt == 14))
					cur_st				<=	over						;
				else 
					cur_st				<=	crc_send					;
			end
			over	:
			begin
				if(one_bit_cont == bit_flag_no)
					cur_st				<=	idle						;
				else
					cur_st				<=	over						;
			end
			default	:cur_st				<=	idle						;
			endcase
		end
	end
	//接收ACK信號,輸出是否發(fā)送完成
	always@(posedge clk_can or negedge rst_n)
	begin
		if(~rst_n)
		begin
			send_finish					<=	0							;
			send_error					<=	0							;
		end
		else if(cur_st == idle)
		begin
			send_finish					<=	0							;
			send_error					<=	0							;
		end
		else if(cur_st == over )
		begin
			if((one_bit_cont == (bit_flag_no + 1)/2) && (can_rx == 0))
				send_finish				<=	1							;
			else
				send_error				<=	0							;
		end
	end
	//send bit計數(shù) 延時計數(shù)
	always@(posedge clk_can or negedge rst_n)
	begin
		if(~rst_n)
		begin
			send_cnt					<=	'b0							;
			one_bit_cont				<=	'b0							;
		end
		else
		begin
			case(cur_st)
			idle				:
			begin
				send_cnt				<=	'b0							;
				one_bit_cont			<=	'b0							;
			end
			data_send , Ext_data_send ,	remote_send , Ext_remote_send	:
			begin
				if((one_bit_cont == bit_flag_no )&& (send_cnt == can_frame_len - 1))
				begin
					one_bit_cont		<=	0							;
					send_cnt			<=	0							;
				end	
				else if(one_bit_cont == bit_flag_no)	
				begin	
					if(can_continuity_data_flag == 0)
						send_cnt		<=	send_cnt	+	1			;
					one_bit_cont		<=	0							;
				end	
				else if(one_bit_cont < bit_flag_no)	
				begin	
					one_bit_cont		<=	one_bit_cont	+	1		;
					send_cnt			<=	send_cnt					;
				end	
			end
			crc_send			:
			begin
				if((one_bit_cont == bit_flag_no)&& (send_cnt == 15))
				begin
					one_bit_cont		<=	0							;
					send_cnt			<=	0							;
				end	
				else if(one_bit_cont == bit_flag_no)	
				begin	
					if(can_continuity_data_flag == 0)
						send_cnt		<=	send_cnt	+	1			;
					one_bit_cont		<=	0							;
				end	
				else if(one_bit_cont < bit_flag_no)	
				begin	
					one_bit_cont		<=	one_bit_cont	+	1		;
					send_cnt			<=	send_cnt					;
				end	
			end
			over				:
			begin
				if(one_bit_cont == bit_flag_no)
					one_bit_cont		<=	'b0							;
				else
					one_bit_cont		<=	one_bit_cont	+	1		;
				send_cnt				<=	'b0							;
			end
			default				:
			begin
				one_bit_cont			<=	'b0							;
				send_cnt				<=	'b0							;
			end
			endcase
		end
	end
	
	always@(posedge clk_can or negedge rst_n)
	begin
		if(~rst_n)
		begin
			can_tx							<=	'b1									;
			data_frame 						<=	{83{1'b1}}    						;
			Ext_data_frame 					<=	{103{1'b1}}   						;
			remote_frame 					<=	{19{1'b1}}    						;
			Ext_remote_frame 				<=	{39{1'b1}}    						;
			crc_data_buff					<=	{15{1'b1}}							;
			can_frame_len					<=	'b0									;
		end
		else
		begin
			case(cur_st)
			idle				:
			begin
				can_tx						<=	'b1									;
				data_frame 					<=	{83{1'b1}}    						;
				Ext_data_frame 				<=	{103{1'b1}}   						;
				remote_frame 				<=	{19{1'b1}}    						;
				Ext_remote_frame 			<=	{39{1'b1}}    						;
				crc_data_buff				<=	{15{1'b1}}							;
				can_frame_len				<=	'b0									;
			end
			init				:
			begin
				case(can_mode)
				8'h00	:																						//標準數(shù)據(jù)幀[82	:0]
				begin
					can_frame_len			<=	8'd19 + {1'b0,user_data_len[3:0],3'b0}									;	
					case(user_data_len)
					4'd0	:
						data_frame			<=	{1'b0,can_id,1'b0,1'b0,1'b0,user_data_len[3:0],64'b0}					;
					4'd1	:	
						data_frame			<=	{1'b0,can_id,1'b0,1'b0,1'b0,user_data_len[3:0],user_data[7:0],56'b0}	;
				//0 0010_1011_010 000 0(1)001  0111 1000   (CRC)101_0001_1101_0101(補1) 0000_0000_0000_0000_0000_0000_0000_0000_0000_0000
					4'd2	:	
						data_frame			<=	{1'b0,can_id,1'b0,1'b0,1'b0,user_data_len[3:0],user_data[15:0],48'b0}	;
					4'd3	:	
						data_frame			<=	{1'b0,can_id,1'b0,1'b0,1'b0,user_data_len[3:0],user_data[23:0],40'b0}	;
					4'd4	:	
						data_frame			<=	{1'b0,can_id,1'b0,1'b0,1'b0,user_data_len[3:0],user_data[31:0],32'b0}	;
					4'd5	:	
						data_frame			<=	{1'b0,can_id,1'b0,1'b0,1'b0,user_data_len[3:0],user_data[39:0],24'b0}	;
					4'd6	:	
						data_frame			<=	{1'b0,can_id,1'b0,1'b0,1'b0,user_data_len[3:0],user_data[47:0],16'b0}	;
					4'd7	:	
						data_frame			<=	{1'b0,can_id,1'b0,1'b0,1'b0,user_data_len[3:0],user_data[55:0],8'b0}	;
					4'd8	:	
						data_frame			<=	{1'b0,can_id,1'b0,1'b0,1'b0,user_data_len[3:0],user_data[63:0]}			;
					default	:	
						data_frame			<=	{1'b0,can_id,1'b0,1'b0,1'b0,user_data_len[3:0],user_data[7:0],56'b0}	;
					endcase
				end
				8'h01	:																							//擴展數(shù)據(jù)幀[102:0]
				begin
					can_frame_len			<=	8'd39 + {1'b0,user_data_len[3:0],3'b0}									;
					case(user_data_len)
					4'd0	:
						Ext_data_frame		<=	{1'b0,can_id,1'b1,1'b1,Extend_can_id,1'b0,1'b0,1'b0,user_data_len[3:0],64'b0}					;
					4'd1	:	
						Ext_data_frame		<=	{1'b0,can_id,1'b1,1'b1,Extend_can_id,1'b0,1'b0,1'b0,user_data_len[3:0],user_data[7:0],56'b0}	;
				//	0 (ID)0010_1011_010 (SRR)1(ID)1 (ex_id)10_0001_0101_0010_0011 (RTR)0 (PB1)0 (PB0)0  (字節(jié)數(shù))00(1)01  0111_1000 (CRC)011_0101_1111(0)_0010(補1) 0000_0000_0000_0000_0000_0000_0000_0000_0000_0000
					4'd2	:	
						Ext_data_frame		<=	{1'b0,can_id,1'b1,1'b1,Extend_can_id,1'b0,1'b0,1'b0,user_data_len[3:0],user_data[15:0],48'b0}	;
					4'd3	:	
						Ext_data_frame		<=	{1'b0,can_id,1'b1,1'b1,Extend_can_id,1'b0,1'b0,1'b0,user_data_len[3:0],user_data[23:0],40'b0}	;
					4'd4	:	
						Ext_data_frame		<=	{1'b0,can_id,1'b1,1'b1,Extend_can_id,1'b0,1'b0,1'b0,user_data_len[3:0],user_data[31:0],32'b0}	;
					4'd5	:	
						Ext_data_frame		<=	{1'b0,can_id,1'b1,1'b1,Extend_can_id,1'b0,1'b0,1'b0,user_data_len[3:0],user_data[39:0],24'b0}	;
					4'd6	:	
						Ext_data_frame		<=	{1'b0,can_id,1'b1,1'b1,Extend_can_id,1'b0,1'b0,1'b0,user_data_len[3:0],user_data[47:0],16'b0}	;
					4'd7	:	
						Ext_data_frame		<=	{1'b0,can_id,1'b1,1'b1,Extend_can_id,1'b0,1'b0,1'b0,user_data_len[3:0],user_data[55:0],8'b0}	;
					4'd8	:	
						Ext_data_frame		<=	{1'b0,can_id,1'b1,1'b1,Extend_can_id,1'b0,1'b0,1'b0,user_data_len[3:0],user_data[63:0]}			;
					default	:	
						Ext_data_frame		<=	{1'b0,can_id,1'b1,1'b1,Extend_can_id,1'b0,1'b0,1'b0,user_data_len[3:0],user_data[7:0],56'b0}	;
					endcase
				end
				8'h02	:																							//標準遠程幀[18 :0]
				begin
					remote_frame			<=	{1'b0,can_id,1'b1,1'b0,1'b0,user_data_len[3:0]}							;
					//							0 001_0101_1010 1 0 0 0001
					//							0 001_0101_1010 1 0 0 0001
					can_frame_len			<=	8'd19 																	;
				end
				8'h03	:																							//擴展遠程幀[38 :0]
				begin
					Ext_remote_frame		<=	{1'b0,can_id,1'b1,1'b1,Extend_can_id,1'b1,1'b0,1'b0,user_data_len[3:0]}	;
					can_frame_len			<=	8'd39																	;
				end
				default	:																							//標準數(shù)據(jù)幀[102:0]
				begin
					data_frame				<=	data_frame																;
					Ext_data_frame			<=	Ext_data_frame															;
					remote_frame			<=	remote_frame															;
					Ext_remote_frame		<=	Ext_remote_frame														;
					can_frame_len			<=	8'd19 + {1'b0,user_data_len[3:0],3'b0}									;	
				end
				endcase	
				can_tx						<=	'b0																		;
			end
			data_send 			:
			begin
				if((one_bit_cont == bit_flag_no - 1) && (can_continuity_data_flag == 0))
					data_frame				<=	{data_frame[81:0],1'b0}			;
				else if(one_bit_cont == bit_flag_no && (can_continuity_data_flag == 0))		
				begin		
					can_tx					<=	data_frame[82]					;
				end
				else if(one_bit_cont == bit_flag_no && can_continuity_data_flag)
				begin
					data_frame				<=	data_frame						;
					can_tx					<=	~can_tx							;
				end
				
				if((one_bit_cont == bit_flag_no) && ((send_cnt == can_frame_len - 1)))
				begin
					crc_data_buff			<=	crc_data_o						;
					can_tx					<=	crc_data_o[14]					;
				end
			end
			Ext_data_send 		:
			begin
				if((one_bit_cont == bit_flag_no - 1) && (can_continuity_data_flag == 0))
					Ext_data_frame			<=	{Ext_data_frame[101:0],1'b0}	;
				else if(one_bit_cont == bit_flag_no && (can_continuity_data_flag == 0))	
				begin
					can_tx					<=	Ext_data_frame[102]				;
				end
				else if(one_bit_cont == bit_flag_no && can_continuity_data_flag)
				begin
					Ext_data_frame			<=	Ext_data_frame					;
					can_tx					<=	~can_tx							;
				end

				if((one_bit_cont == bit_flag_no) && ((send_cnt == can_frame_len - 1)))
				begin
					crc_data_buff			<=	crc_data_o						;
					can_tx					<=	crc_data_o[14]					;
				end
			end
			remote_send 		:
			begin
				if((one_bit_cont == bit_flag_no - 1) && (can_continuity_data_flag == 0))
					remote_frame			<=	{remote_frame[17:0],1'b0}		;
				else if(one_bit_cont == bit_flag_no && (can_continuity_data_flag == 0))	
				begin
					can_tx					<=	remote_frame[18]				;
				end
				else if(one_bit_cont == bit_flag_no && can_continuity_data_flag)
				begin
					remote_frame			<=	remote_frame					;
					can_tx					<=	~can_tx							;
				end

				if((one_bit_cont == bit_flag_no) && ((send_cnt == can_frame_len - 1)))
				begin
					crc_data_buff			<=	crc_data_o						;
					can_tx					<=	crc_data_o[14]					;
				end
			end
			Ext_remote_send		:
			begin
				if((one_bit_cont == bit_flag_no - 1) && (can_continuity_data_flag == 0))
					Ext_remote_frame		<=	{Ext_remote_frame[37:0],1'b0}	;
				else if(one_bit_cont == bit_flag_no && (can_continuity_data_flag == 0))	
				begin
					can_tx					<=	Ext_remote_frame[38]			;
				end
				else if(one_bit_cont == bit_flag_no && can_continuity_data_flag)
				begin
					Ext_remote_frame		<=	Ext_remote_frame				;
					can_tx					<=	~can_tx							;
				end
				
				
				if((one_bit_cont == bit_flag_no) && ((send_cnt == can_frame_len - 1)))
				begin
					crc_data_buff			<=	crc_data_o						;
					can_tx					<=	crc_data_o[14]					;
				end
			end
			crc_send			:
			begin
				if((one_bit_cont == bit_flag_no - 1) && (can_continuity_data_flag == 0))
					crc_data_buff			<=	{crc_data_buff[13:0],1'b0}		;
				else if(one_bit_cont == bit_flag_no && (can_continuity_data_flag == 0) && send_cnt < 14)		
				begin
					can_tx					<=	crc_data_buff[14]				;
				end
				else if(one_bit_cont == bit_flag_no && (can_continuity_data_flag == 0) && send_cnt == 14)		
				begin
					can_tx					<=	'b1								;
				end
				else if(one_bit_cont == bit_flag_no && can_continuity_data_flag)
				begin
					Ext_remote_frame		<=	Ext_remote_frame				;
					can_tx					<=	~can_tx							;
				end
			end
			over				:
			begin
				data_frame 					<=	data_frame 						;
				Ext_data_frame 				<=	Ext_data_frame 					;
				remote_frame 				<=	remote_frame 					;
				Ext_remote_frame			<=	Ext_remote_frame				;
				crc_data_buff				<=	crc_data_buff					;
				can_frame_len				<=	can_frame_len					;
			end
			default				:
			begin
				can_tx						<=	'b1								;
				data_frame 					<=	data_frame 						;
				Ext_data_frame 				<=	Ext_data_frame 					;
				remote_frame 				<=	remote_frame 					;
				Ext_remote_frame			<=	Ext_remote_frame				;
				crc_data_buff				<=	crc_data_buff					;
				can_frame_len				<=	can_frame_len					;
			end
			endcase
		end
	end
	//crc 校驗使能 
	always@(posedge clk_can or negedge rst_n)
	begin
		if(~rst_n)
			crc_en			<=	'b0					;
		else
		begin
			case(cur_st)
			idle		:
				crc_en		<=	'b0					;
			data_send,Ext_data_send	,remote_send,Ext_remote_send	:
			begin
				if(one_bit_cont == 3 && (can_continuity_data_flag == 0))
					crc_en	<=	'b1					;
				else
					crc_en	<=	'b0					;
			end
			crc_send	:
				crc_en		<=	'b0					;
			over		:
				crc_en		<=	'b0					;
			default		:
				crc_en		<=	'b0					;
			endcase
		end
	end
	//crc 數(shù)據(jù)
	always@(posedge clk_can or negedge rst_n)
	begin
		if(~rst_n)
			crc_data_i		<=	'b0					;
		else
		begin
			case(cur_st)
			idle		:
				crc_data_i	<=	'b0					;
			init		:
				crc_data_i	<=	'b0					;
			data_send,Ext_data_send	,remote_send,Ext_remote_send	:
				crc_data_i	<=	can_tx				;
			crc_send	:
				crc_data_i	<=	'b0					;
			over		:
				crc_data_i	<=	'b0					;
			default		:
				crc_data_i	<=	'b0					;
			endcase
		end
	end
	//crc 軟復位
	always@(posedge clk_can or negedge rst_n)
	begin
		if(~rst_n)
			crc_en			<=	'b0					;
		else if(cur_st == idle)
			crc_rst			<=	'b1					;//未開始,復位crc
		else if(cur_st == init)
			crc_rst			<=	'b0					;
		else if(cur_st == over)
			crc_rst			<=	'b1					;//未開始,復位crc
	end
	//can發(fā)送使能
	always@(posedge clk_can or negedge rst_n)
	begin
		if(~rst_n)
			can_tx_en_flag			<=	'b0					;
		else if(cur_st == idle)				
			can_tx_en_flag			<=	'b0					;
		else if(cur_st == init)			
			can_tx_en_flag			<=	'b1					;
		else 
			can_tx_en_flag			<=	can_tx_en_flag		;
	end

	always @(posedge clk_can or negedge rst_n )
	begin
		if(rst_n==1'b0) 
		begin
			can_continuity_data			<= 5'b11111								;
			can_continuity_data_flag	<= 'b0									;
		end 
		else if ((one_bit_cont==(bit_flag_no+1)/2)&&(can_tx_en_flag==1)) 
		begin
			can_continuity_data			<= {can_continuity_data[3:0],can_tx}	;
		end	
		else if (((can_continuity_data==0)||(can_continuity_data==5'b11111))&&(one_bit_cont==(bit_flag_no+1)/2 + 1)) 
		begin
			can_continuity_data_flag	<= 'b1									;
		end 
		else if (can_tx_en_flag==0) 
		begin
			can_continuity_data			<= 5'b11111								;
			can_continuity_data_flag	<= 'b0									;
		end 
		else if (one_bit_cont == 6)
			can_continuity_data_flag	<= 'b0									;
	end 

	can_crc can_crc(	
		.crc_clk_i		(clk_can		)	,
		.rst_i			(rst_n  		)	,
		.en_i			(crc_en			)	,
		.data_i			(crc_data_i		)	,
		.crc_rst_i		(crc_rst		)	,
		.crc_reg_o		(crc_data_o		)	
	);
endmodule

CRC校驗

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2022/11/23 16:16:44
// Design Name: 
// Module Name: can_crc
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//
//https://github.com/AlxyF/CAN-fpga/blob/master/can_crc.v
module can_crc(	
	input 				crc_clk_i	,
	input 				rst_i		,
	input			    en_i		,
	input 				data_i		,
	input				crc_rst_i	,
	output reg [14:0]	crc_reg_o	
);

wire 	    crc_next;
wire [14:0] crc_tmp;
assign crc_next = data_i ^ crc_reg_o[14];
assign crc_tmp  = {crc_reg_o[13:0], 1'b0};

always @( posedge crc_clk_i or negedge rst_i or posedge crc_rst_i ) begin
	if ( rst_i == 1'b0 || crc_rst_i == 1'b1 ) begin
		crc_reg_o <= 15'h0;
	end else begin 
        if ( en_i ) begin	
            if ( crc_next ) begin 
                crc_reg_o <= crc_tmp ^ 15'h4599;
            end else begin
                crc_reg_o <= crc_tmp;
            end				
        end 
    end
end

endmodule

測試文件 tb

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2022/11/24 10:09:11
// Design Name: 
// Module Name: tb_can_send
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module tb_can_send(

    );
	wire				can_tx				;
	
	reg					clk_100m	    		;
	reg					rst_n       		;

	reg					can_send_en			;
	reg		[10:0]		can_id				;
	reg		[17:0]		Extend_can_id		;
	reg		[7:0]		can_mode			;
	reg		[3:0]		user_data_len		;
	reg		[63:0]		user_data			;
	
	wire					can_ack_out_low	;
	wire					can_id_out_en	;
	wire		[10:0]		can_id_out		;
	wire					can_data_out_en	;
	wire		[63:0]		can_data_out	;
	
	initial
	begin
		rst_n       	=	0				;
		clk_100m		=	0				;
		can_send_en		=	0				;
		can_id			=	0				;
		Extend_can_id	=	0				;
		can_mode		=	0				;
		user_data_len	=	0				;
		user_data		=	0				;
	#100;
		rst_n			=	1				;
	#100;
		can_id			=	11'h15a			;
		Extend_can_id	=	18'h2_1523		;
		can_mode		=	8'h02			;//幀模式 00 標準數(shù)據(jù)幀;01擴展數(shù)據(jù)幀;02標準遠程幀;03擴展遠程幀
		user_data_len	=	1				;
		user_data		=	64'h1a_1b_1c_1f_12_34_56_78		;
	#5000;
		can_send_en		=	1				;
	end
	always #5 clk_100m    =  ~clk_100m			;
	
	
	reg			[7:0]		can_div					;		//500倍分頻,一個數(shù)據(jù)位分為20份
	reg						can_clk_i				;	
	always @(posedge clk_100m or negedge rst_n )begin
		if(rst_n==1'b0) begin
			can_div	<= 'b0							;
		end else if (can_div==249) begin
			can_div	<= 'b0							;
		end	else  begin 
			can_div	<= can_div + 1'b1				;
		end	
	end 	
	
	always @(posedge clk_100m or negedge rst_n )begin
		if(rst_n==1'b0) begin
			can_clk_i	<= 'b0						;
		end else if (can_div==249) begin
			can_clk_i	<= ~can_clk_i 				;
		end	
	end
	
	can_send can_send(
		.clk_can	    	(can_clk_i	    	)	,
		.rst_n       		(rst_n       		)	,
		.can_tx				(can_tx				)	,
		.can_rx		        (can_ack_out_low	)	,
		.send_finish	    (send_finish	    )	,
		.send_error	        (send_error	        )	,
		.can_send_en		(can_send_en		)	,
		.can_id				(can_id				)	,	//can 	id
		.Extend_can_id		(Extend_can_id		)	,	//擴展	id
		.can_mode			(can_mode			)	,	//幀模式 00 標準數(shù)據(jù)幀;01擴展數(shù)據(jù)幀;02標準遠程幀;03擴展遠程幀
		.user_data_len		(user_data_len		)	,	//數(shù)據(jù)字段字節(jié)數(shù)
		.user_data			(user_data			)		//數(shù)據(jù)字段
    );
	
	//can_recive   can_rx
	can_recive	can_rx_init(
		.can_clk	    	(can_clk_i	    	)	,
		.rst_n       		(rst_n       		)	,
		.can_rx				(can_tx				)	,
		.can_ack_out_low	(can_ack_out_low	)	,
		.can_id_en_o		(can_id_out_en		)	,
		.can_id_o			(can_id_out			)	,
		.can_data_out_en	(can_data_out_en	)	,
		.can_data_out		(can_data_out		)	
    );
endmodule

仿真波形

(1)標準數(shù)據(jù)幀,數(shù)據(jù)段一個字節(jié)
發(fā)送端:
can標準幀fpga傳輸,CAN,vivado,fpga開發(fā)

接收端:
can標準幀fpga傳輸,CAN,vivado,fpga開發(fā)

(2)擴展數(shù)據(jù)幀,數(shù)據(jù)段一個字節(jié)
發(fā)送端:
can標準幀fpga傳輸,CAN,vivado,fpga開發(fā)

接收端:
can標準幀fpga傳輸,CAN,vivado,fpga開發(fā)

(3)標準遙控幀(遠程幀)
發(fā)送端:
can標準幀fpga傳輸,CAN,vivado,fpga開發(fā)

接收端:
can標準幀fpga傳輸,CAN,vivado,fpga開發(fā)

(4)擴展遙控幀(遠程幀)
發(fā)送端:
can標準幀fpga傳輸,CAN,vivado,fpga開發(fā)

接收端:
can標準幀fpga傳輸,CAN,vivado,fpga開發(fā)

參考、引用

https://blog.csdn.net/qq_40052606/article/details/115896679
https://github.com/AlxyF/CAN-fpga/blob/master/can_crc.v
https://blog.csdn.net/LEON1741/article/details/106199472文章來源地址http://www.zghlxwxcb.cn/news/detail-571595.html

到了這里,關(guān)于FPGA Verilog 控制CAN接收發(fā)送數(shù)據(jù)幀(標準/擴展),遙控幀(標準/擴展)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務器費用

相關(guān)文章

  • Kvaser Leaf light HS v2 | 如何使用Excel發(fā)送和接收CAN報文數(shù)據(jù)

    Kvaser Leaf light HS v2 | 如何使用Excel發(fā)送和接收CAN報文數(shù)據(jù)

    從1980年代,Kvaser就開始CAN產(chǎn)品的研發(fā),在相關(guān)產(chǎn)品開發(fā)領(lǐng)域有近40多年的經(jīng)驗,對CAN和相關(guān)總線技術(shù)有著非常深入的研究。我們將分享一些有趣的發(fā)現(xiàn)和一些特定情況的技術(shù)處理,歡迎關(guān)注??廣州智維電子科技有限公司??! 所有人的電腦上都有Microsoft Office,平時我們用

    2024年02月08日
    瀏覽(38)
  • FPGA串口接收解幀、并逐幀發(fā)送有效數(shù)據(jù)-2

    FPGA串口接收解幀、并逐幀發(fā)送有效數(shù)據(jù)-2

    工程實現(xiàn)的功能:FPGA串口接收到串口調(diào)試助手發(fā)來的數(shù)據(jù),將其數(shù)據(jù)解幀。判斷到正確的幀頭和幀尾之后,將有效數(shù)據(jù)存入rx_data中;另一方面發(fā)送端將有效數(shù)據(jù)逐幀發(fā)送出去。 參考:正點原子官方FPGA串口通信實驗 模塊構(gòu)成: 在原子哥的基礎上改的代碼。 添加了接收狀態(tài)機

    2024年02月05日
    瀏覽(21)
  • FPGA串口接收解幀、并逐幀發(fā)送有效數(shù)據(jù)——1

    FPGA串口接收解幀、并逐幀發(fā)送有效數(shù)據(jù)——1

    工程實現(xiàn)的功能:FPGA串口接收到串口調(diào)試助手發(fā)來的數(shù)據(jù),將其數(shù)據(jù)解幀。判斷到正確的幀頭和幀尾之后,將有效數(shù)據(jù)存入rx_data中;另一方面發(fā)送端將有效數(shù)據(jù)逐幀發(fā)送出去。 參考:正點原子官方FPGA串口通信實驗 模塊構(gòu)成: 在原子哥的基礎上改的代碼。 添加了接收狀態(tài)機

    2024年02月05日
    瀏覽(28)
  • FPGA自學筆記--串口通信發(fā)送多字節(jié)數(shù)據(jù)(verilog版)

    FPGA自學筆記--串口通信發(fā)送多字節(jié)數(shù)據(jù)(verilog版)

    ????????關(guān)于uart協(xié)議實現(xiàn)這部分大家可以參考我上一篇的博客?!禙PGA自學筆記--串口通信實現(xiàn)(vivadoverilog版)》。在上一篇博客中,主要實現(xiàn)了將單字節(jié)的數(shù)據(jù),我們其實就是用上一篇博客的模塊來實現(xiàn)多字節(jié)數(shù)據(jù)的發(fā)送。 ????????在真實的數(shù)據(jù)傳輸過程中,我們不

    2023年04月17日
    瀏覽(22)
  • 孩子都能學會的FPGA:第九課——多字節(jié)數(shù)據(jù)的發(fā)送和接收

    孩子都能學會的FPGA:第九課——多字節(jié)數(shù)據(jù)的發(fā)送和接收

    (原創(chuàng)聲明:該文是 作者的原創(chuàng) ,面向?qū)ο笫?FPGA入門者 ,后續(xù)會有進階的高級教程。宗旨是 讓每個想做FPGA的人輕松入門 , 作者不光讓大家知其然,還要讓大家知其所以然 !每個工程作者都搭建了全自動化的仿真環(huán)境,只需要雙擊 top_tb.bat 文件就可以完成整個的仿真(前

    2024年02月04日
    瀏覽(41)
  • STM32標準庫開發(fā)——串口發(fā)送/單字節(jié)接收

    STM32標準庫開發(fā)——串口發(fā)送/單字節(jié)接收

    串口發(fā)送信息 啟動串口一的時鐘 初始化對應串口一的時鐘,引腳,將TX引腳設置為復用推挽輸出。 配置串口一配置寄存器,設置波特率為9600,關(guān)閉硬件流控,不使用校驗位,數(shù)據(jù)長度為八字節(jié) 封裝串口發(fā)送字節(jié)函數(shù) 封裝串口發(fā)送字符串函數(shù) 封裝串口發(fā)送數(shù)組函數(shù) 封裝串口

    2024年01月23日
    瀏覽(25)
  • 【項目典型案例】-1-如何加快接收的CAN信號處理能力,提高發(fā)送CAN信號的響應

    點擊返回「《Autosar_BSW高階配置》總目錄」 案例背景( 共 5 頁精講 ): 在實際的項目當中,有時遇到這樣一個問題: 當 ECU 接收到一個 CAN 信號 A ,經(jīng)過 軟件 APP 層

    2023年04月25日
    瀏覽(29)
  • stm32與openmv的相互發(fā)送與接收(基于標準庫)

    stm32與openmv的相互發(fā)送與接收(基于標準庫)

    提示:文章寫完后,目錄可以自動生成,如何生成可參考右邊的幫助文檔 文章目錄 目錄 文章目錄 前言 一、硬件連接 二、數(shù)據(jù)包傳輸 三、openmv發(fā)送stm32端接收 1.openmv端(發(fā)送函數(shù)) 2.stm32端(接收函數(shù)) 串口中斷服務函數(shù): 數(shù)據(jù)讀取函數(shù): 數(shù)據(jù)處理函數(shù): ?main函數(shù)oled屏幕

    2024年02月17日
    瀏覽(19)
  • 基于FPGA的CAN通訊verilog代碼設計

    基于FPGA的CAN通訊verilog代碼設計

    FPAGA本篇文章參考github網(wǎng)站的開源項目can-FPGA-master編寫改進 在調(diào)試過程中,發(fā)現(xiàn)該項目無法在quartus pro13.0的環(huán)境下運行通過,代碼存在錯誤,并且對于EP4系列的芯片來說有太多的IO口,無法在燒錄,所以筆者對此進行了改進。 ?can_top模塊 can_tx傳輸數(shù)據(jù)模塊 can_rx接收數(shù)據(jù)模塊

    2024年02月08日
    瀏覽(23)
  • 基于fpga的ddr3讀寫控制,純verilog實現(xiàn),能實現(xiàn)多通道圖像數(shù)據(jù)讀寫控制

    基于fpga的ddr3讀寫控制,純verilog實現(xiàn),能實現(xiàn)多通道圖像數(shù)據(jù)讀寫控制

    基于fpga的ddr3讀寫控制,純verilog實現(xiàn),能實現(xiàn)多通道圖像數(shù)據(jù)讀寫控制,模塊接口清晰,可移植性高. 基于FPGA的DDR3讀寫控制是一項重要的技術(shù),它為多通道圖像數(shù)據(jù)的讀寫提供了高效的解決方案。本文將介紹一種純Verilog實現(xiàn)的DDR3讀寫控制模塊,旨在實現(xiàn)模塊接口清晰、可移

    2024年04月12日
    瀏覽(40)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包