FPGA Verilog 控制CAN接收发送数据帧(标准/扩展),遥控帧(标准/扩展)

这篇具有很好参考价值的文章主要介绍了FPGA Verilog 控制CAN接收发送数据帧(标准/扩展),遥控帧(标准/扩展)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

说明

使用Verilog接收发送,CAN数据帧和远程帧,由于条件有限,并没有实际下载到办卡上验证,只做了仿真验证,后续准确性验证后再行修改。

CAN帧格式

(1)标准数据帧:
can标准帧fpga传输,CAN,vivado,fpga开发(2)扩展数据帧:
can标准帧fpga传输,CAN,vivado,fpga开发
(3)标准遥控帧
can标准帧fpga传输,CAN,vivado,fpga开发
与数据帧的区别就是没有数据字段;
(4)扩展遥控帧
can标准帧fpga传输,CAN,vivado,fpga开发

系统时钟为100Mhz,CAN通信频率是10KHz,在tb处做了分频得到200Khz的时钟,为了能够稳定获取数据,所以需要在数据中间部位取数,所以增加了一个时钟计数,在cnt=10左右进行取数。

CAN接收

说明:CAN数据帧有直流平衡,即连续5个0后面必须插入一个1,连续5个1后面必须插入一个0,所以在接收的时候检测到连续5个0或者5个1后需要将后面的一个字节放弃。
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				,	//	数据	输出使能
	output		reg			[63:0]			can_data_out					//	数据
    );
	
	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数据帧

	reg	 				   				crc_en							;
	reg									crc_data_i						;
	reg									crc_rst							;
	wire 				[14:0]			crc_data_o						;
	
	reg									crc_success						;
	//CRC校验结果
	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			;	//标准数据帧
			2'b10:		can_mode_o	<=	8'h01			;	//扩展数据帧
			2'b01:		can_mode_o	<=	8'h02			;	//标准远程帧
			2'b11:		can_mode_o	<=	8'h03			;	//扩展远程帧
			default	:	can_mode_o	<=	8'h00			;	//标准数据帧
			endcase
		end	
	end 
	
	localparam			st_idle		 			= 11'd0				,	//状态机初始化
						st_sof		 			= 11'd1				,	//开始帧头第一位SOF
						st_id		 			= 11'd2				,	//包ID,仲裁字段
						Extended_id	 			= 11'd3				,	//扩展帧ID
						standard_data_ctrl		= 11'd4				,	//标准帧数据段
						remote_ctrl	 			= 11'd5				,	//标准帧控制段
						Extend_remote_ctrl	 	= 11'd6				,	//扩展远程帧控制段
						st_data		 			= 11'd7				,	//数据段
						st_crc		 			= 11'd8				,	//CRC段
						st_ack		 			= 11'd9				,	//ACK段  确认间隙位1bit , 确认定界符1bit
						st_eof		 			= 11'd10			,	//帧结束段
						st_end		 			= 11'd11			;	//状态机结束状态
	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		:													//低电平持续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)										//标准数据帧
							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)										//扩展数据帧
						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							;//数据帧
					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							;//数据帧
					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))			//帧结束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
	//判断连续5个1 或者连续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数据
	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 接收数据字段
	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 结束 输出使能
	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 数据
	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发送

