CAN协议FPGA篇

news/2024/10/17 20:19:50/

一.引言

        CAN(Controller Area Network)总线,即控制器局域网总线,是一种功能丰富的车用总线标准。该协议最初是由德国博世(Bosch)公司在1983年制定的,之后在美国密歇根州底特律举行的汽车工程师协会(SAE) 会议上正式发布推出。1987年,Intel公司推出的首款CAN总线芯片(82526)上市销售。1991年,奔驰汽车发布的第一款基于CAN总线的多路布线系统汽车——W140量产,1993年,国际标准化组织(ISO)发布了CAN标准ISO 11898。后来CAN标准被重新编译分成两个部分:ISO 11898-1涵盖了数据链路层,ISO 11898-2涵盖了高速CAN总线的物理层,所以ISO 11898是针对通信速率为125Kbps~1Mbps的高速通信标准。与此同时,还有另一个标准ISO 11519是针对通信速率为125Kbps以下的低速CAN通信标准,不过ISO 11519后来被此后发布的ISO 11898-3:2006所替代。当然,现在新版的CAN总线芯片支持的通信速率最高波特率也已达5Mbps。

 

二.CAN总线协议

(1) CAN总线协议图       

 

(2)标准协议数据解析图 

 

 (3)拓展协议信息解析图

 

 

(4)CAN总线协议传输图

 

三.FPGA框架设计

(1)控制器设计框图 

 

(2)CAN系统设计框图

 

四.FPGA代码 

(1)整体控制 

//连接其他模块
//寄存器模块can_registers i_can_registers (.clk(clk_i),.rst(rst),.cs(cs),.we(we),….)//连接 Bit Timing Logic 模块can_btl i_can_btl (.clk(clk_i),.rst(rst),.rx(rx_i),…)//连接 Bit Streaming Processor 模块can_bsp i_can_bsp(.clk(clk_i),.rst(rst),…)//选择输出 fifo 或者寄存器中的数据模式always @ (extended_mode or addr or reset_mode)beginif (extended_mode & (~reset_mode) & ((addr >= 8'd16) && (addr <= 8'd28)) | (~extended_mode)& ((addr >= 8'd20) && (addr <= 8'd29)))data_out_fifo_selected <= 1'b1;elsedata_out_fifo_selected <= 1'b0;end//输出数据always @ (posedge clk_i)beginif (cs & (~we))beginif (data_out_fifo_selected)data_out <=#Tp data_out_fifo;elsedata_out <=#Tp data_out_regs;endend// 锁存地址always @ (negedge clk_i or posedge rst)beginif (rst)addr_latched <= 8'h0;else if (ale_i)addr_latched <=#Tp port_0_io;end// 产生延迟信号always @ (posedge clk_i or posedge rst)beginif (rst)beginwr_i_q <= 1'b0;rd_i_q <= 1'b0;endelsebeginwr_i_q <=#Tp wr_i;rd_i_q <=#Tp rd_i;endend//组合得到多个信号,如片选、重起等assign cs = ((wr_i & (~wr_i_q)) | (rd_i & (~rd_i_q))) & cs_can_i;assign rst = rst_i;assign we = wr_i;assign addr = addr_latched;assign data_in = port_0_io;assign port_0_io = (cs_can_i & rd_i)? data_out : 8'hz;

 (2)寄存器控制模块

