基于FPGA的CAN通讯verilog代码设计

这篇具有很好参考价值的文章主要介绍了基于FPGA的CAN通讯verilog代码设计。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

FPAGA本篇文章参考github网站的开源项目can-FPGA-master编写改进

在调试过程中,发现该项目无法在quartus pro13.0的环境下运行通过,代码存在错误,并且对于EP4系列的芯片来说有太多的IO口,无法在烧录,所以笔者对此进行了改进。

 can_top模块

// Extended CAN format
//扩展格式
// 1(SOF)+11(Arb1)+2(SDR,IDE)+11(Arb2)+1(RTR)+1(r1)+1(r0)+4(Control)+64(Data)+15(CRC Field)+1(CRC Delimeter)+2(Ack)+7(EoF)+3(Idle)
//1位+11位ID+1位SDR&1位IDE+18位ID+1位RTR+1位r1+1位1r0+4位control+64位data+15位CRCsequence+CRC界定律+(1位ACK槽+1位ACK界定符)+(7位EOF)

module can_top
#(
    parameter CLK_FREQ      = 'd9600, //设置波特率
    parameter CAN_CLK_FREQ  = 'd50_000_000,    //设置can信号的波特率
    
    // DMA
    parameter DATA_WIDTH        = 32,           //数据宽度32位*2
    parameter ADDR_WIDTH        = 20,           //设置写入数据的宽度为20
    parameter CLK_FREQUENCY     = 200_000_000,  //
    parameter OP_CYCLE_NS       = 35,           //
    
    //
    parameter [5:0]  LOCAL_ADDRESS = 6'b000101,
    
    parameter [19:0] ADDR_SETTING_SEND      = 20'hA0001,            //4'ha表示4位十六进制数字a(二进制1010)
    parameter [19:0] ADDR_DATA_SEND_1       = 20'hA0002,
    parameter [19:0] ADDR_DATA_SEND_2       = 20'hA0003,
    
    parameter [19:0] addr_setting_recieved  = 20'hB0001,            // 
    parameter [19:0] addr_data_recieved_1   = 20'hB0002,
    parameter [19:0] addr_data_recieved_2   = 20'hB0003
)(   
    input       rst_i,
    input       clk_i,
    
    input       rx_i,
    output      rx_busy,
    // output      rx_received,
    
    output tx_o,
    output tx_busy,

    input  tx_send_i            //绑定针脚key1,使得其按下代表开始发送数据
   
    // <DMA> 直接存储器访问
    // wire reg [DATA_WIDTH-1 : 0] data_wr,  //写入数据
    // wire reg [ADDR_WIDTH-1 : 0] addr_wr,  //写入地址
    // reg                    wr_en,    //写入信号
    // wire                   wr_done,  //写入完成
    // wire                   wr_busy,  //写入占用
    

    // output reg                  rd_en,    //读取信号
    // wire                        rd_done,  //完成
    // wire                        rd_busy,  //占用 
    // wire     [63:0]             tx_data_i

  // tx fields
    //input             tx_message_type,
    //input [5:0]       tx_address_remote,
      
    // - output CAN frame LLC/DLC data
         
    // <test>
    // output test_clk_can,                
    // output [2:0]  test_can_state,       
    // output [7:0]  test_can_tx_state,    
    // output [7:0]  test_bit_count,       
    // output [3:0]  test_bit_pol_count,   
    // output reg    bit_stuffed,          
    // output        test_last_bit,        
    
    // output [7:0]  test_rx_state,
    // output [11:0] test_rx_quant_count,
    // output [7:0]  test_rx_bit_count,
    // output [3:0]  test_rx_bit_pol_count,
    // output        test_rx_bit_stuffed,
    // output [6:0]  test_rx_count,
    // output test_rx_rx,
    // output test_sample
    // </test>
);
// <test>
// wire test_arbi;
reg count_rst;
// assign test_sample              = ( CAN_STATE == CAN_PAUSE ) ? 1'b0 : 1'b1;
// assign test_can_state           = CAN_STATE;
// </test>

wire        clk_can;
reg [63:0]  data_to_send;
wire     [DATA_WIDTH-1 : 0] data_rd;    //读取数据

//<input>
reg        tx_message_type      = 1'b0;
reg [5:0]  local_address        = 6'b000101;        // 6'h2A        
reg [5:0]  remote_address       = 6'b100010;
reg [1:0]  tx_handshake         = 2'b10;
reg [1:0]  tx_atribute          = 2'b10;
reg [3:0]  tx_expand_count      = 4'b1011;
reg [7:0]  tx_cmd_data_sign     = 8'b1111_0101;
reg [3:0]  tx_dlc               = 4'b1001;

reg [63:0] tx_data;
reg [31:0] can_send_setting;                    //后面将其等于data_rd        
//</input>

//<output>
reg  [63:0] rx_data_reg;
wire [63:0] rx_data;
//</output>

reg  tx_start;
reg  rx_start;
reg  tx_pending;                                        //tx挂起
reg  init;

wire tx_o_tx;
wire tx_o_rx;

wire frame_sent;
wire can_is_free;
wire rx_frame_ready;