can_rx	:接收端发送的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 标准数据帧;01扩展数据帧;02标准远程帧;03扩展远程帧
	input		wire	[3:0]	user_data_len		,	//数据字段字节数
	input		wire	[63:0]	user_data				//数据字段
    );
	/*
	标准数据帧[107:0]
	扩展数据帧[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发送帧长度
		
	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	:												//标准数据帧[82	:0]
					cur_st				<=	data_send					;
				8'h01	:												//扩展数据帧[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	:												//标准数据帧[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信号,输出是否发送完成
	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计数 延时计数
	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	:																						//标准数据帧[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	:																							//扩展数据帧[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  (字节数)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	:																							//标准数据帧[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 数据
	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发送使能
	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 标准数据帧;01扩展数据帧;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倍分频,一个数据位分为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 标准数据帧;01扩展数据帧;02标准远程帧;03扩展远程帧
		.user_data_len		(user_data_len		)	,	//数据字段字节数
		.user_data			(user_data			)		//数据字段
    );
	
	//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)标准数据帧,数据段一个字节
发送端:
can标准帧fpga传输,CAN,vivado,fpga开发

接收端:
can标准帧fpga传输,CAN,vivado,fpga开发

(2)扩展数据帧,数据段一个字节
发送端:
can标准帧fpga传输,CAN,vivado,fpga开发

接收端:
can标准帧fpga传输,CAN,vivado,fpga开发

(3)标准遥控帧(远程帧)
发送端:
can标准帧fpga传输,CAN,vivado,fpga开发

接收端:
can标准帧fpga传输,CAN,vivado,fpga开发

(4)扩展遥控帧(远程帧)
发送端:
can标准帧fpga传输,CAN,vivado,fpga开发

接收端:
can标准帧fpga传输,CAN,vivado,fpga开发

参考、引用

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文章来源地址https://www.toymoban.com/news/detail-571595.html

到了这里,关于FPGA Verilog 控制CAN接收发送数据帧(标准/扩展),遥控帧(标准/扩展)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Kvaser Leaf light HS v2 | 如何使用Excel发送和接收CAN报文数据

    从1980年代,Kvaser就开始CAN产品的研发,在相关产品开发领域有近40多年的经验,对CAN和相关总线技术有着非常深入的研究。我们将分享一些有趣的发现和一些特定情况的技术处理,欢迎关注❤️广州智维电子科技有限公司❤️! 所有人的电脑上都有Microsoft Office,平时我们用

    2024年02月08日
    浏览(32)
  • FPGA串口接收解帧、并逐帧发送有效数据-2

    工程实现的功能:FPGA串口接收到串口调试助手发来的数据,将其数据解帧。判断到正确的帧头和帧尾之后,将有效数据存入rx_data中;另一方面发送端将有效数据逐帧发送出去。 参考:正点原子官方FPGA串口通信实验 模块构成: 在原子哥的基础上改的代码。 添加了接收状态机

    2024年02月05日
    浏览(27)
  • FPGA串口接收解帧、并逐帧发送有效数据——1

    工程实现的功能:FPGA串口接收到串口调试助手发来的数据,将其数据解帧。判断到正确的帧头和帧尾之后,将有效数据存入rx_data中;另一方面发送端将有效数据逐帧发送出去。 参考:正点原子官方FPGA串口通信实验 模块构成: 在原子哥的基础上改的代码。 添加了接收状态机

    2024年02月05日
    浏览(30)
  • FPGA自学笔记--串口通信发送多字节数据(verilog版)

            关于uart协议实现这部分大家可以参考我上一篇的博客。《FPGA自学笔记--串口通信实现(vivadoverilog版)》。在上一篇博客中,主要实现了将单字节的数据,我们其实就是用上一篇博客的模块来实现多字节数据的发送。         在真实的数据传输过程中,我们不

    2023年04月17日
    浏览(30)
  • 孩子都能学会的FPGA:第九课——多字节数据的发送和接收

    (原创声明:该文是 作者的原创 ,面向对象是 FPGA入门者 ,后续会有进阶的高级教程。宗旨是 让每个想做FPGA的人轻松入门 , 作者不光让大家知其然,还要让大家知其所以然 !每个工程作者都搭建了全自动化的仿真环境,只需要双击 top_tb.bat 文件就可以完成整个的仿真(前

    2024年02月04日
    浏览(47)
  • STM32标准库开发——串口发送/单字节接收

    串口发送信息 启动串口一的时钟 初始化对应串口一的时钟,引脚,将TX引脚设置为复用推挽输出。 配置串口一配置寄存器,设置波特率为9600,关闭硬件流控,不使用校验位,数据长度为八字节 封装串口发送字节函数 封装串口发送字符串函数 封装串口发送数组函数 封装串口

    2024年01月23日
    浏览(37)
  • 【项目典型案例】-1-如何加快接收的CAN信号处理能力,提高发送CAN信号的响应

    点击返回「《Autosar_BSW高阶配置》总目录」 案例背景( 共 5 页精讲 ): 在实际的项目当中,有时遇到这样一个问题: 当 ECU 接收到一个 CAN 信号 A ,经过 软件 APP 层

    2023年04月25日
    浏览(36)
  • stm32与openmv的相互发送与接收(基于标准库)

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 目录 文章目录 前言 一、硬件连接 二、数据包传输 三、openmv发送stm32端接收 1.openmv端(发送函数) 2.stm32端(接收函数) 串口中断服务函数: 数据读取函数: 数据处理函数:  main函数oled屏幕

    2024年02月17日
    浏览(25)
  • 基于FPGA的CAN通讯verilog代码设计

    FPAGA本篇文章参考github网站的开源项目can-FPGA-master编写改进 在调试过程中,发现该项目无法在quartus pro13.0的环境下运行通过,代码存在错误,并且对于EP4系列的芯片来说有太多的IO口,无法在烧录,所以笔者对此进行了改进。  can_top模块 can_tx传输数据模块 can_rx接收数据模块

    2024年02月08日
    浏览(34)
  • 基于fpga的ddr3读写控制,纯verilog实现,能实现多通道图像数据读写控制

    基于fpga的ddr3读写控制,纯verilog实现,能实现多通道图像数据读写控制,模块接口清晰,可移植性高. 基于FPGA的DDR3读写控制是一项重要的技术,它为多通道图像数据的读写提供了高效的解决方案。本文将介绍一种纯Verilog实现的DDR3读写控制模块,旨在实现模块接口清晰、可移

    2024年04月12日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包