always @ (posedge clk)begintx_successful_q <=#Tp tx_successful;overrun_q <=#Tp overrun;transmit_buffer_status_q <=#Tp transmit_buffer_status;info_empty_q <=#Tp info_empty;error_status_q <=#Tp error_status;node_bus_off_q <=#Tp node_bus_off;node_error_passive_q <=#Tp node_error_passive;end…//模式寄存器wire [0:0] mode;wire [4:1] mode_basic;wire [3:1] mode_ext;wire receive_irq_en_basic;wire transmit_irq_en_basic;wire error_irq_en_basic;wire overrun_irq_en_basic;can_register_asyn_syn #(1, 1'h1) MODE_REG0( .data_in(data_in[0]),.data_out(mode[0]),.we(we_mode),.clk(clk),.rst(rst),.rst_sync(set_reset_mode));can_register_asyn #(4, 0) MODE_REG_BASIC( .data_in(data_in[4:1]),.data_out(mode_basic[4:1]),.we(we_mode),.clk(clk),.rst(rst));can_register_asyn #(3, 0) MODE_REG_EXT( .data_in(data_in[3:1]),.data_out(mode_ext[3:1]),.we(we_mode & reset_mode),.clk(clk),.rst(rst));//命令寄存器wire [4:0] command;can_register_asyn_syn #(1, 1'h0) COMMAND_REG0( .data_in(data_in[0]),.data_out(command[0]),.we(we_command),.clk(clk),.rst(rst),.rst_sync(tx_request & sample_point));can_register_asyn_syn #(1, 1'h0) COMMAND_REG1( .data_in(data_in[1]),.data_out(command[1]),.we(we_command),.clk(clk),.rst(rst),.rst_sync(abort_tx & ~transmitting));can_register_asyn_syn #(2, 2'h0) COMMAND_REG( .data_in(data_in[3:2]),.data_out(command[3:2]),.we(we_command),.clk(clk),.rst(rst),.rst_sync(|command[3:2]));can_register_asyn_syn #(1, 1'h0) COMMAND_REG4( .data_in(data_in[4]),.data_out(command[4]),.we(we_command),.clk(clk),.rst(rst),.rst_sync(tx_successful & (~tx_successful_q) | abort_tx));assign self_rx_request = command[4] & (~command[0]);assign clear_data_overrun = command[3];assign release_buffer = command[2];assign abort_tx = command[1] & (~command[0]) & (~command[4]);assign tx_request = command[0] | command[4];always @ (posedge clk or posedge rst)beginif (rst)single_shot_transmission <= 1'b0;else if (we_command & data_in[1] & (data_in[1] | data_in[4]))single_shot_transmission <=#Tp 1'b1;else if (tx_successful & (~tx_successful_q))single_shot_transmission <=#Tp 1'b0;end//状态寄存器wire [7:0] status;assign status[7] = node_bus_off;assign status[6] = error_status;assign status[5] = transmit_status;assign status[4] = receive_status;assign status[3] = transmission_complete;assign status[2] = transmit_buffer_status;assign status[1] = overrun_status;assign status[0] = receive_buffer_status;always @ (posedge clk or posedge rst)beginif (rst)transmission_complete <= 1'b1;else if (tx_successful & (~tx_successful_q) | abort_tx)transmission_complete <=#Tp 1'b1;else if (tx_request)transmission_complete <=#Tp 1'b0;endalways @ (posedge clk or posedge rst)beginif (rst)transmit_buffer_status <= 1'b1;else if (tx_request)transmit_buffer_status <=#Tp 1'b0;else if (~need_to_tx)transmit_buffer_status <=#Tp 1'b1;endalways @ (posedge clk or posedge rst)beginif (rst)overrun_status <= 1'b0;else if (overrun & (~overrun_q))overrun_status <=#Tp 1'b1;else if (clear_data_overrun)overrun_status <=#Tp 1'b0;endalways @ (posedge clk or posedge rst)beginif (rst)receive_buffer_status <= 1'b0;else if (release_buffer)receive_buffer_status <=#Tp 1'b0;else if (~info_empty)receive_buffer_status <=#Tp 1'b1;end//总线时序寄存器 1wire [7:0] bus_timing_0;can_register #(8) BUS_TIMING_0_REG( .data_in(data_in),.data_out(bus_timing_0),.we(we_bus_timing_0),.clk(clk));assign baud_r_presc = bus_timing_0[5:0];assign sync_jump_width = bus_timing_0[7:6];//总线时序寄存器 2wire [7:0] bus_timing_1;can_register #(8) BUS_TIMING_1_REG( .data_in(data_in),.data_out(bus_timing_1),.we(we_bus_timing_1),.clk(clk));assign time_segment1 = bus_timing_1[3:0];assign time_segment2 = bus_timing_1[6:4];assign triple_sampling = bus_timing_1[7];//错误提示寄存器can_register_asyn #(8, 96) ERROR_WARNING_REG( .data_in(data_in),.data_out(error_warning_limit),.we(we_error_warning_limit),.clk(clk),.rst(rst));//时钟分频寄存器wire [7:0] clock_divider;wire clock_off;wire [2:0] cd;reg [2:0] clkout_div;reg [2:0] clkout_cnt;reg clkout_tmp;//reg clkout;can_register #(1) CLOCK_DIVIDER_REG_7( .data_in(data_in[7]),.data_out(clock_divider[7]),.we(we_clock_divider_hi),.clk(clk));assign clock_divider[6:4] = 3'h0;can_register #(1) CLOCK_DIVIDER_REG_3( .data_in(data_in[3]),.data_out(clock_divider[3]),.we(we_clock_divider_hi),.clk(clk));can_register #(3) CLOCK_DIVIDER_REG_LOW( .data_in(data_in[2:0]),.data_out(clock_divider[2:0]),.we(we_clock_divider_low),.clk(clk));assign extended_mode = clock_divider[7];assign clock_off = clock_divider[3];assign cd[2:0] = clock_divider[2:0];always @ (cd)begincase (cd) // synopsys_full_case synopsys_paralel_case3'b000 : clkout_div <= 0;3'b001 : clkout_div <= 1;3'b010 : clkout_div <= 2;3'b011 : clkout_div <= 3;3'b100 : clkout_div <= 4;3'b101 : clkout_div <= 5;3'b110 : clkout_div <= 6;3'b111 : clkout_div <= 0;endcaseendalways @ (posedge clk or posedge rst)beginif (rst)clkout_cnt <= 3'h0;else if (clkout_cnt == clkout_div)clkout_cnt <=#Tp 3'h0;elseclkout_cnt <= clkout_cnt + 1'b1;endalways @ (posedge clk or posedge rst)beginif (rst)clkout_tmp <= 1'b0;else if (clkout_cnt == clkout_div)clkout_tmp <=#Tp ~clkout_tmp;endalways @ (cd or clkout_tmp or clock_off)beginif (clock_off)clkout <=#Tp 1'b1;elseclkout <=#Tp clkout_tmp;endassign clkout = clock_off ? 1'b1 : ((&cd)? clk : clkout_tmp);//从寄存器中读数据always @ ( addr or read or extended_mode or mode or bus_timing_0 or bus_timing_1 or clock_divideroracceptance_code_0 or acceptance_code_1 or acceptance_code_2 or acceptance_code_3oracceptance_mask_0 or acceptance_mask_1 or acceptance_mask_2 or acceptance_mask_3orreset_mode or tx_data_0 or tx_data_1 or tx_data_2 or tx_data_3 or tx_data_4 ortx_data_5 or tx_data_6 or tx_data_7 or tx_data_8 or tx_data_9 or status orerror_warning_limit or rx_err_cnt or tx_err_cnt or irq_en_ext or irq_reg ormode_ext orarbitration_lost_capture or rx_message_counter or mode_basic orerror_capture_code)beginif(read) // readbeginif (extended_mode) // EXTENDED mode (Different register map depends on mode)begincase(addr)8'd0 : data_out_tmp <= {4'b0000, mode_ext[3:1], mode[0]};8'd1 : data_out_tmp <= 8'h0;8'd2 : data_out_tmp <= status;8'd3 : data_out_tmp <= irq_reg;8'd4 : data_out_tmp <= irq_en_ext;8'd6 : data_out_tmp <= bus_timing_0;8'd7 : data_out_tmp <= bus_timing_1;8'd11 : data_out_tmp <= {3'h0, arbitration_lost_capture[4:0]};8'd12 : data_out_tmp <= error_capture_code;8'd13 : data_out_tmp <= error_warning_limit;8'd14 : data_out_tmp <= rx_err_cnt;8'd15 : data_out_tmp <= tx_err_cnt;8'd16 : data_out_tmp <= acceptance_code_0;8'd17 : data_out_tmp <= acceptance_code_1;8'd18 : data_out_tmp <= acceptance_code_2;8'd19 : data_out_tmp <= acceptance_code_3;8'd20 : data_out_tmp <= acceptance_mask_0;8'd21 : data_out_tmp <= acceptance_mask_1;8'd22 : data_out_tmp <= acceptance_mask_2;8'd23 : data_out_tmp <= acceptance_mask_3;8'd24 : data_out_tmp <= 8'h0;8'd25 : data_out_tmp <= 8'h0;8'd26 : data_out_tmp <= 8'h0;8'd27 : data_out_tmp <= 8'h0;8'd28 : data_out_tmp <= 8'h0;8'd29 : data_out_tmp <= {1'b0, rx_message_counter};8'd31 : data_out_tmp <= clock_divider;default: data_out_tmp <= 8'h0;endcaseendelse // BASIC modebegincase(addr)8'd0 : data_out_tmp <= {3'b001, mode_basic[4:1], mode[0]};8'd1 : data_out_tmp <= 8'hff;8'd2 : data_out_tmp <= status;8'd3 : data_out_tmp <= {4'hf, irq_reg[3:0]};8'd4 : data_out_tmp <= reset_mode? acceptance_code_0 : 8'hff;8'd5 : data_out_tmp <= reset_mode? acceptance_mask_0 : 8'hff;8'd6 : data_out_tmp <= reset_mode? bus_timing_0 : 8'hff;8'd7 : data_out_tmp <= reset_mode? bus_timing_1 : 8'hff;8'd10 : data_out_tmp <= reset_mode? 8'hff : tx_data_0;8'd11 : data_out_tmp <= reset_mode? 8'hff : tx_data_1;8'd12 : data_out_tmp <= reset_mode? 8'hff : tx_data_2;8'd13 : data_out_tmp <= reset_mode? 8'hff : tx_data_3;8'd14 : data_out_tmp <= reset_mode? 8'hff : tx_data_4;8'd15 : data_out_tmp <= reset_mode? 8'hff : tx_data_5;8'd16 : data_out_tmp <= reset_mode? 8'hff : tx_data_6;8'd17 : data_out_tmp <= reset_mode? 8'hff : tx_data_7;8'd18 : data_out_tmp <= reset_mode? 8'hff : tx_data_8;8'd19 : data_out_tmp <= reset_mode? 8'hff : tx_data_9;8'd31 : data_out_tmp <= clock_divider;default: data_out_tmp <= 8'h0;endcaseendendelsedata_out_tmp <= 8'h0;endalways @ (posedge clk or posedge rst)beginif (rst)data_out <= 0;else if (read)data_out <=#Tp data_out_tmp;end

