CAN總線控制器IP核的代碼分析
/* Mode register */本文引用地址:http://m.butianyuan.cn/article/170785.htm
.reset_mode(reset_mode),
.listen_only_mode(listen_only_mode),
.acceptance_filter_mode(acceptance_filter_mode),
.self_test_mode(self_test_mode),
/* Command register */
.release_buffer(release_buffer),
.tx_request(tx_request),
.abort_tx(abort_tx),
.self_rx_request(self_rx_request),
.single_shot_transmission(single_shot_transmission),
/* Arbitration Lost Capture Register */
.read_arbitration_lost_capture_reg(read_arbitration_lost_capture_reg),
/* Error Code Capture Register */
.read_error_code_capture_reg(read_error_code_capture_reg),
.error_capture_code(error_capture_code),
/* Error Warning Limit register */
.error_warning_limit(error_warning_limit),
/* Rx Error Counter register */
.we_rx_err_cnt(we_rx_err_cnt),
/* Tx Error Counter register */
.we_tx_err_cnt(we_tx_err_cnt),
/* Clock Divider register */
.extended_mode(extended_mode),
/* output from can_bsp module */
.rx_idle(rx_idle),
.transmitting(transmitting),
.last_bit_of_inter(last_bit_of_inter),
.set_reset_mode(set_reset_mode),
.node_bus_off(node_bus_off),
.error_status(error_status),
.rx_err_cnt({rx_err_cnt_dummy, rx_err_cnt[7:0]}), // The MSB is not displayed. It is just used for easier calculation (no counter overflow).
.tx_err_cnt({tx_err_cnt_dummy, tx_err_cnt[7:0]}), // The MSB is not displayed. It is just used for easier calculation (no counter overflow).
.transmit_status(transmit_status),
.receive_status(receive_status),
.tx_successful(tx_successful),
.need_to_tx(need_to_tx),
.overrun(overrun),
.info_empty(info_empty),
.set_bus_error_irq(set_bus_error_irq),
.set_arbitration_lost_irq(set_arbitration_lost_irq),
.arbitration_lost_capture(arbitration_lost_capture),
.node_error_passive(node_error_passive),
.node_error_active(node_error_active),
.rx_message_counter(rx_message_counter),
/* This section is for BASIC and EXTENDED mode */
/* Acceptance code register */
.acceptance_code_0(acceptance_code_0),
/* Acceptance mask register */
.acceptance_mask_0(acceptance_mask_0),
/* End: This section is for BASIC and EXTENDED mode */
/* This section is for EXTENDED mode */
/* Acceptance code register */
.acceptance_code_1(acceptance_code_1),
.acceptance_code_2(acceptance_code_2),
.acceptance_code_3(acceptance_code_3),
/* Acceptance mask register */
.acceptance_mask_1(acceptance_mask_1),
.acceptance_mask_2(acceptance_mask_2),
.acceptance_mask_3(acceptance_mask_3),
/* End: This section is for EXTENDED mode */
/* Tx data registers. Holding identifier (basic mode), tx frame information (extended mode) and data */
.tx_data_0(tx_data_0),
.tx_data_1(tx_data_1),
.tx_data_2(tx_data_2),
.tx_data_3(tx_data_3),
.tx_data_4(tx_data_4),
.tx_data_5(tx_data_5),
.tx_data_6(tx_data_6),
.tx_data_7(tx_data_7),
.tx_data_8(tx_data_8),
.tx_data_9(tx_data_9),
.tx_data_10(tx_data_10),
.tx_data_11(tx_data_11),
.tx_data_12(tx_data_12),
/* End: Tx data registers */
/* Tx signal */
.tx(tx_out),
.tx_oen(tx_oen)
);
assign tx_o = tx_oen? 1'bz : tx_out;
// Multiplexing wb_dat_o from registers and rx fifo
always @ (extended_mode or addr or reset_mode)
begin
if (extended_mode (~reset_mode) ((addr >= 8'd16) (addr = 8'd28)) | (~extended_mode) ((addr >= 8'd20) (addr = 8'd29)))
data_out_fifo_selected = 1'b1;
else
data_out_fifo_selected = 1'b0;
end
always @ (posedge clk_i)
begin
// if (wb_cyc_i (~wb_we_i))
if (cs (~we))
begin
if (data_out_fifo_selected)
data_out =#Tp data_out_fifo;
else
data_out =#Tp data_out_regs;
end
end
`ifdef CAN_WISHBONE_IF
// Combining wb_cyc_i and wb_stb_i signals to cs signal. Than synchronizing to clk_i clock domain.
always @ (posedge clk_i or posedge rst)
begin
if (rst)
begin
cs_sync1 = 1'b0;
cs_sync2 = 1'b0;
cs_sync3 = 1'b0;
cs_sync_rst1 = 1'b0;
cs_sync_rst2 = 1'b0;
end
else
begin
cs_sync1 =#Tp wb_cyc_i wb_stb_i (~cs_sync_rst2) cs_can_i;
cs_sync2 =#Tp cs_sync1 (~cs_sync_rst2);
cs_sync3 =#Tp cs_sync2 (~cs_sync_rst2);
cs_sync_rst1 =#Tp cs_ack3;
cs_sync_rst2 =#Tp cs_sync_rst1;
end
end
assign cs = cs_sync2 (~cs_sync3);
always @ (posedge wb_clk_i)
begin
cs_ack1 =#Tp cs_sync3;
cs_ack2 =#Tp cs_ack1;
cs_ack3 =#Tp cs_ack2;
end
// Generating acknowledge signal
always @ (posedge wb_clk_i)
begin
wb_ack_o =#Tp (cs_ack2 (~cs_ack3));
end
assign rst = wb_rst_i;
assign we = wb_we_i;
assign addr = wb_adr_i;
assign data_in = wb_dat_i;
assign wb_dat_o = data_out;
`else
// Latching address
always @ (negedge clk_i or posedge rst)
begin
if (rst)
addr_latched = 8'h0;
else if (ale_i)
addr_latched =#Tp port_0_io;
end
// Generating delayed wr_i and rd_i signals
always @ (posedge clk_i or posedge rst)
begin
if (rst)
begin
wr_i_q = 1'b0;
rd_i_q = 1'b0;
end
else
begin
wr_i_q =#Tp wr_i;
rd_i_q =#Tp rd_i;
end
end
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;
`endif
endmodule
評論