//<CAN MAIN FLOW>
assign tx_o = CAN_STATE == CAN_TX ? tx_o_tx :
            ( CAN_STATE == CAN_RX ? tx_o_rx : 1'b1 );   //判断can_state的状态,如果是TX输出则tx_o=tx_o_tx,
                                                        //若否则判断是否为RX写入状态,若是则tx_o为tx_o_rx,若否则tx_o=1'b1;

localparam  CAN_START_INIT = 0;
localparam  CAN_INIT       = 1;
localparam  CAN_IDLE       = 2;
localparam  CAN_PAUSE      = 3;
localparam  CAN_START_RX   = 4;
localparam  CAN_RX         = 5;
localparam  CAN_START_TX   = 6;
localparam  CAN_TX         = 7;
localparam  CAN_TEST_START = 8;
localparam  CAN_TEST       = 9;

reg [3:0] CAN_STATE;  
reg [10:0] count;                               //11位的ID?

always @( posedge clk_can or negedge rst_i ) begin
    if ( rst_i == 1'b0 ) begin
        
    end else begin
        if ( count_rst == 1'b1 ) begin
            count <= 11'd0;
        end else begin
            count <= count + 1'b1;
        end
    end
end
        
always @( posedge clk_i or negedge rst_i ) begin
    if ( rst_i == 1'b0 ) begin
        CAN_STATE       <= CAN_IDLE;
        tx_start        <= 1'b0;                                                //输出和输入的
        rx_start        <= 1'b0;
        count_rst       <= 1'b0;
        init            <= 1'b0;
    end else begin
        case ( CAN_STATE )
        CAN_START_INIT: begin
                            init        <= 1'b1;
                            CAN_STATE   <= CAN_INIT;
                        end                                                     //can初始化 can_state等于can_init
        CAN_INIT:       begin
                            init        <= 1'b0;
                            CAN_STATE   <= CAN_IDLE;                            //can变化为can_idle空闲
                        end
        CAN_IDLE:       begin                              
                            if ( tx_pending == 1'b1 ) begin                     //如果tx挂起 那么开始tx传输数据
                                CAN_STATE   <= CAN_START_TX;                    //can开始发送数据
                                tx_start    <= 1'b1;
                                rx_start    <= 1'b0;
                            end else begin
                                CAN_STATE   <= CAN_START_RX;                    //can开始接收数据
                                rx_start    <= 1'b1;
                            end
                        end
        CAN_PAUSE:      begin                           
                            if ( tx_pending == 1'b1 ) begin                     //tx挂起
                                if ( tx_lost_arbitrage == 1'b1 ) begin
                                    if ( count == 11'd11 ) begin
                                        count_rst <= 1'b1;
                                        CAN_STATE <= CAN_START_TX;
                                    end
                                end else begin
                                    if ( count == 11'd2 ) begin
                                        count_rst <= 1'b1;
                                        CAN_STATE <= CAN_START_TX;
                                    end
                                end
                            end else begin
                                if ( count == 11'd2 ) begin
                                    CAN_STATE <= CAN_START_RX;
                                end
                            end
                        end
        CAN_START_RX:   begin                            
                            if ( rx_busy == 1'b1 ) begin
                                CAN_STATE   <= CAN_RX;
                            end else begin 
                                CAN_STATE   <= CAN_IDLE;
                            end
                        end
        CAN_RX:         begin                             
                            if ( rx_busy == 1'b0 ) begin
                                rx_start    <= 1'b0;
                                count_rst   <= 1'b0;
                                CAN_STATE   <= CAN_PAUSE;   
                            end
                        end
        CAN_START_TX:   begin                               
                            if ( tx_busy == 1'b1 ) begin
                                CAN_STATE   <= CAN_TX;
                            end
                        end
        CAN_TX:         begin
                            if ( frame_sent == 1'b1 ) begin
                                tx_start    <= 1'b0;
                                count_rst   <= 1'b1;
                                CAN_STATE   <= CAN_PAUSE;
                            end
                        end
        // CAN_TEST_START: begin                        
        //                     tx_start    <= 1'b1;
        //                     if ( rx_busy == 1'b1 ) begin
        //                         CAN_STATE   <= CAN_TEST;
        //                     end
        //                 end
        // CAN_TEST:       begin
        //                     tx_start    <= 1'b0;
        //                     if ( rx_busy == 0 ) begin
        //                         rx_start  <= 1'b0;
        //                     end
        //                 end
        endcase
    end
end
//</CAN MAIN FLOW>

//<TX DATA DMA READ>
localparam  TX_READ_IDLE            = 0; 
localparam  TX_START_READ_SETTING   = 1;
localparam  TX_READ_SETTING         = 2;
localparam  TX_START_READ_DATA_1    = 3;
localparam  TX_READ_DATA_1          = 4;
localparam  TX_START_READ_DATA_2    = 5;
localparam  TX_READ_DATA_2          = 6;
localparam  TX_START_SEND_DATA      = 7;
localparam  TX_SEND_DATA            = 8;

reg [3:0] TX_DMA_STATE;  


localparam  RX_WRITE_IDLE            = 0; 
localparam  RX_START_WRITE_SETTING   = 1;
localparam  RX_WRITE_SETTING         = 2;
localparam  RX_START_WRITE_DATA_1    = 3;
localparam  RX_WRITE_DATA_1          = 4;
localparam  RX_START_WRITE_DATA_2    = 5;
localparam  RX_WRITE_DATA_2          = 6;
localparam  RX_START_SEND_DATA       = 7;
localparam  RX_SEND_DATA             = 8;

reg [3:0] RX_DMA_STATE;
//<RX DATA DMA READ>

always @( posedge clk_i or negedge rst_i ) begin
    if ( !rst_i ) begin
        can_send_setting    <= 32'd0;
        tx_data             <= 64'h0;
        // rx_data             <= 64'h0;
        tx_pending          <= 1'b0;
        rx_data_reg         <= 64'h0;       
    end 
    else begin
        case ( TX_DMA_STATE ) 
        TX_READ_IDLE:           begin
                                    if ( tx_send_i == 1'b1  ) begin
                                         TX_DMA_STATE <= TX_START_READ_SETTING;
                                    end
                                end
        TX_START_READ_SETTING:  begin
                                    can_send_setting  <= data_rd;
                                    // rd_en             <= 1'b1;
                                    TX_DMA_STATE      <= TX_READ_SETTING;
                                end
        TX_READ_SETTING:        begin
                                    // rd_en             <= 1'b0;
                                    TX_DMA_STATE      <= TX_START_READ_DATA_1;
                                end
        TX_START_READ_DATA_1:   begin
                                    tx_data[63:32]    <= data_rd;
                                    // rd_en             <= 1'b1;
                                    TX_DMA_STATE      <= TX_READ_DATA_1;    
                                end
        TX_READ_DATA_1:         begin
                                    // rd_en             <= 1'b0;
                                    TX_DMA_STATE      <= TX_START_READ_DATA_2;
                                end
        TX_START_READ_DATA_2:   begin
                                    tx_data[31:0]     <= data_rd;
                                    // rd_en             <= 1'b1;
                                    TX_DMA_STATE      <= TX_READ_DATA_2;  
                                end
        TX_READ_DATA_2:         begin
                                    // rd_en             <= 1'b0;
                                    TX_DMA_STATE      <= TX_START_SEND_DATA;  
                                end
        TX_START_SEND_DATA:     begin
                                    tx_pending        <= 1'b1;
                                    TX_DMA_STATE      <= TX_SEND_DATA;
                                end
        TX_SEND_DATA:           begin
                                    if ( tx_busy ) begin
                                        tx_pending    <= 1'b0;
                                        TX_DMA_STATE  <= TX_READ_IDLE;
                                    end
                                end
        endcase                       
        end
    end 

//</TX DATA DMA READ>



/*   错误原因,不能在同一个always的语句中定义reg型的变量    */

always @( posedge clk_i or negedge rst_i ) begin
    if ( !rst_i  ) begin
        rx_data_reg <= 64'h0;
    end else begin
        case ( RX_DMA_STATE ) 
        RX_WRITE_IDLE:          begin
                                    if ( tx_send_i == 1'b1  ) begin
                                         RX_DMA_STATE <= RX_START_WRITE_SETTING;
                                    end
                                end
        RX_START_WRITE_SETTING: begin
              //这一块有问题
                                    can_send_setting  <= data_rd;
                                    // rd_en             <= 1'b1;
                                    RX_DMA_STATE      <= RX_WRITE_SETTING;
                                end
        RX_WRITE_SETTING:       begin
                                    // rd_en             <= 1'b0;
                                    RX_DMA_STATE      <= RX_START_WRITE_DATA_1;
                                end
        RX_START_WRITE_DATA_1:  begin

                                    rx_data_reg[63:32]    <= data_rd;
                                    // rd_en             <= 1'b1;
                                    RX_DMA_STATE      <= RX_WRITE_DATA_1;    
                                end
        RX_WRITE_DATA_1:        begin
                                    // rd_en             <= 1'b0;
                                    RX_DMA_STATE      <= RX_START_WRITE_DATA_2;
                                end
        RX_START_WRITE_DATA_2:  begin

                                    rx_data_reg[31:0]     <= data_rd;
                                    // rd_en             <= 1'b1;
                                    RX_DMA_STATE      <= RX_WRITE_DATA_2;  
                                end
        RX_WRITE_DATA_2:        begin
                                    // rd_en             <= 1'b0;
                                    RX_DMA_STATE      <= RX_START_SEND_DATA;  
                                end

        endcase                       
    end
end


can_tx #(
    .CLK_FREQ               (CLK_FREQ),
    .CAN_CLK_FREQ           (CAN_CLK_FREQ)
)can_tx_instance
(   
    .rst_i                  (rst_i),    
    .clk_i                  (clk_i),
    .clk_can_i              (clk_can),
    .tx_start_i             (tx_start),
    .tx_lost_arbitrage_o    (tx_lost_arbitrage),
    .tx_acknowledged_o      (tx_acknowledged),
    .frame_sent_o           (frame_sent),
    
    .rx_i                   (rx_i),
    .tx_o                   (tx_o_tx),
    .tx_busy_o              (tx_busy),
    
    .message_type           (tx_message_type),
    .local_address          (local_address),
    .remote_address         (remote_address),
    .handshake              (tx_handshake),
    .expand_count           (tx_expand_count),
    .cmd_data_sign          (tx_cmd_data_sign),
    .dlc                    (tx_dlc),
    .tx_data                (tx_data)
    //test
    // .test_tx_state          (test_can_tx_state),
    // .test_bit_count         (test_bit_count),
    // .test_bit_pol_count     (test_bit_pol_count),
    // .test_arbi              (test_arbi)

);

can_rx #(
    .CLK_FREQ               (CLK_FREQ),
    .CAN_CLK_FREQ           (CAN_CLK_FREQ)
) can_rx_instance
(
    .rst_i                  (rst_i),
    .rx_i                   (rx_i),
    .tx_o                   (tx_o_rx),
    .clk_i                  (clk_i),
    .clk_can_i              (clk_can),
    .can_clk_sync_o         (can_clk_sync),
    .rx_start_i             (rx_start),
    .rx_busy_o              (rx_busy),
    .init_i                 (init),
    .rx_frame_ready_o       (rx_frame_ready),
    
    .local_address           (LOCAL_ADDRESS),
    
    
    //<data_out>
    .rx_data             (rx_data)
    
    //</data_out>
    
    //test
    // .test_rx_state       (test_rx_state),
    // .test_quant_count    (test_rx_quant_count),
    // .test_bit_count      (test_rx_bit_count),
    // .test_bit_pol_count  (test_rx_bit_pol_count),
    // .test_rx_bit_stuffed (test_rx_bit_stuffed),
    // .test_rx_count       (test_rx_count),
    // .test_rx_rx          (test_rx_rx)
    //.test_sample_1        (test_sample)
);
                            
can_clk #(  
    .FREQ_I         (CLK_FREQ),
    .FREQ_O         (CAN_CLK_FREQ)
) can_clk_instance
(   
    .rst_i          (rst_i),
    .clk_i          (clk_i),
    .sync_i         (can_clk_sync),
    .can_clk_o      (clk_can) 
);
    
endmodule

can_tx传输数据模块

module can_tx
#(
    parameter CLK_FREQ      = 'd9600,
    parameter CAN_CLK_FREQ  = 'd50_000_000,
    parameter QUANTS        = CLK_FREQ/CAN_CLK_FREQ
)(
	input rst_i,
    input clk_i,	
	input clk_can_i,
	input tx_start_i,
	
    output reg frame_sent_o,
	output reg tx_lost_arbitrage_o,
	output     tx_acknowledged_o,
	
	input           message_type,
	input [5:0]     local_address,
	input [5:0]     remote_address,
	input [1:0]     handshake,
	input [3:0]     expand_count,
	input [7:0]     cmd_data_sign,
	input [3:0]     dlc,
	input [63:0]    tx_data,
	
	input  rx_i,
	output tx_o,
    output reg tx_busy_o
	
	//test
	// output [7:0] test_tx_state,
	// output [7:0] test_bit_count,
	// output [2:0] test_bit_pol_count,
    // output reg test_arbi
);
//<test>
// assign test_tx_state      = TX_STATE;
// assign test_bit_count     = bit_count_reg;  
// assign test_bit_pol_count = bit_pol_count;
//</test>

reg [6:0]  count;
reg [11:0] quant_count;

//<CRC>
wire [14:0] crc;
wire crc_en;
assign crc_en = ( TX_STATE == TX_IDLE 		    || 
                TX_STATE == TX_START_OF_FRAME   ||
                TX_STATE == TX_BIT_STUFF 	    ||
                TX_STATE == TX_CRC ) ? 1'b0 : 1'b1;
						
reg crc_rst_i;
can_crc can_crc_instance
(
	.crc_clk_i  (clk_can_i),
	.rst_i		(rst_i),
	.data_i		(tx_o),
	.en_i		(crc_en),
	.crc_reg_o	(crc),
	.crc_rst_i  (crc_rst_i)
);
//</CRC>

//<bit stuff>
reg [7:0] 	bit_count_reg;					
reg [2:0] 	bit_pol_count;
reg 		last_bit;
reg 		bit_stuff_bit; 
//</bit stuff>

// <arbitrage>

// </arbitrage>

// 0xAx - MAC, 0xB-x - LLC
localparam TX_IDLE          		= 8'h00;
localparam TX_BIT_STUFF    		    = 8'h0B;
 
localparam TX_START_OF_FRAME  	    = 8'hA1;
localparam TX_MESSAGE_TYPE  		= 8'hB1;
localparam TX_ADDRESS_LOCAL     	= 8'hB2;
localparam TX_ADDRESS_REMOTE        = 8'hB3;
localparam TX_SRR    		 		= 8'hA2;
localparam TX_IDE  		    		= 8'hA3;
localparam TX_HANDSHAKING_P 		= 8'hB4;
localparam TX_ATRIBUTE_RESERVED	    = 8'hB5;
localparam TX_EXPAND_COUNT  		= 8'hB6;
localparam TX_CMD_DATA_SIGN 		= 8'hB7;
localparam TX_RTR				    = 8'hA4;
localparam TX_RESERVED				= 8'hA5;
localparam TX_DLC				 	= 8'hB8;
localparam TX_DATA			 		= 8'hB9;
localparam TX_CRC 					= 8'hA6;
localparam TX_CRC_DELIMITER		    = 8'hA7;
localparam TX_ACK_SLOT				= 8'hA8;
localparam TX_ACK_DELIMITER		    = 8'hA9;
localparam TX_END_OF_FRAME			= 8'hAA;

reg[7:0] TX_STATE = TX_IDLE;
reg[7:0] NEXT_TX_STATE;
						
always @( posedge clk_can_i or negedge rst_i ) begin
	if ( rst_i == 1'b0 ) begin
		TX_STATE                <= 8'h0;
		NEXT_TX_STATE 			<= TX_IDLE;
		
		bit_count_reg 			<= 8'd0;		
		count 					<= 7'd0;	
        bit_pol_count 			<= 3'd1;
		bit_stuff_bit			<= 1'b0;
        last_bit			    <= 1'b1;
		crc_rst_i 				<= 1'b0;
        tx_busy_o               <= 1'b0;
        frame_sent_o            <= 1'b0;
	end else begin
		if ( TX_STATE != TX_IDLE  ) begin
			last_bit 		<= tx_o;
			bit_count_reg   <= bit_count_reg + 1'b1;		
		end
		case ( TX_STATE )
		TX_IDLE: 			begin                               
                                if ( tx_start_i ) begin									                                   
                                    tx_busy_o           <= 1'b1;

                                    count               <= 7'd0;	
                                    bit_count_reg 	    <= 8'd0;
                                    frame_sent_o        <= 1'b0;
                                    TX_STATE		    <= TX_START_OF_FRAME;
                                end
							end																		
		// <MAC-level>
		
		// every 5 consequent same polarity bit add one reversed(not for CRC delimiter, ACK field and EOF)
		// 1 bit
		TX_BIT_STUFF: 		begin		
									TX_STATE 		<= NEXT_TX_STATE;	
							end				
		// 1 bit 
		TX_START_OF_FRAME:  begin											
									TX_STATE 	  	<= TX_MESSAGE_TYPE;
									NEXT_TX_STATE 	<= TX_MESSAGE_TYPE;
									crc_rst_i       <= 1'b0;							
							end					
		
		//	IDE and SRR are placed between 18 and 17 bit of 29 bit extended arbitration field
		// 1 bit
		TX_SRR:				begin
									TX_STATE 		<= TX_IDE;
									NEXT_TX_STATE 	<= TX_IDE;
							end
		// 1 bit
		TX_IDE:				begin
									TX_STATE 		<= TX_ADDRESS_REMOTE;
									NEXT_TX_STATE 	<= TX_ADDRESS_REMOTE;
							end
		// -- RTR-bit is 0 in the Data Frame, in the Remote Frame is 1 there and there is no Data Field 
		// in Remote Frame The DLC field indicates the data length of the requested message (not the transmitted one)
		// 1 bit
		TX_RTR:				begin
									TX_STATE 		<= TX_RESERVED;
									NEXT_TX_STATE 	<= TX_RESERVED;
							end
		// -- r1, r0 Reserved bits which must be set dominant (0), but accepted as either dominant or recessive 
		TX_RESERVED:		begin
                                if ( count == 7'd1 ) begin
                                    count 			<= 7'd0;
                                    TX_STATE 		<= TX_DLC;
                                    NEXT_TX_STATE 	<= TX_DLC;
                                end else begin
                                    count 			<= count + 1'b1;
                                end
							end
		// -- exclude start of the frame bit
		// 15 bit
		TX_CRC:				begin
                                if ( count == 7'd14 ) begin
                                    count 			<= 7'd0;
                                    TX_STATE 		<= TX_CRC_DELIMITER;
                                    crc_rst_i      <= 1'b1;
                                end else begin
                                    count 			<= count + 1'b1;
                                end		
							end
		// -- must be 1
		// 1 bit
		TX_CRC_DELIMITER:	begin
                                    TX_STATE 		<= TX_ACK_SLOT;
							end
		// -- Each node that receives the frame, without an error, transmits a 0 and thus overrides the 1 of the transmitter. 
		// If a transmitter detects a recessive level in the ACK slot, it knows that no receiver found a valid frame. 
		// A receiving node may transmit a recessive to indicate that it did not receive a valid frame, 
		// but another node that did receive a valid frame may override this with a dominant.
		// 1 bit
		TX_ACK_SLOT:		begin
                                    TX_STATE 		<= TX_ACK_DELIMITER;
							end
		// 1 bit(1)
		TX_ACK_DELIMITER:	begin
                                    TX_STATE 		<= TX_END_OF_FRAME;
							end
		// 7 bits(1)
		TX_END_OF_FRAME:	begin
                                if ( count == 7'd6 ) begin
                                    count 			<= 7'd0;
                                    TX_STATE 		<= TX_IDLE;
                                    frame_sent_o    <= 1'b1;
                                    tx_busy_o       <= 1'b0;
                                end else begin
                                    count 			<= count + 1'b1;
                                end	
							end								
		// </MAC-level>			
																						
		// <LLC-level>
		//		<Identificator>
		// 		C/D 1 bit
		TX_MESSAGE_TYPE:	begin
                                TX_STATE 	  			<= TX_ADDRESS_LOCAL;
                                NEXT_TX_STATE 			<= TX_ADDRESS_LOCAL;	
							end
		// 		Address local 6 bit
		TX_ADDRESS_LOCAL:  	begin
                                if ( count == 7'd5 ) begin
                                    count 				<= 7'd0;							
                                    TX_STATE 			<= TX_ADDRESS_REMOTE;
                                    NEXT_TX_STATE 		<= TX_ADDRESS_REMOTE;	
                                end else begin													
                                    count 				<= count + 1'b1;	
                                end
							end
		// 		Address remote 6 bit				
		TX_ADDRESS_REMOTE:	begin
                                if ( count == 7'd5 ) begin
                                    count 				<= 7'd0;	
                                    TX_STATE 			<= TX_HANDSHAKING_P;
                                    NEXT_TX_STATE 		<= TX_HANDSHAKING_P;	
                                end else begin					
                                    if ( count == 7'd3 ) begin
                                        count 			<= count + 1'b1;
                                        TX_STATE 		<= TX_SRR;
                                        NEXT_TX_STATE 	<= TX_SRR;
                                    end else begin																			
                                        count 			<= count + 1'b1;
                                    end	
                                end
							end
		//		</Identificator>
		// 	<Atribute>		
		// 		DataFrame: pointer, CommandFrame: handshaking 2 bit
		TX_HANDSHAKING_P:   begin
                                if ( count == 7'd1 ) begin
                                    count				<= 7'd0;
                                    TX_STATE 			<= TX_ATRIBUTE_RESERVED;
                                    NEXT_TX_STATE 		<= TX_ATRIBUTE_RESERVED;	
                                end else begin
                                    count 				<= count + 1'b1;
                                end
                            end
		// 		DataFrame: reserved 2'b00, CommandFrame: 2'b10 2 bit
		TX_ATRIBUTE_RESERVED:begin
                                if ( count == 7'd1 ) begin
                                    count				<= 7'd0;
                                    TX_STATE 			<= TX_EXPAND_COUNT;
                                    NEXT_TX_STATE 		<= TX_EXPAND_COUNT;	
                                end else begin
                                    count 				<= count + 1'b1;
                                end										
							end	
		// 		DataFrame: frame count, CommandFrame: expand command field 4 bit		
		TX_EXPAND_COUNT:	begin
                                if ( count == 7'd3 ) begin
                                    count				<= 7'd0;
                                    TX_STATE 			<= TX_CMD_DATA_SIGN;
                                    NEXT_TX_STATE 		<= TX_CMD_DATA_SIGN;	
                                end else begin
                                    count 				<= count + 1'b1;
                                end
							end
		// 		DataFrame: type of data, CommandFrame: type of command 8 bit
		TX_CMD_DATA_SIGN: 	begin
                                if ( count == 7'd7 ) begin
                                    count				<= 7'd0;
                                    TX_STATE 			<= TX_RTR;
                                    NEXT_TX_STATE 		<= TX_RTR;	
                                end else begin
                                    count 				<= count + 1'b1;
                                end										
							end
		// 		DLC 4 bit
		TX_DLC:				begin
                                if ( count == 7'd3 ) begin
                                    count				<= 7'd0;
                                    TX_STATE 			<= TX_DATA;
                                    NEXT_TX_STATE 		<= TX_DATA;	
                                end else begin
                                    count 				<= count + 1'b1;
                                end											
							end
		//			Data 0 or 64 bit
		TX_DATA:			begin
                                if ( count == 7'd63 ) begin
                                    count				<= 7'd0;
                                    TX_STATE 			<= TX_CRC;
                                    NEXT_TX_STATE 		<= TX_CRC;
                                end else begin
                                    count 				<= count + 1'b1;
                                end		
							end
		// </LLC-level>
		endcase		
	
		// <bit stuff check>
		if (    TX_STATE !=	TX_IDLE 	        && 
                TX_STATE != TX_CRC_DELIMITER 	&& 
                TX_STATE !=	TX_ACK_SLOT 		&& 
                TX_STATE !=	TX_ACK_DELIMITER 	&& 
				TX_STATE !=	TX_END_OF_FRAME ) begin
			if ( tx_o == last_bit ) begin	
				bit_pol_count 			<= bit_pol_count + 1'b1;					
					if ( bit_pol_count == 3'd5 ) begin
						if ( tx_o == 1'b0 ) begin
							bit_stuff_bit <= 1'b1;
						end else begin
							bit_stuff_bit <= 1'b0;
						end							
						bit_pol_count 	<= 3'd1;
						TX_STATE 	  	<= TX_BIT_STUFF;
					end				
			end else begin						
				bit_pol_count 	<= 3'd2;								
			end
		end
		// </bit stuff check>
		if ( TX_STATE != TX_IDLE &&
			 TX_STATE != TX_ACK_SLOT ) begin
			if ( tx_o != rx_i ) begin
				//tx_lost_arbitrage_o 	<= 1'b1;
                //TX_STATE  		<= TX_IDLE;
			end
		end
	end
end

//<acknowledgement>
reg    tx_acknowledged_o_reg;
assign tx_acknowledged_o = tx_acknowledged_o_reg;

always @( posedge clk_can_i or negedge rst_i ) begin
	if ( rst_i == 1'b0 ) begin
		tx_acknowledged_o_reg <= 1'b0;
	end else begin
		if ( TX_STATE == TX_ACK_SLOT ) begin
			if ( rx_i == 1'b0 ) begin
				tx_acknowledged_o_reg <= 1'b1;
			end
		end
	end
end
//</acknowledgement>

localparam SAMPLE = QUANTS/2;
localparam STATE_RES = 12'd0;

//<arbitrage>
always @( posedge clk_i or negedge rst_i ) begin
    if ( rst_i == 1'b0 ) begin
        tx_lost_arbitrage_o <= 1'b0;
    end else begin
        if ( TX_STATE == TX_IDLE ) begin
            quant_count         <= STATE_RES;
            tx_lost_arbitrage_o <= 1'b0;
        end else begin
            quant_count     <= quant_count + 1'b1;
            if ( quant_count == SAMPLE ) begin
                // test_arbi <= rx_i;
                    if ( TX_STATE != TX_ACK_SLOT ) begin
                        if ( tx_o != rx_i ) begin
                            tx_lost_arbitrage_o 	<= 1'b1;
                        end
                    end
            end else begin
                if ( quant_count == QUANTS ) begin
                    quant_count <= STATE_RES;
                end
            end
        end
    end
end
//</arbitrage>

localparam [1:0] atribute = 2'b10;
localparam rtr = 1'b0;
assign tx_o = TX_STATE == TX_START_OF_FRAME 		? 1'b0 								:												
				( TX_STATE == TX_MESSAGE_TYPE 		? message_type 						:
				( TX_STATE == TX_ADDRESS_LOCAL 		? local_address	    [7'd5 - count]  :	
				( TX_STATE == TX_ADDRESS_REMOTE 	? remote_address	[7'd5 - count]  :
				( TX_STATE == TX_SRR 				? 1'b1 								:
				( TX_STATE == TX_IDE 				? 1'b1 								:
				( TX_STATE == TX_HANDSHAKING_P 		? handshake			[7'd1 - count]	:
				( TX_STATE == TX_ATRIBUTE_RESERVED 	? atribute			[7'd1 - count]	:
				( TX_STATE == TX_EXPAND_COUNT 		? expand_count		[7'd3 - count]  :
				( TX_STATE == TX_CMD_DATA_SIGN 		? cmd_data_sign	    [7'd7 - count]	:
				( TX_STATE == TX_RTR 				? rtr								:
				( TX_STATE == TX_RESERVED 			? 1'b0							    :
				( TX_STATE == TX_DLC 				? dlc				[7'd3 - count]	:
				( TX_STATE == TX_DATA 				? tx_data			[7'd63 - count] :
				( TX_STATE == TX_CRC 				? crc		        [7'd14 - count] :
				( TX_STATE == TX_CRC_DELIMITER 		? 1'b1							    :
				( TX_STATE == TX_ACK_SLOT 			? 1'b1								:
				( TX_STATE == TX_ACK_DELIMITER 		? 1'b1								:
				( TX_STATE == TX_END_OF_FRAME 		? 1'b1								:
				( TX_STATE == TX_BIT_STUFF			? bit_stuff_bit						:
                ( TX_STATE == TX_IDLE               ? 1'b1                              :
                                                      1'b1 ))))))))))))))))))));

endmodule

can_rx接收数据模块

module can_rx
#(
    parameter CLK_FREQ      = 'd9600,
    parameter CAN_CLK_FREQ  = 'd50_000_000,
    parameter QUANTS        = CLK_FREQ/CAN_CLK_FREQ
)(
    input rst_i,
    input clk_i,
    input clk_can_i,
    input rx_start_i,
    input init_i,
    
    output reg          rx_busy_o,
    output reg          can_clk_sync_o,
    output reg          rx_frame_ready_o,
    
    input               message_type,
    input  [5:0]        local_address,    
    input  [5:0]        rx_local_address,
    output reg [5:0]    remote_address,
    output [1:0]        handshake,
    output [3:0]        expand_count,
    output [7:0]        cmd_data_sign,
    output [3:0]        dlc,
    output reg [63:0]   rx_data,
    
    input  rx_i,
    output tx_o
    
    //test
    // output [7:0]  test_rx_state,
    // output [11:0] test_quant_count,
    // output [7:0]  test_bit_count,
    // output [2:0]  test_bit_pol_count,
    // output        test_rx_bit_stuffed,
    
    // output [6:0]  test_rx_count,
    // output reg    test_sample,
    // output reg    test_rx_rx,
    // output        test_sample_1
);
// <test>

// assign test_rx_state       = RX_STATE;
// assign test_quant_count    = quant_count;
// assign test_bit_count      = bit_count_reg;
// assign test_bit_pol_count  = bit_pol_count;
// assign test_rx_bit_stuffed = rx_bit_stuffed;
// assign test_rx_count       = count;

// reg test_reg_on;
// reg [6:0] test_count;
// always @( posedge clk_can_i or negedge rst_i ) begin
//     if ( rst_i == 1'b0 ) begin
//         test_count  <= 7'd0;
//         test_sample <= 1'b1;
//     end else begin
//         if ( test_reg_on == 1'b1 ) begin
//             if ( test_count == 7'd15 ) begin
//                 test_sample <= 1'b1;
//             end else begin
//                 test_sample <= crc_calc[7'd14 - test_count];
//                 test_count  <= test_count + 1'b1;
//             end
//         end else begin
//             test_sample <= 1'b1;
//             test_count  <= 7'd0;
//         end
//     end
// end

// always @( posedge clk_i or negedge rst_i ) begin
//     if ( rst_i == 1'b0 ) begin
//         test_rx_rx <= 1'b1;
//     end else begin
//         if ( RX_STATE != RX_IDLE ) begin
//             if ( quant_count == SAMPLE ) begin
//                 test_rx_rx <= rx_i;
//             end
//         end else begin
//             test_rx_rx <= 1'b1;
//         end
//     end
// end
// assign test_sample_1 = tx_o;	
// </test>

reg [5:0] local_adress_reg;
wire [5:0] local_adress;
// <init>
always @( posedge clk_i or negedge rst_i ) begin
    if ( rst_i == 1'b0 ) begin
        local_adress_reg <= 6'h0;
    end else begin
        if ( init_i == 1'b1 ) begin
            local_adress_reg <= local_adress;
        end
    end
end
// </init>

// <ACK>
reg acknowledged_aux;
assign tx_o = ( RX_STATE == RX_ACK_SLOT && acknowledged_aux ) ? 1'b0 : 1'b1;

always @( posedge clk_i or negedge rst_i ) begin
    if ( rst_i == 1'b0 ) begin
        acknowledged_aux    <= 1'b0;
    end else begin
        if ( RX_STATE == RX_HANDSHAKING_P ) begin
            if ( rx_address_remote == local_adress_reg ) begin
                acknowledged_aux <= 1'b1;
            end
        end else begin
            if ( RX_STATE == RX_IDLE ) begin
                acknowledged_aux <= 1'b0;
            end 
        end
    end
end
// </ACK>

//<CRC>
reg  [14:0] crc_calc;
wire [14:0] crc;
wire crc_en;
wire crc_clk;
assign crc_en = ( RX_STATE == RX_IDLE 		     || 
				  RX_STATE == RX_START_OF_FRAME  ||
				  RX_STATE == RX_BIT_STUFF 		 ||
                  RX_STATE == RX_ACK_SLOT 		 ||
                  RX_STATE == RX_ACK_DELIMITER   ||
                  RX_STATE == RX_END_OF_FRAME    ||
                  RX_STATE == RX_CRC_DELIMITER   ||
				  RX_STATE == RX_CRC ) ? 1'b0 : 1'b1;
assign crc_clk = ( quant_count == SAMPLE ) ? 1'b1 : 1'b0;

reg crc_rst_i;

can_crc can_crc_instance
(
	.crc_clk_i	(crc_clk),
	.rst_i		(rst_i),
	.data_i		(rx_i),
	.en_i       (crc_en),
	.crc_reg_o	(crc),
	.crc_rst_i  (crc_rst_i)
);
//</CRC>

// <frame regs>
reg         rx_message_type;
reg [5:0]   rx_address_local;
reg [5:0]   rx_address_remote;
reg [1:0]   rx_handshaking_p;
reg [1:0]   rx_atribute_reserved;
reg [3:0]   rx_expand_count;
reg [7:0]   rx_cmd_data_sign;
reg [3:0]   rx_dlc;
reg [14:0]  rx_crc;
// </frame regs>

// <count and aux>
reg [7:0] bit_count_reg ;
reg [6:0] count; 
reg [2:0] bit_pol_count;
reg 	  last_bit;
reg 	  bit_stuff_bit; 
reg       rx_bit_stuffed;

reg rx_i_last;
reg aux_count;

reg [11:0] quant_count;
// </count and aux>

localparam SAMPLE = QUANTS/2;
localparam STATE_RES = 12'd0;

// 0xAx - MAC, 0xB-x - LLC
localparam RX_IDLE                  = 8'h00;
localparam RX_BIT_STUFF             = 8'h0B;
 
localparam RX_START_OF_FRAME        = 8'hA1;
localparam RX_MESSAGE_TYPE          = 8'hB1;
localparam RX_ADDRESS_LOCAL         = 8'hB2;
localparam RX_ADDRESS_REMOTE        = 8'hB3;
localparam RX_SRR                   = 8'hA2;
localparam RX_IDE                   = 8'hA3;
localparam RX_HANDSHAKING_P         = 8'hB4;
localparam RX_ATRIBUTE_RESERVED     = 8'hB5;
localparam RX_EXPAND_COUNT          = 8'hB6;
localparam RX_CMD_DATA_SIGN         = 8'hB7;
localparam RX_RTR                   = 8'hA4;
localparam RX_RESERVED              = 8'hA5;
localparam RX_DLC                   = 8'hB8;
localparam RX_DATA                  = 8'hB9;
localparam RX_CRC                   = 8'hA6;
localparam RX_CRC_DELIMITER         = 8'hA7;
localparam RX_ACK_SLOT              = 8'hA8;
localparam RX_ACK_DELIMITER         = 8'hA9;
localparam RX_END_OF_FRAME          = 8'hAA;

reg[7:0] RX_STATE;
reg[7:0] NEXT_RX_STATE;

always @( posedge clk_i or negedge rst_i ) begin
    if ( rst_i == 1'b0 ) begin
        RX_STATE                <= RX_IDLE;
        NEXT_RX_STATE           <= RX_IDLE;
        //<test>
        // test_reg_on             <= 1'b0;
        //</test>
        rx_address_local        <= 6'd0;
        rx_address_remote       <= 6'd0;
        rx_handshaking_p        <= 2'd0;
        rx_atribute_reserved    <= 2'd0;
        rx_expand_count         <= 4'd0;
        rx_cmd_data_sign        <= 8'd0;
        rx_dlc                  <= 4'd0;
        rx_crc                  <= 15'd0;
        rx_data                 <= 64'd0;
        
        bit_count_reg           <= 8'd0;        
        count                   <= 7'd0;    
        bit_stuff_bit           <= 1'b0;
        last_bit                <= 1'b0;
        crc_rst_i               <= 1'b0;
        quant_count             <= 12'd1;
        rx_busy_o               <= 1'b0;
        aux_count               <= 1'b0;
        crc_calc                <= 15'd0;
        rx_i_last               <= 1'b0;
        aux_count               <= 1'b0;
        rx_frame_ready_o        <= 1'b0;
    end else begin
    if ( rx_start_i ) begin
        if ( RX_STATE != RX_IDLE ) begin
            quant_count      <= quant_count + 1'b1;
        end
        case ( RX_STATE )
        RX_IDLE:            begin
                                crc_rst_i <= 1'b0;    
                                bit_count_reg       <= 8'd0;
                                // test_reg_on         <= 1'b0;
                                rx_frame_ready_o    <= 1'b0;                
                                if ( rx_i == 1'b0 && rx_i_last == 1'b1 ) begin
                                    RX_STATE        <= RX_START_OF_FRAME;
                                    quant_count     <= 12'd1;
                                    rx_busy_o       <= 1'b1;
                                    rx_data         <= 64'd0;                           
                                end
                            end                                                                     
        // <MAC-level>
        
        // every 5 consequent same polarity bit add one reversed(not for CRC delimiter, ACK field and EOF)
        // 1 bit
        RX_BIT_STUFF:       begin
                                if ( aux_count == 1'b1 ) begin
                                    if ( quant_count == 12'd0 ) begin
                                        RX_STATE            <= NEXT_RX_STATE;
                                        aux_count <= 1'b0;
                                    end
                                end else begin
                                    if ( quant_count == SAMPLE ) begin
                                        aux_count <= 1'b1;
                                    end 
                                end
                            end             
        // 1 bit 
        RX_START_OF_FRAME:  begin
                                if ( aux_count == 1'b1 ) begin  
                                    if ( quant_count == STATE_RES ) begin
                                        RX_STATE        <= RX_MESSAGE_TYPE;
                                        NEXT_RX_STATE   <= RX_MESSAGE_TYPE;
                                        aux_count       <= 1'b0;
                                    end
                                end else begin
                                    if ( quant_count == SAMPLE ) begin
                                        aux_count <= 1'b1;
                                    end 
                                end
                            end               
        
        //  IDE and SRR are placed between 18 and 17 bit of 29 bit extended arbitration field
        // 1 bit
        RX_SRR:             begin
                                if ( aux_count == 1'b1 ) begin
                                     if ( quant_count == STATE_RES ) begin
                                        RX_STATE        <= RX_IDE;
                                        NEXT_RX_STATE   <= RX_IDE;
                                        aux_count       <= 1'b0;
                                     end
                                end else begin
                                    if ( quant_count == SAMPLE ) begin
                                        aux_count       <= 1'b1;
                                    end 
                                end
                            end
        // 1 bit
        RX_IDE:             begin
                                if ( aux_count == 1'b1 ) begin
                                    if ( quant_count == STATE_RES ) begin
                                        RX_STATE        <= RX_ADDRESS_REMOTE;
                                        NEXT_RX_STATE   <= RX_ADDRESS_REMOTE;
                                        aux_count       <= 1'b0;
                                    end
                                end else begin
                                    if ( quant_count == SAMPLE ) begin
                                        aux_count       <= 1'b1;
                                    end 
                                end
                            end
        // -- RTR-bit is 0 in the Data Frame, in the Remote Frame is 1 there and there is no Data Field 
        // in Remote Frame The DLC field indicates the data length of the requested message (not the transmitted one)
        // 1 bit
        RX_RTR:             begin
                                if ( aux_count == 1'b1 ) begin
                                    if ( quant_count == STATE_RES ) begin
                                        RX_STATE        <= RX_RESERVED;
                                        NEXT_RX_STATE   <= RX_RESERVED;
                                        aux_count       <= 1'b0;
                                    end
                                end else begin
                                    if ( quant_count == SAMPLE ) begin
                                        aux_count       <= 1'b1;
                                    end 
                                end
                            end
        // -- r1, r0 Reserved bits which must be set dominant (0), but accepted as either dominant or recessive 
        RX_RESERVED:        begin
                                if ( count == 7'd2 ) begin
                                    if ( quant_count == STATE_RES ) begin             
                                        RX_STATE        <= RX_DLC;
                                        NEXT_RX_STATE   <= RX_DLC;
                                        count           <= 7'd0;
                                    end
                                end else begin
                                    if ( quant_count == SAMPLE ) begin
                                        count           <= count + 1'b1;
                                    end
                                end
                            end
        // -- exclude start of the frame bit
        // 15 bit
        RX_CRC:             begin
                                if ( count == 7'd15 ) begin
                                    if ( quant_count == STATE_RES ) begin  
                                        count           <= 7'd0;
                                        RX_STATE        <= RX_CRC_DELIMITER;
                                        
                                        //
                                        // test_reg_on <= 1'b1;
                                        //
                                    end
                                end else begin
                                    if ( quant_count == SAMPLE ) begin 
                                        rx_crc[7'd14 - count]   <= rx_i;
                                        count                   <= count + 1'b1;
                                    end
                                end     
                            end
        // -- must be 1
        // 1 bit
        RX_CRC_DELIMITER:   begin
                                if ( aux_count == 1'b1 ) begin
                                    if ( quant_count == STATE_RES ) begin
                                        RX_STATE        <= RX_ACK_SLOT;
                                        aux_count       <= 1'b0;
                                    end
                                end else begin
                                    if ( quant_count == SAMPLE ) begin
                                        aux_count       <= 1'b1;
                                    end 
                                end
                            end
        // -- Each node that receives the frame, without an error, transmits a 0 and thus overrides the 1 of the transmitter. 
        // If a transmitter detects a recessive level in the ACK slot, it knows that no receiver found a valid frame. 
        // A receiving node may transmit a recessive to indicate that it did not receive a valid frame, 
        // but another node that did receive a valid frame may override this with a dominant.
        // 1 bit
        RX_ACK_SLOT:        begin
                                if ( aux_count == 1'b1 ) begin
                                    if ( quant_count == STATE_RES ) begin
                                        RX_STATE        <= RX_ACK_DELIMITER;
                                        aux_count       <= 1'b0;
                                    end
                                end else begin
                                    if ( quant_count == SAMPLE ) begin
                                        aux_count       <= 1'b1;
                                    end 
                                end
                            end
        // 1 bit(1)
        RX_ACK_DELIMITER:   begin
                                if ( aux_count == 1'b1 ) begin
                                    if ( quant_count == STATE_RES ) begin
                                        RX_STATE        <= RX_END_OF_FRAME;
                                        aux_count       <= 1'b0;
                                    end
                                end else begin
                                    if ( quant_count == SAMPLE ) begin
                                        aux_count       <= 1'b1;
                                    end 
                                end
                            end
        // 7 bits(1)
        RX_END_OF_FRAME:    begin   
                                rx_frame_ready_o <= 1'b1;
                                if ( count == 7'd7 ) begin
                                    if ( quant_count == STATE_RES ) begin        
                                        RX_STATE        <= RX_IDLE;
                                        crc_rst_i       <= 1'b1;
                                        count           <= 7'd0;
                                        rx_busy_o       <= 1'b0;
                                    end
                                end else begin
                                    if ( quant_count == SAMPLE ) begin
                                        count           <= count + 1'b1;
                                    end
                                end 
                            end                             
        // </MAC-level>                 
           
        // <LLC-level>
        //      <Identificator>
        //      C/D 1 bit
        RX_MESSAGE_TYPE:    begin
                                if ( count == 7'd1 ) begin
                                    if ( quant_count == STATE_RES ) begin
                                        RX_STATE        <= RX_ADDRESS_LOCAL;
                                        NEXT_RX_STATE   <= RX_ADDRESS_LOCAL;
                                        count           <= 7'd0;
                                    end
                                end else begin
                                    if ( quant_count == SAMPLE ) begin
                                        rx_message_type  <= rx_i;
                                        count            <= count + 1'b1;
                                    end
                                end  
                            end
        //      Address local 6 bit
        RX_ADDRESS_LOCAL:   begin                              
                                if ( count == 7'd6 ) begin
                                    if ( quant_count == STATE_RES ) begin
                                        RX_STATE        <= RX_ADDRESS_REMOTE;
                                        NEXT_RX_STATE   <= RX_ADDRESS_REMOTE;
                                        count           <= 7'd0;   
                                    end 
                                end else begin
                                    if ( quant_count == SAMPLE ) begin
                                        rx_address_local[7'd5 - count]  <= rx_i;
                                        count                           <= count + 1'b1;
                                    end
                                end
                            end
        //      Address remote 6 bit                
        RX_ADDRESS_REMOTE:  begin
                                if ( count == 7'd6 ) begin
                                    if ( quant_count == STATE_RES) begin  
                                        RX_STATE            <= RX_HANDSHAKING_P;
                                        NEXT_RX_STATE       <= RX_HANDSHAKING_P;
                                        count               <= 7'd0;    
                                    end 
                                end else begin
                                    if ( count == 7'd4 ) begin
                                        if ( quant_count == STATE_RES ) begin  
                                            RX_STATE        <= RX_SRR;
                                            NEXT_RX_STATE   <= RX_SRR;
                                        end else begin
                                            if ( quant_count == SAMPLE ) begin
                                                rx_address_remote[7'd5 - count]  <= rx_i;
                                                count                            <= count + 1'b1;
                                            end                                           
                                        end
                                    end else begin 
                                        if ( quant_count == SAMPLE ) begin
                                            rx_address_remote[7'd5 - count]  <= rx_i;
                                            count                            <= count + 1'b1;               
                                        end 
                                    end
                                end
                            end
        //      </Identificator>
        //  <Atribute>      
        //      DataFrame: pointer, CommandFrame: handshaking 2 bit
        RX_HANDSHAKING_P:       begin
                                    if ( count == 7'd2 ) begin
                                        if ( quant_count == STATE_RES ) begin
                                            RX_STATE            <= RX_ATRIBUTE_RESERVED;
                                            NEXT_RX_STATE       <= RX_ATRIBUTE_RESERVED;
                                            count               <= 7'd0;
                                        end    
                                    end else begin
                                        if ( quant_count == SAMPLE ) begin
                                            rx_handshaking_p[7'd1 - count]  <= rx_i;
                                            count                           <= count + 1'b1;
                                        end
                                    end
                                end
        //      DataFrame: reserved 2'b00, CommandFrame: 2'b10 2 bit
        RX_ATRIBUTE_RESERVED:begin
                                if ( count == 7'd2 ) begin
                                    if ( quant_count == STATE_RES ) begin                                   
                                        RX_STATE            <= RX_EXPAND_COUNT;
                                        NEXT_RX_STATE       <= RX_EXPAND_COUNT;
                                        count               <= 7'd0;
                                    end 
                                end else begin
                                    if ( quant_count == SAMPLE ) begin
                                        rx_atribute_reserved[7'd1 - count]  <= rx_i;
                                        count                               <= count + 1'b1;
                                    end
                                end                                     
                            end 
        //      DataFrame: frame count, CommandFrame: expand command field 4 bit        
        RX_EXPAND_COUNT:    begin
                                if ( count == 7'd4 ) begin
                                    if ( quant_count == STATE_RES ) begin                                           
                                        RX_STATE            <= RX_CMD_DATA_SIGN;
                                        NEXT_RX_STATE       <= RX_CMD_DATA_SIGN;
                                        count               <= 7'd0;
                                    end    
                                end else begin
                                    if ( quant_count == SAMPLE ) begin
                                        rx_expand_count[7'd3 - count]   <= rx_i;
                                        count                           <= count + 1'b1;
                                    end
                                end
                            end
        //      DataFrame: type of data, CommandFrame: type of command 8 bit
        RX_CMD_DATA_SIGN:   begin
                                if ( count == 7'd8 ) begin
                                    if ( quant_count == STATE_RES ) begin 
                                        RX_STATE            <= RX_RTR;
                                        NEXT_RX_STATE       <= RX_RTR;
                                        count               <= 7'd0;
                                    end  
                                end else begin
                                    if ( quant_count == SAMPLE ) begin
                                        rx_cmd_data_sign[7'd7 - count]  <= rx_i;
                                        count                           <= count + 1'b1;
                                    end
                                end                                     
                            end
        //      DLC 4 bit
        RX_DLC:             begin
                                if ( count == 7'd4 ) begin
                                    if ( quant_count == STATE_RES ) begin                                         
                                        RX_STATE            <= RX_DATA;
                                        NEXT_RX_STATE       <= RX_DATA;
                                        count               <= 7'd0;
                                    end 
                                end else begin
                                    if ( quant_count == SAMPLE ) begin
                                        rx_dlc[7'd3 - count]    <= rx_i;
                                        count                   <= count + 1'b1;
                                    end
                                end                                         
                             end
        //          Data 0 or 64 bit
        RX_DATA:             begin
                                if ( count == 7'd64 ) begin
                                    if ( quant_count == STATE_RES ) begin                                        
                                        RX_STATE            <= RX_CRC;
                                        NEXT_RX_STATE       <= RX_CRC;
                                        count               <= 7'd0;
                                        //
                                        crc_calc <= crc;
                                     end
                                end else begin
                                    if ( quant_count == SAMPLE ) begin
                                        rx_data[7'd63 - count]  <= rx_i;
                                        count                   <= count + 1'b1;
                                    end
                                end     
                            end
    // </LLC-level>
        endcase     
        
        // <can clk sync>
        if ( rx_i == 1'b0 && rx_i_last == 1'b1 ) begin
            can_clk_sync_o  <= 1'b1; 
        end else begin
            can_clk_sync_o  <= 1'b0;
        end
        // </can clk sync>
        
        // <bit stuff check>
        if ( quant_count == STATE_RES ) begin
            if ( rx_bit_stuffed ) begin
                RX_STATE    <= RX_BIT_STUFF;                   
            end
         end       
        // </bit stuff check>
        
        // <bit count>
        if ( RX_STATE != RX_IDLE  ) begin
            if ( quant_count == SAMPLE ) begin
                last_bit        <= rx_i;
                bit_count_reg   <= bit_count_reg + 1'b1;
            end
        end
        // </bit count>
        
        // <quant count>
        if ( quant_count == QUANTS ) begin
            quant_count     <= STATE_RES;
        end
        // </quant count>
        
        // <quant sync>
        if ( rx_i != rx_i_last && RX_STATE != RX_IDLE ) begin
            quant_count     <= STATE_RES;
        end
        // </quant sync>
        
        rx_i_last <= rx_i; 
        
        end
    end
        
end

// <bit_stuffing>
always @( posedge clk_i or negedge rst_i ) begin
        if ( rst_i == 1'b0 ) begin
            rx_bit_stuffed <= 1'b0;
            bit_pol_count  <= 1'b0;
        end else begin
            if ( quant_count == SAMPLE ) begin
                if (  RX_STATE != RX_IDLE           && 
                      RX_STATE != RX_CRC_DELIMITER  && 
                      RX_STATE != RX_ACK_SLOT       && 
                      RX_STATE != RX_ACK_DELIMITER  && 
                      RX_STATE != RX_END_OF_FRAME ) begin
                    if ( rx_i == last_bit ) begin   
                        bit_pol_count       <= bit_pol_count + 1'b1;
                        if ( bit_pol_count == 3'd5 ) begin                       
                            bit_pol_count   <= 3'd1;
                        end                    
                    end else begin                      
                        bit_pol_count   <= 3'd1;                                
                    end
                end
            end else begin 
                if ( quant_count == STATE_RES ) begin
                     rx_bit_stuffed  <= 1'b0;
            end else begin
                if ( bit_pol_count == 3'd5 && RX_STATE != RX_BIT_STUFF ) begin                       
                    rx_bit_stuffed  <= 1'b1;
                end
            end
        end
    end
end
// </bit stuffing>

endmodule 

以下为模块化设计,便于修改CRC校验和CLK时钟信号

can_crc校验模块

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

can_clk时钟模块

module can_clk
#(
   parameter FREQ_I = 50_000_000,
   parameter FREQ_O = 1_000_000,
   parameter END_COUNT = FREQ_I/(FREQ_O*2) - 1
)( 
   input rst_i,
   input clk_i,
   input sync_i,
   
   output can_clk_o
);

reg [11:0] count;
reg can_clk_o_reg;

assign can_clk_o = can_clk_o_reg;

always @( posedge clk_i or negedge rst_i ) begin
   if ( rst_i == 1'b0 ) begin
      can_clk_o_reg     <= 1'b1;
      count             <= 12'd0;
   end else begin
       if ( sync_i ) begin
          count             <= 12'd0;
          can_clk_o_reg     <= 1'b1;
       end else if ( count == END_COUNT ) begin
          count             <= 12'd0;
          can_clk_o_reg     <= ~can_clk_o_reg;
       end else begin
          count             <= count + 1'b1;
       end
    end
end

endmodule	

can_top_inst模块实例化

can_top can_top_inst
(
	.rst_i(rst_i_sig) ,	// input  rst_i_sig
	.clk_i(clk_i_sig) ,	// input  clk_i_sig
	.rx_i(rx_i_sig) ,	// input  rx_i_sig
	// .rx_busy(rx_busy_sig) ,	// output  rx_busy_sig
	.tx_o(tx_o_sig) ,	// output  tx_o_sig
	// .tx_busy(tx_busy_sig) ,	// output  tx_busy_sig
	.data_i(data_i_sig) ,	// input [7:0] data_i_sig
	.data_o(data_o_sig) 	// output [7:0] data_o_sig
);

注:以下模块本项目已经注释掉了,没有在项目中实际运行,原因:使用了太多的IO口,芯片无法支持。

can_test模块

module can_test
(
    input clk_i,
    input rx_i,
    input rst_i,
    output tx_o,
    
    output tx_busy,
    output rx_busy,
    
    
    output test_rx_rx,
    output test_sample
    
);

reg tx_send = 1'b1;

reg [63:0] tx_data              = 64'b0011000100110010001100110011010000110101001101100011011100111000;


can_top can_top_inst 
(
    .rst_i      (rst_i),
    .clk_i      (clk_i),
    
    .rx_i       (rx_i),
    .rx_busy    (rx_busy),
    
    .tx_o       (tx_o),
    .tx_busy    (tx_busy),
    .tx_send_i  (1'b1),
    
    
    .tx_data_i   (tx_data),
    
    
    .data_wr    (data_wr),
    .addr_wr    (addr_wr),
    .wr_en      (wr_en),
    .wr_done    (wr_done),
    .wr_busy    (wr_busy)
);

localparam addr_width = 10;
localparam data_width = 32;

localparam [9:0] addr_data_send    = 20'hA0001;
localparam [9:0] addr_setting_send = 20'hA0002;


PMRAMIF # (
    .DATA_WIDTH        (data_width),
    .ADDR_WIDTH        (addr_width),
    .CLK_FREQUENCY     (50_000_000),
    .OP_CYCLE_NS       (35)
) PMRAMIF_inst
(
    .clk        (clk_i),
    .rst        (rst_i),
    
    .data_wr    (data_wr),
    .addr_wr    (addr_wr),
    .wr_en      (wr_en),
    .wr_done    (wr_done),
    .wr_busy    (wr_busy),

    .data_rd    (data_rd),
    .addr_rd    (addr_rd),
    .rd_en      (rd_en),
    .rd_done    (rd_done),
    .rd_busy    (rd_busy)
);

endmodule
    

pmramif模块

module PMRAMIF
#(
    parameter DATA_WIDTH        = 32,
    parameter ADDR_WIDTH        = 20,
    parameter CLK_FREQUENCY     = 200_000_000,
    parameter OP_CYCLE_NS       = 35
)(
    input                          clk,
    input                          rst,

    input       [DATA_WIDTH-1 : 0] data_wr,
    input       [ADDR_WIDTH-1 : 0] addr_wr,
    input                          wr_en,
    output reg                     wr_done,
    output reg                     wr_busy,

    output reg  [DATA_WIDTH-1 : 0] data_rd,
    input       [ADDR_WIDTH-1 : 0] addr_rd,
    input                          rd_en,
    output reg                     rd_done,
    output reg                     rd_busy,
     
     
    inout       [DATA_WIDTH-1 : 0] mram_data,
    output reg  [ADDR_WIDTH-1 : 0] mram_addr,
    output reg                     mram_ng,
    output reg                     mram_nw,
    output reg                     mram_nce
);

function integer clog2;
input integer value;
    begin
        value = value-1;
        for ( clog2 = 0; value > 0; clog2 = clog2+1 ) begin
            value = value >> 1;
        end
    end
endfunction




localparam CLK_PERIOD_NS         = 1_000_000_000 / CLK_FREQUENCY;
localparam OP_CLK_CYCLES         = (OP_CYCLE_NS + CLK_PERIOD_NS - 1) / CLK_PERIOD_NS;
localparam OP_COUNTER_WIDTH      = clog2(OP_CLK_CYCLES + 1);




wire op_done;
wire begin_op;




reg [DATA_WIDTH-1 : 0]       data_wr_reg;
reg [ADDR_WIDTH-1 : 0]       addr_wr_reg;
reg [ADDR_WIDTH-1 : 0]       addr_rd_reg;

reg [OP_COUNTER_WIDTH-1 : 0] op_counter    = 0;
reg                          op_counter_en = 1'b0;




assign mram_data = mram_nw ? { DATA_WIDTH {1'bz} } : data_wr_reg;

assign op_done   = (op_counter == OP_CLK_CYCLES);
assign begin_op  = (op_counter == 0);




    always @( posedge clk ) begin
        if ( op_counter_en ) begin
            if ( op_counter < OP_CLK_CYCLES ) begin
                op_counter <= op_counter + 1'b1;
            end else begin
                op_counter <= 0;
            end
        end else begin
            op_counter <= 0;
        end
    end

    always @( posedge clk ) begin
        case (STATE)
         IDLE :         begin
                            mram_nce      <= 1'b1;
                            mram_nw       <= 1'b1;
                            mram_ng       <= 1'b1;
                        end
        
        MRAM_WRITE :    begin
                            if ( begin_op ) begin
                                mram_addr <= addr_wr_reg;

                                mram_nce  <= 1'b0;
                                mram_ng   <= 1'b1;
                                mram_nw   <= 1'b0;                    
                            end else begin
                                if ( op_done ) begin
                                    mram_ng <= 1'b1;
                                    mram_nw <= 1'b1;
                                end
                            end
                        end

        MRAM_READ :     begin
                            if ( begin_op ) begin
                                mram_addr <= addr_rd_reg;

                                mram_nce  <= 1'b0;
                                mram_ng   <= 1'b0;
                                mram_nw   <= 1'b1;                    
                            end else begin
                                if ( op_done ) begin
                                    mram_nce  <= 1'b1;
                                    mram_ng   <= 1'b1;
                                end
                            end
                        end
        default:        begin
                            mram_nce <= 1'b1;
                            mram_nw <= 1'b1;
                            mram_ng <= 1'b1;
                        end
        endcase
    end






    localparam IDLE = 0;
    localparam MRAM_WRITE = 1;
    localparam MRAM_READ  = 2;

    reg [1:0] STATE;

    always @( posedge clk ) begin
        if ( rst ) begin
            STATE <= IDLE;
        end else begin
            case (STATE)
                IDLE :          begin
                                    if ( wr_en ) begin
                                        data_wr_reg   <= data_wr;
                                        addr_wr_reg   <= addr_wr;                                    
                                        wr_busy       <= 1'b1;

                                        op_counter_en <= 1'b1;
                                        STATE         <= MRAM_WRITE;                                    
                                    end else begin
                                        if ( rd_en ) begin              
                                            addr_rd_reg   <= addr_rd;                                        
                                            rd_busy       <= 1'b1;

                                            op_counter_en <= 1'b1;
                                            STATE         <= MRAM_READ;                                                                                
                                        end else begin
                                            wr_done       <= 1'b0;
                                            rd_done       <= 1'b0;
                                            op_counter_en <= 1'b0;
                                            wr_busy       <= 1'b0;
                                            rd_busy       <= 1'b0;
                                            data_wr_reg   <= 0;
                                            addr_wr_reg    <= 0;
                                            addr_rd_reg   <= 0;
                                        end
                                    end
                                end

                MRAM_WRITE:     begin
                                    if ( op_done ) begin                                    
                                        wr_done       <= 1'b1;
                                        wr_busy       <= 1'b0;

                                        op_counter_en <= 1'b0;
                                        if ( rd_en ) begin
                                            addr_rd_reg   <= addr_rd;                                        
                                            rd_busy       <= 1'b1;

                                            op_counter_en <= 1'b1;
                                            STATE         <= MRAM_READ;
                                        end else begin
                                            STATE <= IDLE;
                                        end
                                    end
                                    rd_done <= 1'b0;
                                end

                MRAM_READ:      begin
                                    if ( op_done ) begin
                                        rd_done       <= 1'b1;
                                        rd_busy       <= 1'b0;
                                        data_rd       <= mram_data;
                                        
                                        op_counter_en <= 1'b0;
                                        if ( wr_en ) begin
                                            data_wr_reg   <= data_wr;
                                            addr_wr_reg   <= addr_wr;                                        
                                            wr_busy       <= 1'b1;

                                            op_counter_en <= 1'b1;
                                            STATE         <= MRAM_WRITE;
                                        end else begin
                                            STATE <= IDLE;
                                        end
                                    end
                                    wr_done <= 1'b0;
                                end
                default:        begin                                
                                    STATE <= IDLE;
                                end
            endcase
        end
    end




endmodule

以下为实际运行截图基于FPGA的CAN通讯verilog代码设计,fpga,fpga开发,信号处理,信息与通信,vscode

 针脚绑定及IO

基于FPGA的CAN通讯verilog代码设计,fpga,fpga开发,信号处理,信息与通信,vscode

 使用GCANTOOLS上位机验证传输

波特率为800kps(可在can_top及其他模块中设置)

基于FPGA的CAN通讯verilog代码设计,fpga,fpga开发,信号处理,信息与通信,vscode文章来源地址https://www.toymoban.com/news/detail-718425.html

到了这里,关于基于FPGA的CAN通讯verilog代码设计的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 基于FPGA的QPSK调制系统verilog开发

    目录 一、理论基础 二、核心程序 三、测试结果         正交相移键控(Quadrature Phase Shift Keying,QPSK)是一种数字调制方式。它分为绝对相移和相对相移两种。由于绝对相移方式存在相位模糊问题,所以在实际中主要采用相对移相方式DQPSK。QPSK是一种四进制相位调制,具有良

    2024年02月01日
    浏览(46)
  • m基于FPGA的数字下变频verilog设计

    目录 1.算法描述 2.仿真效果预览 3.verilog核心程序 4.完整FPGA 整个数字下变频的基本结构如下所示 NCO使用CORDIC算法,CIC采用h结构的CIC滤波器,HBF采用复用结构的半带滤波器,而FIR则采用DA算法结构。     这里,我们首先假设不考虑中频信号输入的载波频偏问题,即发送的中频

    2024年02月21日
    浏览(47)
  • 基于FPGA的FSK调制解调系统verilog开发

    目录 1.算法仿真效果 2.verilog核心程序 3.算法涉及理论知识概要 4.完整verilog VIVADO2019.2仿真结果如下:       频移键控是利用载波的频率变化来传递数字信息。数字频率调制是数据通信中使用较 早的一种通信方式,由于这种调制解调方式容易实现,抗噪声和抗衰减性能较强,

    2024年02月05日
    浏览(77)
  • 基于Verilog 语言开发的FPGA密码锁工程

    基于Verilog 语言开发的FPGA密码锁工程。 通过矩阵键盘输入按键值。 输入12修改密码,13清除密码,可以修改原来默认的密码,修改时首先要输入当前密码进行验证,正确后才能更新当前密码,否则修改不成功。 修改结束后按键15,确认修改成功。 也直接使用默认密码作为最终

    2024年02月10日
    浏览(58)
  • 基于FPGA的多通道数据采集系统Verilog设计

    基于FPGA的多通道数据采集系统Verilog设计 随着科技的不断发展,数据采集在许多领域变得越来越重要。为了满足高速、高精度和多通道数据采集的需求,基于FPGA的多通道数据采集系统成为了一种常见的解决方案。本文将介绍如何使用Verilog语言设计一个基于FPGA的多通道数据采

    2024年02月09日
    浏览(57)
  • 基于FPGA的MSK调制波形Verilog代码Quartus仿真

    名称:基于FPGA的MSK调制波形Verilog代码Quartus仿真(文末获取) 软件:Quartus 语言:Verilog 代码功能: 基于FPGA的MSK调制波形 1、输入调制原始数据,输出MSK调制波形 2、包括差分编码模块,MSK调制模块,DDS模块,有符号乘法器模块等 1. 工程文件 2. 程序文件 3. 程序编译 4. RTL图

    2024年02月20日
    浏览(39)
  • 基于FPGA的音乐喷泉控制Verilog代码Quartus仿真

    名称:基于FPGA的音乐喷泉控制Verilog代码Quartus仿真(文末获取) 软件:Quartus 语言:Verilog 代码功能: 基于FPGA的音乐喷泉控制 1、具有启动控制按键,按下后开始 2、喷泉具有6个喷嘴,可以手动切换三种工作模式 3、输入的音乐信号分为低音、中音、高音 4、将输入的音转换为

    2024年02月22日
    浏览(47)
  • 基于FPGA的电风扇控制器verilog,视频/代码

    名称:基于FPGA的电风扇控制器verilog 软件:QuartusII 语言:Verilog 代码功能: 基于FPGA的电风扇控制器  运用 EDA SOPO实验开发系统设计一个基于FPGA的电风扇定时开关控制器,能实现手动和自动模式之间的切换。要求:  (1)KI为电源开关由电源开关控制电风扇的开关,即当K1为高电平“

    2024年02月07日
    浏览(54)
  • fpga开发基于verilog HDL的四人抢答器

    鱼弦:CSDN内容合伙人、CSDN新星导师、全栈领域创作新星创作者 、51CTO(Top红人+专家博主) 、github开源爱好者(go-zero源码二次开发、游戏后端架构 https://github.com/Peakchen) 智能电子抢答器可容纳4组参赛者抢答,每组设一个抢答钮。 ③ 电路具有第一抢答信号的鉴别和锁存功能。

    2024年02月04日
    浏览(49)
  • 基于vivado+Verilog FPGA开发 — GT收发器

    代码规范:Verilog 代码规范_verilog代码编写规范-CSDN博客 开发流程:FPGA基础知识----第二章 FPGA 开发流程_fpga 一个项目的整个流程-CSDN博客   源码下载:GitHub - Redamancy785/FPGA-Learning-Record: 项目博客:https://blog.csdn.net/weixin_51460407 零、低速通信接口的缺陷 1、同步通信要求传输数据

    2024年04月17日
    浏览(63)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包