(3)时序逻辑模块

//计数器always @ (posedge clk or posedge rst)beginif (rst)clk_cnt <= 0;else if (clk_cnt == (preset_cnt-1))clk_cnt <=#Tp 0;elseclk_cnt <=#Tp clk_cnt + 1;end//产生定义波特率的一般使能信号always @ (posedge clk or posedge rst)beginif (rst)clk_en <= 1'b0;else if (clk_cnt == (preset_cnt-1))clk_en <=#Tp 1'b1;elseclk_en <=#Tp 1'b0;end//改变状态assign go_sync = clk_en & (seg2 & (~hard_sync) & (~resync) & ((quant_cnt == time_segment2)));assign go_seg1 = clk_en & (sync | hard_sync | (resync & seg2 & sync_window) | (resync_latched& sync_window));assign go_seg2 = clk_en & (seg1 & (~hard_sync) & (quant_cnt == (time_segment1 + delay)));//当探测到 SJW 字段的沿时,同步请求被锁存并被执行always @ (posedge clk or posedge rst)beginif (rst)resync_latched <= 1'b0;else if (resync & seg2 & (~sync_window))resync_latched <=#Tp 1'b1;else if (go_seg1)resync_latched <= 1'b0;end//同步的平台或片断always @ (posedge clk or posedge rst)beginif (rst)sync <= 0;else if (go_sync)sync <=#Tp 1'b1;else if (go_seg1)sync <=#Tp 1'b0;endassign tx_point = go_sync;//片断 seg1always @ (posedge clk or posedge rst)beginif (rst)seg1 <= 1;else if (go_seg1)seg1 <=#Tp 1'b1;else if (go_seg2)seg1 <=#Tp 1'b0;end//片断 seg2always @ (posedge clk or posedge rst)beginif (rst)seg2 <= 0;else if (go_seg2)seg2 <=#Tp 1'b1;else if (go_sync | go_seg1)seg2 <=#Tp 1'b0;end//Quant 计数器always @ (posedge clk or posedge rst)beginif (rst)quant_cnt <= 0;else if (go_sync | go_seg1 | go_seg2)quant_cnt <=#Tp 0;else if (clk_en)quant_cnt <=#Tp quant_cnt + 1'b1;end//当探测到后沿时,片断 seg1 被延时beginif (rst)delay <= 0;else if (clk_en & resync & seg1)delay <=#Tp (quant_cnt > sync_jump_width)? (sync_jump_width + 1) : (quant_cnt + 1);else if (go_sync | go_seg1)delay <=#Tp 0;end//如果沿出现在这个窗口中,相位的错误将得到完全的补偿assign sync_window = ((time_segment2 - quant_cnt) < ( sync_jump_width + 1));//数据采样always @ (posedge clk or posedge rst)beginif (rst)sample <= 2'b11;else if (clk_en)sample <= {sample[0], rx};end//获得使能后,采样完成always @ (posedge clk or posedge rst)beginif (rst)beginsampled_bit <= 1;sampled_bit_q <= 1;sample_point <= 0;endelse if (clk_en & (~hard_sync))beginif (seg1 & (quant_cnt == (time_segment1 + delay)))beginsample_point <=#Tp 1;sampled_bit_q <=#Tp sampled_bit;if (triple_sampling)sampled_bit <=#Tp (sample[0] & sample[1]) | ( sample[0] & rx) | (sample[1] & rx);elsesampled_bit <=#Tp rx;endendelsesample_point <=#Tp 0;end//阻塞同步always @ (posedge clk or posedge rst)beginif (rst)sync_blocked <=#Tp 1'b0;else if (clk_en)beginif (hard_sync | resync)sync_blocked <=#Tp 1'b1;else if (seg2 & quant_cnt == time_segment2)sync_blocked <=#Tp 1'b0;endend//阻塞重同步直到收到开始信号/* Blocking resynchronization until reception starts (needed because after reset mode exitswe are waiting forend-of-frame and interframe. No resynchronization is needed meanwhile). */always @ (posedge clk or posedge rst)beginif (rst)resync_blocked <=#Tp 1'b1;else if (reset_mode)resync_blocked <=#Tp 1'b1;else if (hard_sync)resync_blocked <=#Tp 1'b0;end

 (4)位数据流处理器模块

//各个数据收发的起始状态
//接收数据的 idle 状态always @ (posedge clk or posedge rst)beginif (rst)rx_idle <= 1'b0;else if (reset_mode | go_rx_id1 | error_frame)rx_idle <=#Tp 1'b0;else if (go_rx_idle)rx_idle <=#Tp 1'b1;end// 接收数据的 id1 状态always @ (posedge clk or posedge rst)beginif (rst)rx_id1 <= 1'b0;else if (reset_mode | go_rx_rtr1 | error_frame)rx_id1 <=#Tp 1'b0;else if (go_rx_id1)rx_id1 <=#Tp 1'b1;end//接收数据的 rtr1 状态always @ (posedge clk or posedge rst)beginif (rst)rx_rtr1 <= 1'b0;else if (reset_mode | go_rx_ide | error_frame)rx_rtr1 <=#Tp 1'b0;else if (go_rx_rtr1)rx_rtr1 <=#Tp 1'b1;end//接收数据的 ide 状态always @ (posedge clk or posedge rst)beginif (rst)rx_ide <= 1'b0;else if (reset_mode | go_rx_r0 | go_rx_id2 | error_frame)rx_ide <=#Tp 1'b0;else if (go_rx_ide)rx_ide <=#Tp 1'b1;end//接收数据的 id2 状态always @ (posedge clk or posedge rst)beginif (rst)rx_id2 <= 1'b0;else if (reset_mode | go_rx_rtr2 | error_frame)rx_id2 <=#Tp 1'b0;else if (go_rx_id2)rx_id2 <=#Tp 1'b1;end//接收数据的 rtr2 状态always @ (posedge clk or posedge rst)beginif (rst)rx_rtr2 <= 1'b0;else if (reset_mode | go_rx_r1 | error_frame)rx_rtr2 <=#Tp 1'b0;else if (go_rx_rtr2)rx_rtr2 <=#Tp 1'b1;end//接收数据的 r0 状态always @ (posedge clk or posedge rst)beginif (rst)rx_r1 <= 1'b0;else if (reset_mode | go_rx_r0 | error_frame)rx_r1 <=#Tp 1'b0;else if (go_rx_r1)rx_r1 <=#Tp 1'b1;end//接收数据的 r0 状态always @ (posedge clk or posedge rst)beginif (rst)rx_r0 <= 1'b0;else if (reset_mode | go_rx_dlc | error_frame)rx_r0 <=#Tp 1'b0;else if (go_rx_r0)rx_r0 <=#Tp 1'b1;end//接收数据的 dlc 状态always @ (posedge clk or posedge rst)beginif (rst)rx_dlc <= 1'b0;else if (reset_mode | go_rx_data | go_rx_crc | error_frame)rx_dlc <=#Tp 1'b0;else if (go_rx_dlc)rx_dlc <=#Tp 1'b1;end//接收数据状态always @ (posedge clk or posedge rst)beginif (rst)rx_data <= 1'b0;else if (reset_mode | go_rx_crc | error_frame)rx_data <=#Tp 1'b0;else if (go_rx_data)rx_data <=#Tp 1'b1;end// 接收数据的 crc 状态always @ (posedge clk or posedge rst)beginif (rst)rx_crc <= 1'b0;else if (reset_mode | go_rx_crc_lim | error_frame)rx_crc <=#Tp 1'b0;else if (go_rx_crc)rx_crc <=#Tp 1'b1;end//接收数据 crc 分隔符状态always @ (posedge clk or posedge rst)beginif (rst)rx_crc_lim <= 1'b0;else if (reset_mode | go_rx_ack | error_frame)rx_crc_lim <=#Tp 1'b0;else if (go_rx_crc_lim)rx_crc_lim <=#Tp 1'b1;end//接收数据的应答状态always @ (posedge clk or posedge rst)beginif (rst)rx_ack <= 1'b0;else if (reset_mode | go_rx_ack_lim | error_frame)rx_ack <=#Tp 1'b0;else if (go_rx_ack)rx_ack <=#Tp 1'b1;end//接收数据分隔符状态always @ (posedge clk or posedge rst)beginif (rst)rx_ack_lim <= 1'b0;else if (reset_mode | go_rx_eof | error_frame)rx_ack_lim <=#Tp 1'b0;else if (go_rx_ack_lim)rx_ack_lim <=#Tp 1'b1;end//接收数据的帧尾状态always @ (posedge clk or posedge rst)beginif (rst)rx_eof <= 1'b0;else if (go_rx_inter | error_frame | go_overload_frame)rx_eof <=#Tp 1'b0;else if (go_rx_eof)rx_eof <=#Tp 1'b1;end//帧间空间状态always @ (posedge clk or posedge rst)beginif (rst)rx_inter <= 1'b0;else if (reset_mode | go_rx_idle | go_rx_id1 | go_overload_frame | go_error_frame)rx_inter <=#Tp 1'b0;else if (go_rx_inter)rx_inter <=#Tp 1'b1;end// ID 寄存器always @ (posedge clk or posedge rst)beginif (rst)id <= 0;else if (sample_point & (rx_id1 | rx_id2) & (~bit_de_stuff))id <=#Tp {id[27:0], sampled_bit};end// rtr1 位always @ (posedge clk or posedge rst)beginif (rst)rtr1 <= 0;else if (sample_point & rx_rtr1 & (~bit_de_stuff))rtr1 <=#Tp sampled_bit;end// rtr2 位always @ (posedge clk or posedge rst)beginif (rst)rtr2 <= 0;else if (sample_point & rx_rtr2 & (~bit_de_stuff))rtr2 <=#Tp sampled_bit;end// ide 位always @ (posedge clk or posedge rst)beginif (rst)ide <= 0;else if (sample_point & rx_ide & (~bit_de_stuff))ide <=#Tp sampled_bit;end// 获得数据长度always @ (posedge clk or posedge rst)beginif (rst)data_len <= 0;else if (sample_point & rx_dlc & (~bit_de_stuff))data_len <=#Tp {data_len[2:0], sampled_bit};end// 获得数据always @ (posedge clk or posedge rst)beginif (rst)tmp_data <= 0;else if (sample_point & rx_data & (~bit_de_stuff))tmp_data <=#Tp {tmp_data[6:0], sampled_bit};endalways @ (posedge clk or posedge rst)beginif (rst)write_data_to_tmp_fifo <= 0;else if (sample_point & rx_data & (~bit_de_stuff) & (&bit_cnt[2:0]))write_data_to_tmp_fifo <=#Tp 1'b1;elsewrite_data_to_tmp_fifo <=#Tp 0;endalways @ (posedge clk or posedge rst)beginif (rst)byte_cnt <= 0;else if (write_data_to_tmp_fifo)byte_cnt <=#Tp byte_cnt + 1;else if (reset_mode | (sample_point & go_rx_crc_lim))byte_cnt <=#Tp 0;endalways @ (posedge clk)beginif (write_data_to_tmp_fifo)tmp_fifo[byte_cnt] <=#Tp tmp_data;end// CRC 校验数据always @ (posedge clk or posedge rst)beginif (rst)crc_in <= 0;else if (sample_point & rx_crc & (~bit_de_stuff))crc_in <=#Tp {crc_in[13:0], sampled_bit};end//计数器always @ (posedge clk or posedge rst)beginif (rst)bit_cnt <= 0;else if (go_rx_id1 | go_rx_id2 | go_rx_dlc | go_rx_data | go_rx_crc |go_rx_ack | go_rx_eof | go_rx_inter | go_error_frame | go_overload_frame)bit_cnt <=#Tp 0;else if (sample_point & (~bit_de_stuff))bit_cnt <=#Tp bit_cnt + 1'b1;end//帧尾计数器always @ (posedge clk or posedge rst)beginif (rst)eof_cnt <= 0;else if (sample_point)beginif (reset_mode | go_rx_inter | go_error_frame | go_overload_frame)eof_cnt <=#Tp 0;else if (rx_eof)eof_cnt <=#Tp eof_cnt + 1'b1;endend// 使能位填充always @ (posedge clk or posedge rst)beginif (rst)bit_stuff_cnt_en <= 1'b0;else if (bit_de_stuff_set)bit_stuff_cnt_en <=#Tp 1'b1;else if (bit_de_stuff_reset)bit_stuff_cnt_en <=#Tp 1'b0;end//位填充计数器always @ (posedge clk or posedge rst)beginif (rst)bit_stuff_cnt <= 1;else if (bit_de_stuff_reset)bit_stuff_cnt <=#Tp 1;else if (sample_point & bit_stuff_cnt_en)beginif (bit_stuff_cnt == 5)bit_stuff_cnt <=#Tp 1;else if (sampled_bit == sampled_bit_q)bit_stuff_cnt <=#Tp bit_stuff_cnt + 1'b1;elsebit_stuff_cnt <=#Tp 1;endend// 发送数据的使能位填充always @ (posedge clk or posedge rst)beginif (rst)bit_stuff_cnt_tx_en <= 1'b0;else if (bit_de_stuff_set & transmitting)bit_stuff_cnt_tx_en <=#Tp 1'b1;else if (bit_de_stuff_reset)bit_stuff_cnt_tx_en <=#Tp 1'b0;end//发送数据的位填充计数always @ (posedge clk or posedge rst)beginif (rst)bit_stuff_cnt_tx <= 1;else if (bit_de_stuff_reset)bit_stuff_cnt_tx <=#Tp 1;else if (tx_point_q & bit_stuff_cnt_en)beginif (bit_stuff_cnt_tx == 5)bit_stuff_cnt_tx <=#Tp 1;else if (tx == tx_q)bit_stuff_cnt_tx <=#Tp bit_stuff_cnt_tx + 1'b1;elsebit_stuff_cnt_tx <=#Tp 1;endendassign bit_de_stuff = bit_stuff_cnt == 5;assign bit_de_stuff_tx = bit_stuff_cnt_tx == 5;//位填充错误assign stuff_err = sample_point & bit_stuff_cnt_en & bit_de_stuff & (sampled_bit ==sampled_bit_q);//产生延迟信号always @ (posedge clk)beginreset_mode_q <=#Tp reset_mode;node_bus_off_q <=#Tp node_bus_off;endalways @ (posedge clk or posedge rst)beginif (rst)crc_enable <= 1'b0;else if (go_crc_enable)crc_enable <=#Tp 1'b1;else if (reset_mode | rst_crc_enable)crc_enable <=#Tp 1'b0;end//CRC 校验错误always @ (posedge clk or posedge rst)beginif (rst)crc_err <= 1'b0;else if (go_rx_ack)crc_err <=#Tp crc_in != calculated_crc;else if (reset_mode | error_frame_ended)crc_err <=#Tp 1'b0;end// 一般错误的条件assign form_err = sample_point & ( ((~bit_de_stuff) & rx_ide & sampled_bit & (~rtr1)) |(rx_crc_lim & (~sampled_bit)) | (rx_ack_lim & (~sampled_bit)) | ((eof_cnt < 6) & rx_eof &(~sampled_bit) & (~tx_state) ) | (& rx_eof & (~sampled_bit) & tx_state));always @ (posedge clk or posedge rst)beginif (rst)ack_err_latched <= 1'b0;else if (reset_mode | error_frame_ended | go_overload_frame)ack_err_latched <=#Tp 1'b0;else if (ack_err)ack_err_latched <=#Tp 1'b1;endalways @ (posedge clk or posedge rst)beginif (rst)bit_err_latched <= 1'b0;else if (reset_mode | error_frame_ended | go_overload_frame)bit_err_latched <=#Tp 1'b0;else if (bit_err)bit_err_latched <=#Tp 1'b1;end//规则 5assign rule5 = (~node_error_passive) & bit_err & (error_frame & (error_cnt1 < 7) |overload_frame & (overload_cnt1 < 7) );//规则 3always @ (posedge clk or posedge rst)beginif (rst)rule3_exc1_1 <= 1'b0;else if (reset_mode | error_flag_over | rule3_exc1_2)rule3_exc1_1 <=#Tp 1'b0;else if (transmitter & node_error_passive & ack_err)rule3_exc1_1 <=#Tp 1'b1;endalways @ (posedge clk or posedge rst)beginif (rst)rule3_exc1_2 <= 1'b0;else if (reset_mode | error_flag_over)rule3_exc1_2 <=#Tp 1'b0;else if (rule3_exc1_1)rule3_exc1_2 <=#Tp 1'b1;else if ((error_cnt1 < 7) & sample_point & (~sampled_bit))rule3_exc1_2 <=#Tp 1'b0;endalways @ (posedge clk or posedge rst)beginif (rst)rule3_exc2 <= 1'b0;else if (reset_mode | error_flag_over)rule3_exc2 <=#Tp 1'b0;else if (transmitter & stuff_err & arbitration_field & sample_point & tx & (~sampled_bit))rule3_exc2 <=#Tp 1'b1;endalways @ (posedge clk or posedge rst)beginif (rst)stuff_err_latched <= 1'b0;else if (reset_mode | error_frame_ended | go_overload_frame)stuff_err_latched <=#Tp 1'b0;else if (stuff_err)stuff_err_latched <=#Tp 1'b1;endalways @ (posedge clk or posedge rst)beginif (rst)form_err_latched <= 1'b0;else if (reset_mode | error_frame_ended | go_overload_frame)form_err_latched <=#Tp 1'b0;else if (form_err)form_err_latched <=#Tp 1'b1;end//接收数据的 CRC 校验
can_crc i_can_crc_rx(.clk(clk),.data(sampled_bit),.enable(crc_enable & sample_point & (~bit_de_stuff)),.initialize(go_crc_enable),.crc(calculated_crc));assign no_byte0 = rtr1 | (data_len<1);
assign no_byte1 = rtr1 | (data_len<2);// 接收数据 FIFO 的写使能always @ (posedge clk or posedge rst)beginif (rst)wr_fifo <= 1'b0;else if (reset_wr_fifo)wr_fifo <=#Tp 1'b0;else if (go_rx_inter & id_ok & (~error_frame_ended) & ((~tx_state) | self_rx_request))wr_fifo <=#Tp 1'b1;endalways @ (posedge clk or posedge rst)beginif (rst)header_cnt <= 0;else if (reset_wr_fifo)header_cnt <=#Tp 0;else if (wr_fifo & storing_header)header_cnt <=#Tp header_cnt + 1;end//数据计数器always @ (posedge clk or posedge rst)beginif (rst)data_cnt <= 0;else if (reset_wr_fifo)data_cnt <=#Tp 0;else if (wr_fifo)data_cnt <=#Tp data_cnt + 1;end// 数据的合成并保存到 FIFO 中always @ (extended_mode or ide or data_cnt or header_cnt or header_len orstoring_header or id or rtr1 or rtr2 or data_len ortmp_fifo[0] or tmp_fifo[2] or tmp_fifo[4] or tmp_fifo[6] ortmp_fifo[1] or tmp_fifo[3] or tmp_fifo[5] or tmp_fifo[7])beginif (storing_header)beginif (extended_mode) // extended modebeginif (ide) // extended formatbegincase (header_cnt) // synthesis parallel_case3'h0 : data_for_fifo <= {1'b1, rtr2, 2'h0, data_len};3'h1 : data_for_fifo <= id[28:21];3'h2 : data_for_fifo <= id[20:13];3'h3 : data_for_fifo <= id[12:5];3'h4 : data_for_fifo <= {id[4:0], 3'h0};default: data_for_fifo <= 0;endcaseendelse // standard formatbegincase (header_cnt) // synthesis parallel_case3'h0 : data_for_fifo <= {1'b0, rtr1, 2'h0, data_len};3'h1 : data_for_fifo <= id[10:3];3'h2 : data_for_fifo <= {id[2:0], 5'h0};default: data_for_fifo <= 0;endcaseendendelse // normal modebegincase (header_cnt) // synthesis parallel_case3'h0 : data_for_fifo <= id[10:3];3'h1 : data_for_fifo <= {id[2:0], rtr1, data_len};default: data_for_fifo <= 0;endcaseendendelsedata_for_fifo <= tmp_fifo[data_cnt-header_len];end// 传输错误帧always @ (posedge clk or posedge rst)beginif (rst)error_frame <= 1'b0;else if (reset_mode | error_frame_ended | go_overload_frame)error_frame <=#Tp 1'b0;else if (go_error_frame)error_frame <=#Tp 1'b1;endalways @ (posedge clk)beginif (sample_point)error_frame_q <=#Tp error_frame;endalways @ (posedge clk or posedge rst)beginif (rst)error_cnt1 <= 1'b0;else if (reset_mode | error_frame_ended | go_error_frame | go_overload_frame)error_cnt1 <=#Tp 1'b0;else if (error_frame & tx_point & (error_cnt1 < 7))error_cnt1 <=#Tp error_cnt1 + 1'b1;endassign error_flag_over = ((~node_error_passive) & sample_point & (error_cnt1 == 7) |node_error_passive & sample_point & (passive_cnt == 5)) & (~enable_error_cnt2);always @ (posedge clk or posedge rst)beginif (rst)error_flag_over_blocked <= 1'b0;else if (reset_mode | error_frame_ended | go_error_frame | go_overload_frame)error_flag_over_blocked <=#Tp 1'b0;else if (error_flag_over)error_flag_over_blocked <=#Tp 1'b1;endalways @ (posedge clk or posedge rst)beginif (rst)enable_error_cnt2 <= 1'b0;else if (reset_mode | error_frame_ended | go_error_frame | go_overload_frame)enable_error_cnt2 <=#Tp 1'b0;else if (error_frame & (error_flag_over & sampled_bit))enable_error_cnt2 <=#Tp 1'b1;endalways @ (posedge clk or posedge rst)beginif (rst)error_cnt2 <= 0;else if (reset_mode | error_frame_ended | go_error_frame | go_overload_frame)error_cnt2 <=#Tp 0;else if (enable_error_cnt2 & tx_point)error_cnt2 <=#Tp error_cnt2 + 1'b1;endalways @ (posedge clk or posedge rst)beginif (rst)delayed_dominant_cnt <= 0;else if (reset_mode | enable_error_cnt2 | go_error_frame | enable_overload_cnt2 |go_overload_frame)delayed_dominant_cnt <=#Tp 0;else if (sample_point & (~sampled_bit) & ((error_cnt1 == 7) | (overload_cnt1 == 7)))delayed_dominant_cnt <=#Tp delayed_dominant_cnt + 1'b1;end//被动计数always @ (posedge clk or posedge rst)beginif (rst)passive_cnt <= 0;else if (reset_mode | error_frame_ended | go_error_frame | go_overload_frame)passive_cnt <=#Tp 0;else if (sample_point & (passive_cnt < 5))beginif (error_frame_q & (~enable_error_cnt2) & (sampled_bit == sampled_bit_q))passive_cnt <=#Tp passive_cnt + 1'b1;elsepassive_cnt <=#Tp 0;endend// 传输超载帧
always @ (posedge clk or posedge rst)
begin
if (rst)
overload_frame <= 1'b0;
else if (reset_mode | overload_frame_ended | go_error_frame)
overload_frame <=#Tp 1'b0;
else if (go_overload_frame)
overload_frame <=#Tp 1'b1;
end
always @ (posedge clk or posedge rst)
begin
if (rst)
overload_cnt1 <= 1'b0;
else if (reset_mode | overload_frame_ended | go_error_frame | go_overload_frame)
overload_cnt1 <=#Tp 1'b0;
else if (overload_frame & tx_point & (overload_cnt1 < 7))
overload_cnt1 <=#Tp overload_cnt1 + 1'b1;
end
assign overload_flag_over = sample_point & (overload_cnt1 == 7) & (~enable_overload_cnt2);
always @ (posedge clk or posedge rst)
begin
if (rst)
enable_overload_cnt2 <= 1'b0;
else if (reset_mode | overload_frame_ended | go_error_frame | go_overload_frame)
enable_overload_cnt2 <=#Tp 1'b0;
else if (overload_frame & (overload_flag_over & sampled_bit))
enable_overload_cnt2 <=#Tp 1'b1;
end
always @ (posedge clk or posedge rst)
begin
if (rst)
overload_cnt2 <= 0;
else if (reset_mode | overload_frame_ended | go_error_frame | go_overload_frame)
overload_cnt2 <=#Tp 0;
else if (enable_overload_cnt2 & tx_point)
overload_cnt2 <=#Tp overload_cnt2 + 1'b1;
end
always @ (posedge clk or posedge rst)
begin
if (rst)
overload_frame_blocked <= 0;
else if (reset_mode | go_error_frame | go_rx_id1)
overload_frame_blocked <=#Tp 0;
else if (go_overload_frame & overload_frame) // This is a second sequential
overload
overload_frame_blocked <=#Tp 1'b1;
end
assign send_ack = (~tx_state) & rx_ack & (~err) & (~listen_only_mode);
always @ (posedge clk or posedge rst)
begin
if (rst)
tx <= 1'b1;
else if (reset_mode) // Reset
tx <=#Tp 1'b1;
else if (tx_point)
begin
if (tx_state) // 传输报文
tx <=#Tp ((~bit_de_stuff_tx) & tx_bit) | (bit_de_stuff_tx & (~tx_q));
else if (send_ack) // 应答
tx <=#Tp 1'b0;
else if (overload_frame) //传输超载帧
begin
if (overload_cnt1 < 6)
tx <=#Tp 1'b0;
else
tx <=#Tp 1'b1;
end
else if (error_frame) // 传输错误帧
begin
if (error_cnt1 < 6)
begin
if (node_error_passive)
tx <=#Tp 1'b1;
else
tx <=#Tp 1'b0;
end
else
tx <=#Tp 1'b1;
end
else
tx <=#Tp 1'b1;
end
end
always @ (posedge clk)
begin
if (tx_point)
tx_q <=#Tp tx & (~go_early_tx_latched);
end
//延迟发送数据
always @ (posedge clk)
begin
tx_point_q <=#Tp tx_point;
end

(5)CRC校验模块

assign crc_next = data ^ crc[14];assign crc_tmp = {crc[13:0], 1'b0};//CRC 校验always @ (posedge clk)beginif(initialize)crc <= #Tp 0;else if (enable)beginif (crc_next)crc <= #Tp crc_tmp ^ 15'h4599;elsecrc <= #Tp crc_tmp;endend

(6)FIFO模块

assign write_length_info = (~wr) & wr_q;//延迟写信号always @ (posedge clk or posedge rst)beginif (rst)wr_q <= 0;else if (reset_mode)wr_q <=#Tp 0;elsewr_q <=#Tp wr;end// 数据长度计数器always @ (posedge clk or posedge rst)beginif (rst)len_cnt <= 0;else if (reset_mode | write_length_info)len_cnt <=#Tp 1'b0;else if (wr & (~fifo_full))len_cnt <=#Tp len_cnt + 1'b1;end// 写信息指针always @ (posedge clk or posedge rst)beginif (rst)wr_info_pointer <= 0;else if (reset_mode)wr_info_pointer <=#Tp 0;else if (write_length_info & (~info_full))wr_info_pointer <=#Tp wr_info_pointer + 1'b1;end//读信息指针always @ (posedge clk or posedge rst)beginif (rst)rd_info_pointer <= 0;else if (reset_mode)rd_info_pointer <=#Tp 0;else if (release_buffer & (~fifo_empty))rd_info_pointer <=#Tp rd_info_pointer + 1'b1;end// 读指针always @ (posedge clk or posedge rst)beginif (rst)rd_pointer <= 0;else if (release_buffer & (~fifo_empty))rd_pointer <=#Tp rd_pointer + length_info;else if (reset_mode)rd_pointer <=#Tp 0;end// 写指针always @ (posedge clk or posedge rst)beginif (rst)wr_pointer <= 0;else if (wr & (~fifo_full))wr_pointer <=#Tp wr_pointer + 1'b1;else if (reset_mode)wr_pointer <=#Tp 0;end//锁存always @ (posedge clk or posedge rst)beginif (rst)latch_overrun <= 0;else if (reset_mode | write_length_info)latch_overrun <=#Tp 0;else if (wr & fifo_full)latch_overrun <=#Tp 1'b1;end//统计在 FIFO 中的数据always @ (posedge clk or posedge rst)beginif (rst)fifo_cnt <= 0;else if (wr & (~release_buffer) & (~fifo_full))fifo_cnt <=#Tp fifo_cnt + 1'b1;else if ((~wr) & release_buffer & (~fifo_empty))fifo_cnt <=#Tp fifo_cnt - length_info;else if (wr & release_buffer & (~fifo_full) & (~fifo_empty))fifo_cnt <=#Tp fifo_cnt - length_info + 1'b1;else if (reset_mode)fifo_cnt <=#Tp 0;endassign fifo_full = fifo_cnt == 64;assign fifo_empty = fifo_cnt == 0;//统计在 length_fifo 和 overrun_info fifo 中的数据always @ (posedge clk or posedge rst)beginif (rst)info_cnt <= 0;else if (write_length_info ^ release_buffer)beginif (release_buffer & (~info_empty))info_cnt <=#Tp info_cnt - 1'b1;else if (write_length_info & (~info_full))info_cnt <=#Tp info_cnt + 1'b1;endendassign info_full = info_cnt == 64;assign info_empty = info_cnt == 0;//选择用来读数据的 FIFO 的地址always @ (extended_mode or rd_pointer or addr)beginif (extended_mode) // extended modebeginread_address <= rd_pointer + (addr - 8'd16);endelse // normal modebeginread_address <= rd_pointer + (addr - 8'd20);endendalways @ (posedge clk)beginif (wr & (~fifo_full))fifo[wr_pointer] <=#Tp data_in;end//从 FIFO 中读数据assign data_out = fifo[read_address];//写到 length_fifoalways @ (posedge clk)beginif (write_length_info & (~info_full))length_fifo[wr_info_pointer] <=#Tp len_cnt;end// 读 length_fifo 中的数据assign length_info = length_fifo[rd_info_pointer];// overrun_infoalways @ (posedge clk)beginif (write_length_info & (~info_full))overrun_info[wr_info_pointer] <=#Tp latch_overrun | (wr & fifo_full);end// 读取 overrunassign overrun = overrun_info[rd_info_pointer]

 


http://www.ppmy.cn/news/1283230.html

相关文章

python产生任意位数随机密码的示例代码

import string rdmstrstring.ascii_lettersstring.digitsstring.punctuation; #依次是26*2个字母&#xff0c;0-9数字&#xff0c;标点符号 import random print(.join([random.choice(rdmstr) for i in range(15)])) #其中把15改为任意整数就可以设置密码长度

Volume Control 2

为游戏添加音乐和音效总是需要一些编码来设置一个系统来控制、显示和保存应用程序的音量设置。 音量控制的设计是为了立即为您设置这些内容,让您有更多时间专注于最重要的事情——制作出色的游戏! 在版本2中,我们对系统进行了重新设计,使其更加模块化、灵活,甚至更易于使用…

Java 面试题集锦记录

Java 面试题集锦记录 一1. SpringBoot、SpringCloud区别2. SpringCloud怎么保证服务间通信&#xff1f;3. Spring怎么保持高可用性、稳定性&#xff1f;4. 负载均衡5. [Rabbitmq](https://blog.csdn.net/qq_40985985/article/details/128013229) 怎么避免重复消费&#xff0c;[…

嵌入式开发——DMA外设到内存

学习目标 加强理解DMA数据传输过程加强掌握DMA的初始化流程掌握DMA数据表查询理解源和目标的配置理解数据传输特点能够动态配置源数据学习内容 需求 uint8_t data; 串口接收(&data);data有数据了 实现串口的数据接收,要求采用dma的方式。 数据交互流程 CPU配置好DMA外…

数模学习02-Matlab基础知识入门

先把matlab下载好。然后你就会发现电脑有少了几十个GB。服啦~ 修改字体 字体真的是太小了&#xff0c;其实我无论是使用什么编辑器我一般都会先改字体&#xff0c;字体在开始中有一个预设&#xff0c;可以修改字体&#xff0c;这样眼睛看着也会舒服一点 命令行窗口的使用 这…

AutoSAR(基础入门篇)2.2-AutoSAR架构中的Ports类型与Runnables可运行实体

Ports的类型 一、接口的类型 1、S/R接口 2、C/S接口 Runnables可运行实体

【力扣题解】P589-N叉树的前序遍历-Java题解

&#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【力扣题解】 文章目录 【力扣题解】P589-N叉树的前序遍历&#x1f30f;题目描述&#x1f4a1;题解&#x1f30f;总结 【力…

Matlab:解非线性方程组

1、基于问题求解非线性方程组 例&#xff1a; xoptimvar(x,2); %将x定义为一个二元素优化变量 eq1exp(-exp(-(x(1)x(2))))x(2)*(1x(1)^2); %创建第一个方程作为优化等式表达式 eq2x(1)*cos(x(2))x(2)*sin(x(1))1/2; %创建第二个方程作为优化等式表达式 probe…