├── .gitignore ├── CODINGSTYLE.md ├── LICENSE ├── Makefile ├── README.md ├── can_acf.v ├── can_bsp.v ├── can_btl.v ├── can_crc.v ├── can_fifo.v ├── can_ibo.v ├── can_register.v ├── can_register_asyn.v ├── can_register_asyn_syn.v ├── can_register_syn.v ├── can_registers.v ├── can_top.v ├── can_top_defines.v ├── can_top_tb.v └── testbench ├── canbus.v ├── fixture.inc ├── old_testbench.v ├── tasks.inc ├── test_acceptance_filter.v ├── test_rx_tx.v └── timings.inc /.gitignore: -------------------------------------------------------------------------------- 1 | *.test 2 | .*.swp 3 | *.vcd 4 | -------------------------------------------------------------------------------- /CODINGSTYLE.md: -------------------------------------------------------------------------------- 1 | # vim: colorcolumn=80 fo+=a 2 | 3 | General verilog coding style 4 | ============================ 5 | 6 | Overall the style is similar to the C coding style of the linux kernel, adapted 7 | to verilog. 8 | 9 | 10 | * Code- and textwidth should not be more than 80 characters. 11 | 12 | * Indent using a single tab (and not space(s)). A single tab may be assumed to 13 | be 8 spaces wide, but it is and stays a tab. 14 | 15 | * Remove needless whitespace, e.g. at end of lines. 16 | 17 | 18 | * Always place `begin` and `end`, even if optional. 19 | 20 | * Place `begin` on same line as corresponding statement (e.g. with `for`, 21 | `else`, `if` or `always`). 22 | 23 | * Always break the line after `begin`. Exception: place `begin` and `end` 24 | separately for `fork` children. 25 | 26 | * If a long statement with a `begin` at the end has to be broken up (e.g. long 27 | if-statement), leave an empty line before any further code. 28 | 29 | * `end` may be followed by `else begin` or `else if(...) begin`. 30 | 31 | * No other code should follow an `end`. 32 | 33 | 34 | * `if` and `for` are followed by a brace, without space. `if(a=0) begin` 35 | 36 | * `always @(...)`: No space between `@` and brace. 37 | 38 | 39 | * Avoid macros and defines where possible. Use parameters or refactor your code 40 | such that you gain a backend with multiple frontend implementations that 41 | introduce the required changes. 42 | 43 | * For a larger module `mymodule`, have a single file `mymodule.v` 44 | 45 | * Smaller modules and helper-modules may be collected in a single file. 46 | 47 | * Always set the default nettype to none. 48 | 49 | * Module inputs and outputs must be fully defined and qualified in the 50 | `module()` statement: `module mymod(input wire xyz, output reg [7...0] foo)`. 51 | Do not insert `input xyz` or `wire xyz` statements inside the module 52 | definition. 53 | 54 | * Module inputs and outputs should not be marked with suffixes like `_i` or 55 | `_o`. 56 | 57 | * Use sensible i/o and variable names that can be understood by seeing them. 58 | Use `bit_ready` instead of `rdy` or `shiftreg` instead of `s`. 59 | 60 | * Full module statement including i/o definitions should not be more than a few 61 | lines, preferably single line. Consider refactoring if that is not the case. 62 | Only if that is (currently) not possible the i/o variables should be listed 63 | one per line. 64 | 65 | * Variable names are preferred to be lower case with underscore. Same goes for 66 | module names. 67 | 68 | 69 | * Track your code in a git repo (git commit style is not part of this 70 | document). 71 | 72 | 73 | Testbenches and simulation 74 | ========================== 75 | 76 | * Each module should have a testbench that does at least some minimal i/o 77 | tests. 78 | 79 | * Testbench for module `mymod` should be named `mymod_tb` and be in file 80 | `mymod_tb.v` 81 | 82 | * For a proper signal delay simulation, read the below document. LHS and RHS 83 | delay operator are usually not the correct way. 84 | http://www-inst.eecs.berkeley.edu/~cs152/fa06/handouts/CummingsHDLCON1999_BehavioralDelays_Rev1_1.pdf 85 | 86 | * Testbench errors should be added up. At the end, if there were more than zero 87 | errors, the result should be `$fatal()`. Otherwise `$finish` 88 | 89 | * Provide a make-target to run all known testbenches (*_tb.v). Run it before 90 | every commit to see if your code still works properly. 91 | 92 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | /* vim: colorcolumn=80 2 | * 3 | * This file is part of a verilog CAN controller that is SJA1000 compatible. 4 | * 5 | * Authors: 6 | * * Igor Mohor 7 | * Author of the original version at 8 | * http://www.opencores.org/projects/can/ 9 | * (which has been unmaintained since about 2009) 10 | * 11 | * * David Piegdon 12 | * Picked up project for cleanup and bugfixes in 2019 13 | * 14 | * Any additional information is available in the LICENSE file. 15 | * 16 | * Copyright (C) 2002, 2003, 2004, 2019 Authors 17 | * 18 | * This source file may be used and distributed without restriction provided 19 | * that this copyright statement is not removed from the file and that any 20 | * derivative work contains the original copyright notice and the associated 21 | * disclaimer. 22 | * 23 | * This source file is free software; you can redistribute it and/or modify it 24 | * under the terms of the GNU Lesser General Public License as published by the 25 | * Free Software Foundation; either version 2.1 of the License, or (at your 26 | * option) any later version. 27 | * 28 | * This source is distributed in the hope that it will be useful, but WITHOUT 29 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 30 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 31 | * details. 32 | * 33 | * You should have received a copy of the GNU Lesser General Public License 34 | * along with this source; if not, download it from 35 | * http://www.opencores.org/lgpl.shtml 36 | * 37 | * The CAN protocol is developed by Robert Bosch GmbH and protected by patents. 38 | * Anybody who wants to implement this CAN IP core on silicon has to obtain 39 | * a CAN protocol license from Bosch. 40 | */ 41 | 42 | 43 | The original version of this core, as published on 44 | http://www.opencores.org/projects/can/, had additional information about tests 45 | against the Bosch VHDL Reference Model and tests with real hardware. As the 46 | source code changed since then are significant, these do no longer apply. 47 | 48 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # vim: colorcolumn=80 2 | # 3 | # This file is part of a verilog CAN controller that is SJA1000 compatible. 4 | # 5 | # Authors: 6 | # * Igor Mohor 7 | # Author of the original version at 8 | # http://www.opencores.org/projects/can/ 9 | # (which has been unmaintained since about 2009) 10 | # 11 | # * David Piegdon 12 | # Picked up project for cleanup and bugfixes in 2019 13 | # 14 | # Any additional information is available in the LICENSE file. 15 | # 16 | # Copyright (C) 2002, 2003, 2004, 2019 Authors 17 | # 18 | # This source file may be used and distributed without restriction provided 19 | # that this copyright statement is not removed from the file and that any 20 | # derivative work contains the original copyright notice and the associated 21 | # disclaimer. 22 | # 23 | # This source file is free software; you can redistribute it and/or modify it 24 | # under the terms of the GNU Lesser General Public License as published by the 25 | # Free Software Foundation; either version 2.1 of the License, or (at your 26 | # option) any later version. 27 | # 28 | # This source is distributed in the hope that it will be useful, but WITHOUT 29 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 30 | # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 31 | # details. 32 | # 33 | # You should have received a copy of the GNU Lesser General Public License 34 | # along with this source; if not, download it from 35 | # http://www.opencores.org/lgpl.shtml 36 | # 37 | # The CAN protocol is developed by Robert Bosch GmbH and protected by patents. 38 | # Anybody who wants to implement this CAN IP core on silicon has to obtain 39 | # a CAN protocol license from Bosch. 40 | 41 | TESTBENCHES=$(wildcard *_tb.v) 42 | TESTS=$(TESTBENCHES:%.v=%.test) 43 | 44 | .PHONY: all run_tests clean 45 | 46 | all: run_tests 47 | 48 | run_tests: $(TESTS) 49 | @for test in $^; do \ 50 | echo $$test; \ 51 | ./$$test; \ 52 | done 53 | clean: 54 | -rm *_tb.test 55 | -rm *.vcd 56 | 57 | %_tb.test: %_tb.v %.v 58 | iverilog -Wall -Wno-timescale -s $(patsubst %.test,%,$@) -o $@ $^ 59 | 60 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Verilog CAN controller 2 | ====================== 3 | 4 | This is a fork of https://opencores.org/projects/can with the intention 5 | to improve code quality and fix several bugs. 6 | 7 | This is very much work in progess. I started working on it in 2019 when 8 | I needed fixes, but then lost track as issues were solved a different way. 9 | Hopefully the project can be picked up again now. 10 | 11 | 12 | More information to come. 13 | 14 | 15 | State 16 | ===== 17 | 18 | Currently nonfunctional. 19 | 20 | 21 | Authors 22 | ======= 23 | 24 | Authors: 25 | 26 | * Igor Mohor -- Author of the original version 27 | at http://www.opencores.org/projects/can/ 28 | (which has been unmaintained since about 2009) 29 | 30 | * David Piegdon -- Picked up project for cleanup and 31 | bugfixes in 2019 32 | 33 | 34 | License 35 | ======= 36 | 37 | Please see LICENSE file. 38 | 39 | -------------------------------------------------------------------------------- /can_acf.v: -------------------------------------------------------------------------------- 1 | /* vim: colorcolumn=80 2 | * 3 | * This file is part of a verilog CAN controller that is SJA1000 compatible. 4 | * 5 | * Authors: 6 | * * Igor Mohor 7 | * Author of the original version at 8 | * http://www.opencores.org/projects/can/ 9 | * (which has been unmaintained since about 2009) 10 | * 11 | * * David Piegdon 12 | * Picked up project for cleanup and bugfixes in 2019 13 | * 14 | * Any additional information is available in the LICENSE file. 15 | * 16 | * Copyright (C) 2002, 2003, 2004, 2019 Authors 17 | * 18 | * This source file may be used and distributed without restriction provided 19 | * that this copyright statement is not removed from the file and that any 20 | * derivative work contains the original copyright notice and the associated 21 | * disclaimer. 22 | * 23 | * This source file is free software; you can redistribute it and/or modify it 24 | * under the terms of the GNU Lesser General Public License as published by the 25 | * Free Software Foundation; either version 2.1 of the License, or (at your 26 | * option) any later version. 27 | * 28 | * This source is distributed in the hope that it will be useful, but WITHOUT 29 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 30 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 31 | * details. 32 | * 33 | * You should have received a copy of the GNU Lesser General Public License 34 | * along with this source; if not, download it from 35 | * http://www.opencores.org/lgpl.shtml 36 | * 37 | * The CAN protocol is developed by Robert Bosch GmbH and protected by patents. 38 | * Anybody who wants to implement this CAN IP core on silicon has to obtain 39 | * a CAN protocol license from Bosch. 40 | */ 41 | 42 | `default_nettype none 43 | 44 | `include "can_top_defines.v" 45 | 46 | module can_acf( 47 | input wire clk, 48 | input wire rst, 49 | input wire [28:0] id, 50 | 51 | /* Mode register */ 52 | input wire reset_mode, 53 | input wire acceptance_filter_mode, 54 | input wire extended_mode, 55 | 56 | input wire [7:0] acceptance_code_0, 57 | input wire [7:0] acceptance_code_1, 58 | input wire [7:0] acceptance_code_2, 59 | input wire [7:0] acceptance_code_3, 60 | input wire [7:0] acceptance_mask_0, 61 | input wire [7:0] acceptance_mask_1, 62 | input wire [7:0] acceptance_mask_2, 63 | input wire [7:0] acceptance_mask_3, 64 | 65 | input wire go_rx_crc_lim, 66 | input wire go_rx_inter, 67 | input wire go_error_frame, 68 | 69 | input wire [7:0] data0, 70 | input wire [7:0] data1, 71 | input wire rtr1, 72 | input wire rtr2, 73 | input wire ide, 74 | input wire no_byte0, 75 | input wire no_byte1, 76 | 77 | output reg id_ok 78 | ); 79 | 80 | parameter Tp = 1; 81 | 82 | 83 | wire match; 84 | wire match_sf_std; 85 | wire match_sf_ext; 86 | wire match_df_std; 87 | wire match_df_ext; 88 | 89 | // Working in basic mode. ID match for standard format (11-bit ID). 90 | assign match = 91 | ( (id[3] == acceptance_code_0[0] | acceptance_mask_0[0] ) 92 | & (id[4] == acceptance_code_0[1] | acceptance_mask_0[1] ) 93 | & (id[5] == acceptance_code_0[2] | acceptance_mask_0[2] ) 94 | & (id[6] == acceptance_code_0[3] | acceptance_mask_0[3] ) 95 | & (id[7] == acceptance_code_0[4] | acceptance_mask_0[4] ) 96 | & (id[8] == acceptance_code_0[5] | acceptance_mask_0[5] ) 97 | & (id[9] == acceptance_code_0[6] | acceptance_mask_0[6] ) 98 | & (id[10] == acceptance_code_0[7] | acceptance_mask_0[7] ) 99 | ); 100 | 101 | // Working in extended mode. ID match for standard format (11-bit ID). Using single filter. 102 | assign match_sf_std = 103 | ( (id[3] == acceptance_code_0[0] | acceptance_mask_0[0] ) 104 | & (id[4] == acceptance_code_0[1] | acceptance_mask_0[1] ) 105 | & (id[5] == acceptance_code_0[2] | acceptance_mask_0[2] ) 106 | & (id[6] == acceptance_code_0[3] | acceptance_mask_0[3] ) 107 | & (id[7] == acceptance_code_0[4] | acceptance_mask_0[4] ) 108 | & (id[8] == acceptance_code_0[5] | acceptance_mask_0[5] ) 109 | & (id[9] == acceptance_code_0[6] | acceptance_mask_0[6] ) 110 | & (id[10] == acceptance_code_0[7] | acceptance_mask_0[7] ) 111 | 112 | & (rtr1 == acceptance_code_1[4] | acceptance_mask_1[4] ) 113 | & (id[0] == acceptance_code_1[5] | acceptance_mask_1[5] ) 114 | & (id[1] == acceptance_code_1[6] | acceptance_mask_1[6] ) 115 | & (id[2] == acceptance_code_1[7] | acceptance_mask_1[7] ) 116 | 117 | & (data0[0] == acceptance_code_2[0] | acceptance_mask_2[0] | no_byte0) 118 | & (data0[1] == acceptance_code_2[1] | acceptance_mask_2[1] | no_byte0) 119 | & (data0[2] == acceptance_code_2[2] | acceptance_mask_2[2] | no_byte0) 120 | & (data0[3] == acceptance_code_2[3] | acceptance_mask_2[3] | no_byte0) 121 | & (data0[4] == acceptance_code_2[4] | acceptance_mask_2[4] | no_byte0) 122 | & (data0[5] == acceptance_code_2[5] | acceptance_mask_2[5] | no_byte0) 123 | & (data0[6] == acceptance_code_2[6] | acceptance_mask_2[6] | no_byte0) 124 | & (data0[7] == acceptance_code_2[7] | acceptance_mask_2[7] | no_byte0) 125 | 126 | & (data1[0] == acceptance_code_3[0] | acceptance_mask_3[0] | no_byte1) 127 | & (data1[1] == acceptance_code_3[1] | acceptance_mask_3[1] | no_byte1) 128 | & (data1[2] == acceptance_code_3[2] | acceptance_mask_3[2] | no_byte1) 129 | & (data1[3] == acceptance_code_3[3] | acceptance_mask_3[3] | no_byte1) 130 | & (data1[4] == acceptance_code_3[4] | acceptance_mask_3[4] | no_byte1) 131 | & (data1[5] == acceptance_code_3[5] | acceptance_mask_3[5] | no_byte1) 132 | & (data1[6] == acceptance_code_3[6] | acceptance_mask_3[6] | no_byte1) 133 | & (data1[7] == acceptance_code_3[7] | acceptance_mask_3[7] | no_byte1) 134 | ); 135 | 136 | // Working in extended mode. ID match for extended format (29-bit ID). Using single filter. 137 | assign match_sf_ext = 138 | ( (id[21] == acceptance_code_0[0] | acceptance_mask_0[0] ) 139 | & (id[22] == acceptance_code_0[1] | acceptance_mask_0[1] ) 140 | & (id[23] == acceptance_code_0[2] | acceptance_mask_0[2] ) 141 | & (id[24] == acceptance_code_0[3] | acceptance_mask_0[3] ) 142 | & (id[25] == acceptance_code_0[4] | acceptance_mask_0[4] ) 143 | & (id[26] == acceptance_code_0[5] | acceptance_mask_0[5] ) 144 | & (id[27] == acceptance_code_0[6] | acceptance_mask_0[6] ) 145 | & (id[28] == acceptance_code_0[7] | acceptance_mask_0[7] ) 146 | 147 | & (id[13] == acceptance_code_1[0] | acceptance_mask_1[0] ) 148 | & (id[14] == acceptance_code_1[1] | acceptance_mask_1[1] ) 149 | & (id[15] == acceptance_code_1[2] | acceptance_mask_1[2] ) 150 | & (id[16] == acceptance_code_1[3] | acceptance_mask_1[3] ) 151 | & (id[17] == acceptance_code_1[4] | acceptance_mask_1[4] ) 152 | & (id[18] == acceptance_code_1[5] | acceptance_mask_1[5] ) 153 | & (id[19] == acceptance_code_1[6] | acceptance_mask_1[6] ) 154 | & (id[20] == acceptance_code_1[7] | acceptance_mask_1[7] ) 155 | 156 | & (id[5] == acceptance_code_2[0] | acceptance_mask_2[0] ) 157 | & (id[6] == acceptance_code_2[1] | acceptance_mask_2[1] ) 158 | & (id[7] == acceptance_code_2[2] | acceptance_mask_2[2] ) 159 | & (id[8] == acceptance_code_2[3] | acceptance_mask_2[3] ) 160 | & (id[9] == acceptance_code_2[4] | acceptance_mask_2[4] ) 161 | & (id[10] == acceptance_code_2[5] | acceptance_mask_2[5] ) 162 | & (id[11] == acceptance_code_2[6] | acceptance_mask_2[6] ) 163 | & (id[12] == acceptance_code_2[7] | acceptance_mask_2[7] ) 164 | 165 | & (rtr2 == acceptance_code_3[2] | acceptance_mask_3[2] ) 166 | & (id[0] == acceptance_code_3[3] | acceptance_mask_3[3] ) 167 | & (id[1] == acceptance_code_3[4] | acceptance_mask_3[4] ) 168 | & (id[2] == acceptance_code_3[5] | acceptance_mask_3[5] ) 169 | & (id[3] == acceptance_code_3[6] | acceptance_mask_3[6] ) 170 | & (id[4] == acceptance_code_3[7] | acceptance_mask_3[7] ) 171 | ); 172 | 173 | // Working in extended mode. ID match for standard format (11-bit ID). Using double filter. 174 | assign match_df_std = 175 | ( ( (id[3] == acceptance_code_0[0] | acceptance_mask_0[0] ) 176 | & (id[4] == acceptance_code_0[1] | acceptance_mask_0[1] ) 177 | & (id[5] == acceptance_code_0[2] | acceptance_mask_0[2] ) 178 | & (id[6] == acceptance_code_0[3] | acceptance_mask_0[3] ) 179 | & (id[7] == acceptance_code_0[4] | acceptance_mask_0[4] ) 180 | & (id[8] == acceptance_code_0[5] | acceptance_mask_0[5] ) 181 | & (id[9] == acceptance_code_0[6] | acceptance_mask_0[6] ) 182 | & (id[10] == acceptance_code_0[7] | acceptance_mask_0[7] ) 183 | 184 | & (rtr1 == acceptance_code_1[4] | acceptance_mask_1[4] ) 185 | & (id[0] == acceptance_code_1[5] | acceptance_mask_1[5] ) 186 | & (id[1] == acceptance_code_1[6] | acceptance_mask_1[6] ) 187 | & (id[2] == acceptance_code_1[7] | acceptance_mask_1[7] ) 188 | 189 | & (data0[0] == acceptance_code_3[0] | acceptance_mask_3[0] | no_byte0) 190 | & (data0[1] == acceptance_code_3[1] | acceptance_mask_3[1] | no_byte0) 191 | & (data0[2] == acceptance_code_3[2] | acceptance_mask_3[2] | no_byte0) 192 | & (data0[3] == acceptance_code_3[3] | acceptance_mask_3[3] | no_byte0) 193 | & (data0[4] == acceptance_code_1[0] | acceptance_mask_1[0] | no_byte0) 194 | & (data0[5] == acceptance_code_1[1] | acceptance_mask_1[1] | no_byte0) 195 | & (data0[6] == acceptance_code_1[2] | acceptance_mask_1[2] | no_byte0) 196 | & (data0[7] == acceptance_code_1[3] | acceptance_mask_1[3] | no_byte0) 197 | ) 198 | | ( (id[3] == acceptance_code_2[0] | acceptance_mask_2[0] ) 199 | & (id[4] == acceptance_code_2[1] | acceptance_mask_2[1] ) 200 | & (id[5] == acceptance_code_2[2] | acceptance_mask_2[2] ) 201 | & (id[6] == acceptance_code_2[3] | acceptance_mask_2[3] ) 202 | & (id[7] == acceptance_code_2[4] | acceptance_mask_2[4] ) 203 | & (id[8] == acceptance_code_2[5] | acceptance_mask_2[5] ) 204 | & (id[9] == acceptance_code_2[6] | acceptance_mask_2[6] ) 205 | & (id[10] == acceptance_code_2[7] | acceptance_mask_2[7] ) 206 | 207 | & (rtr1 == acceptance_code_3[4] | acceptance_mask_3[4] ) 208 | & (id[0] == acceptance_code_3[5] | acceptance_mask_3[5] ) 209 | & (id[1] == acceptance_code_3[6] | acceptance_mask_3[6] ) 210 | & (id[2] == acceptance_code_3[7] | acceptance_mask_3[7] ) 211 | ) 212 | ); 213 | 214 | // Working in extended mode. ID match for extended format (29-bit ID). Using double filter. 215 | assign match_df_ext = 216 | ( ( (id[21] == acceptance_code_0[0] | acceptance_mask_0[0] ) 217 | & (id[22] == acceptance_code_0[1] | acceptance_mask_0[1] ) 218 | & (id[23] == acceptance_code_0[2] | acceptance_mask_0[2] ) 219 | & (id[24] == acceptance_code_0[3] | acceptance_mask_0[3] ) 220 | & (id[25] == acceptance_code_0[4] | acceptance_mask_0[4] ) 221 | & (id[26] == acceptance_code_0[5] | acceptance_mask_0[5] ) 222 | & (id[27] == acceptance_code_0[6] | acceptance_mask_0[6] ) 223 | & (id[28] == acceptance_code_0[7] | acceptance_mask_0[7] ) 224 | 225 | & (id[13] == acceptance_code_1[0] | acceptance_mask_1[0] ) 226 | & (id[14] == acceptance_code_1[1] | acceptance_mask_1[1] ) 227 | & (id[15] == acceptance_code_1[2] | acceptance_mask_1[2] ) 228 | & (id[16] == acceptance_code_1[3] | acceptance_mask_1[3] ) 229 | & (id[17] == acceptance_code_1[4] | acceptance_mask_1[4] ) 230 | & (id[18] == acceptance_code_1[5] | acceptance_mask_1[5] ) 231 | & (id[19] == acceptance_code_1[6] | acceptance_mask_1[6] ) 232 | & (id[20] == acceptance_code_1[7] | acceptance_mask_1[7] ) 233 | ) 234 | | ( (id[21] == acceptance_code_2[0] | acceptance_mask_2[0] ) 235 | & (id[22] == acceptance_code_2[1] | acceptance_mask_2[1] ) 236 | & (id[23] == acceptance_code_2[2] | acceptance_mask_2[2] ) 237 | & (id[24] == acceptance_code_2[3] | acceptance_mask_2[3] ) 238 | & (id[25] == acceptance_code_2[4] | acceptance_mask_2[4] ) 239 | & (id[26] == acceptance_code_2[5] | acceptance_mask_2[5] ) 240 | & (id[27] == acceptance_code_2[6] | acceptance_mask_2[6] ) 241 | & (id[28] == acceptance_code_2[7] | acceptance_mask_2[7] ) 242 | 243 | & (id[13] == acceptance_code_3[0] | acceptance_mask_3[0] ) 244 | & (id[14] == acceptance_code_3[1] | acceptance_mask_3[1] ) 245 | & (id[15] == acceptance_code_3[2] | acceptance_mask_3[2] ) 246 | & (id[16] == acceptance_code_3[3] | acceptance_mask_3[3] ) 247 | & (id[17] == acceptance_code_3[4] | acceptance_mask_3[4] ) 248 | & (id[18] == acceptance_code_3[5] | acceptance_mask_3[5] ) 249 | & (id[19] == acceptance_code_3[6] | acceptance_mask_3[6] ) 250 | & (id[20] == acceptance_code_3[7] | acceptance_mask_3[7] ) 251 | ) 252 | ); 253 | 254 | // ID ok signal generation 255 | always @(posedge clk or posedge rst) begin 256 | if(rst) begin 257 | id_ok <= 1'b0; 258 | end else if(go_rx_crc_lim) begin 259 | // sample_point is already included in go_rx_crc_lim 260 | if(extended_mode) begin 261 | if(~acceptance_filter_mode) begin 262 | // dual filter 263 | if(ide) begin 264 | // extended frame message 265 | id_ok <=#Tp match_df_ext; 266 | end else begin 267 | // standard frame message 268 | id_ok <=#Tp match_df_std; 269 | end 270 | end else begin 271 | // single filter 272 | if(ide) begin 273 | // extended frame message 274 | id_ok <=#Tp match_sf_ext; 275 | end else begin 276 | // standard frame message 277 | id_ok <=#Tp match_sf_std; 278 | end 279 | end 280 | end else begin 281 | id_ok <=#Tp match; 282 | end 283 | end else if(reset_mode | go_rx_inter | go_error_frame) begin 284 | // sample_point is already included in go_rx_inter 285 | id_ok <=#Tp 1'b0; 286 | end 287 | end 288 | 289 | endmodule 290 | -------------------------------------------------------------------------------- /can_bsp.v: -------------------------------------------------------------------------------- 1 | /* vim: colorcolumn=80 2 | * 3 | * This file is part of a verilog CAN controller that is SJA1000 compatible. 4 | * 5 | * Authors: 6 | * * Igor Mohor 7 | * Author of the original version at 8 | * http://www.opencores.org/projects/can/ 9 | * (which has been unmaintained since about 2009) 10 | * 11 | * * David Piegdon 12 | * Picked up project for cleanup and bugfixes in 2019 13 | * 14 | * Any additional information is available in the LICENSE file. 15 | * 16 | * Copyright (C) 2002, 2003, 2004, 2019 Authors 17 | * 18 | * This source file may be used and distributed without restriction provided 19 | * that this copyright statement is not removed from the file and that any 20 | * derivative work contains the original copyright notice and the associated 21 | * disclaimer. 22 | * 23 | * This source file is free software; you can redistribute it and/or modify it 24 | * under the terms of the GNU Lesser General Public License as published by the 25 | * Free Software Foundation; either version 2.1 of the License, or (at your 26 | * option) any later version. 27 | * 28 | * This source is distributed in the hope that it will be useful, but WITHOUT 29 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 30 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 31 | * details. 32 | * 33 | * You should have received a copy of the GNU Lesser General Public License 34 | * along with this source; if not, download it from 35 | * http://www.opencores.org/lgpl.shtml 36 | * 37 | * The CAN protocol is developed by Robert Bosch GmbH and protected by patents. 38 | * Anybody who wants to implement this CAN IP core on silicon has to obtain 39 | * a CAN protocol license from Bosch. 40 | */ 41 | 42 | `default_nettype none 43 | 44 | `include "can_top_defines.v" 45 | `include "can_crc.v" 46 | `include "can_acf.v" 47 | `include "can_fifo.v" 48 | `include "can_ibo.v" 49 | 50 | module can_bsp( 51 | input wire clk, 52 | input wire rst, 53 | 54 | input wire sample_point, 55 | input wire sampled_bit, 56 | input wire sampled_bit_q, 57 | input wire tx_point, 58 | input wire hard_sync, 59 | 60 | input wire [7:0] addr, 61 | input wire [7:0] data_in, 62 | output wire [7:0] data_out, 63 | input wire fifo_selected, 64 | 65 | /* Mode register */ 66 | input wire reset_mode, 67 | input wire listen_only_mode, 68 | input wire acceptance_filter_mode, 69 | input wire self_test_mode, 70 | 71 | /* Command register */ 72 | input wire release_buffer, 73 | input wire tx_request, 74 | input wire abort_tx, 75 | input wire self_rx_request, 76 | input wire single_shot_transmission, 77 | output reg tx_state, 78 | output reg tx_state_q, 79 | input wire overload_request, // When receiver is busy, it needs to send overload frame. Only 2 overload frames are allowed to 80 | output reg overload_frame, // be send in a row. This is not implemented, yet, because host can not send an overload request. 81 | 82 | /* Arbitration Lost Capture Register */ 83 | input wire read_arbitration_lost_capture_reg, 84 | 85 | /* Error Code Capture Register */ 86 | input wire read_error_code_capture_reg, 87 | output reg [7:0] error_capture_code, 88 | 89 | /* Error Warning Limit register */ 90 | input wire [7:0] error_warning_limit, 91 | 92 | /* Rx Error Counter register */ 93 | input wire we_rx_err_cnt, 94 | 95 | /* Tx Error Counter register */ 96 | input wire we_tx_err_cnt, 97 | 98 | /* Clock Divider register */ 99 | input wire extended_mode, 100 | 101 | output reg rx_idle, 102 | output reg transmitting, 103 | output reg transmitter, 104 | output wire go_rx_inter, 105 | output wire not_first_bit_of_inter, 106 | output reg rx_inter, 107 | output wire set_reset_mode, 108 | output reg node_bus_off, 109 | output wire error_status, 110 | output reg [8:0] rx_err_cnt, 111 | output reg [8:0] tx_err_cnt, 112 | output wire transmit_status, 113 | output wire receive_status, 114 | output wire tx_successful, 115 | output reg need_to_tx, // When the CAN core has something to transmit and a dominant bit is sampled at the third bit 116 | output wire overrun, 117 | output wire info_empty, 118 | output wire set_bus_error_irq, 119 | output wire set_arbitration_lost_irq, 120 | output reg [4:0] arbitration_lost_capture, 121 | output reg node_error_passive, 122 | output wire node_error_active, 123 | output wire [6:0] rx_message_counter, 124 | 125 | /* This section is for BASIC and EXTENDED mode */ 126 | /* Acceptance code register */ 127 | input wire [7:0] acceptance_code_0, 128 | 129 | /* Acceptance mask register */ 130 | input wire [7:0] acceptance_mask_0, 131 | /* End: This section is for BASIC and EXTENDED mode */ 132 | 133 | /* This section is for EXTENDED mode */ 134 | /* Acceptance code register */ 135 | input wire [7:0] acceptance_code_1, 136 | input wire [7:0] acceptance_code_2, 137 | input wire [7:0] acceptance_code_3, 138 | 139 | /* Acceptance mask register */ 140 | input wire [7:0] acceptance_mask_1, 141 | input wire [7:0] acceptance_mask_2, 142 | input wire [7:0] acceptance_mask_3, 143 | /* End: This section is for EXTENDED mode */ 144 | 145 | /* Tx data registers. Holding identifier (basic mode), tx frame information (extended mode) and data */ 146 | input wire [7:0] tx_data_0, 147 | input wire [7:0] tx_data_1, 148 | input wire [7:0] tx_data_2, 149 | input wire [7:0] tx_data_3, 150 | input wire [7:0] tx_data_4, 151 | input wire [7:0] tx_data_5, 152 | input wire [7:0] tx_data_6, 153 | input wire [7:0] tx_data_7, 154 | input wire [7:0] tx_data_8, 155 | input wire [7:0] tx_data_9, 156 | input wire [7:0] tx_data_10, 157 | input wire [7:0] tx_data_11, 158 | input wire [7:0] tx_data_12, 159 | /* End: Tx data registers */ 160 | 161 | /* Tx signal */ 162 | output reg tx, 163 | output reg tx_next, 164 | output wire bus_off_on, 165 | 166 | output wire go_overload_frame, 167 | output wire go_error_frame, 168 | output wire go_tx, 169 | output wire send_ack 170 | 171 | `ifdef CAN_BIST 172 | , 173 | input wire mbist_si_i, 174 | output wire mbist_so_o, 175 | input wire [`CAN_MBIST_CTRL_WIDTH - 1:0] mbist_ctrl_i 176 | `endif 177 | ); 178 | 179 | parameter Tp = 1; 180 | 181 | reg reset_mode_q; 182 | reg [5:0] bit_cnt; 183 | 184 | reg [3:0] data_len; 185 | reg [28:0] id; 186 | reg [2:0] bit_stuff_cnt; 187 | reg [2:0] bit_stuff_cnt_tx; 188 | reg tx_point_q; 189 | 190 | reg rx_id1; 191 | reg rx_rtr1; 192 | reg rx_ide; 193 | reg rx_id2; 194 | reg rx_rtr2; 195 | reg rx_r1; 196 | reg rx_r0; 197 | reg rx_dlc; 198 | reg rx_data; 199 | reg rx_crc; 200 | reg rx_crc_lim; 201 | reg rx_ack; 202 | reg rx_ack_lim; 203 | reg rx_eof; 204 | reg go_early_tx_latched; 205 | 206 | reg rtr1; 207 | reg ide; 208 | reg rtr2; 209 | reg [14:0] crc_in; 210 | 211 | reg [7:0] tmp_data; 212 | reg [7:0] tmp_fifo [0:7]; 213 | reg write_data_to_tmp_fifo; 214 | reg [2:0] byte_cnt; 215 | reg bit_stuff_cnt_en; 216 | reg crc_enable; 217 | 218 | reg [2:0] eof_cnt; 219 | reg [2:0] passive_cnt; 220 | 221 | 222 | reg error_frame; 223 | reg enable_error_cnt2; 224 | reg [2:0] error_cnt1; 225 | reg [2:0] error_cnt2; 226 | reg [2:0] delayed_dominant_cnt; 227 | reg enable_overload_cnt2; 228 | reg overload_frame_blocked; 229 | reg [1:0] overload_request_cnt; 230 | reg [2:0] overload_cnt1; 231 | reg [2:0] overload_cnt2; 232 | reg crc_err; 233 | 234 | reg arbitration_lost; 235 | reg arbitration_lost_q; 236 | reg arbitration_field_d; 237 | reg [4:0] arbitration_cnt; 238 | reg arbitration_blocked; 239 | reg tx_q; 240 | 241 | reg [3:0] data_cnt; // Counting the data bytes that are written to FIFO 242 | reg [2:0] header_cnt; // Counting header length 243 | reg wr_fifo; // Write data and header to 64-byte fifo 244 | reg [7:0] data_for_fifo;// Multiplexed data that is stored to 64-byte fifo 245 | 246 | reg [5:0] tx_pointer; 247 | reg tx_bit; 248 | reg finish_msg; 249 | 250 | reg [3:0] bus_free_cnt; 251 | reg bus_free_cnt_en; 252 | reg bus_free; 253 | reg waiting_for_bus_free; 254 | 255 | reg node_bus_off_q; 256 | reg ack_err_latched; 257 | reg bit_err_latched; 258 | reg stuff_err_latched; 259 | reg form_err_latched; 260 | reg rule3_exc1_1; 261 | reg rule3_exc1_2; 262 | reg suspend; 263 | reg susp_cnt_en; 264 | reg [2:0] susp_cnt; 265 | reg error_flag_over_latched; 266 | 267 | reg [7:6] error_capture_code_type; 268 | reg error_capture_code_blocked; 269 | reg first_compare_bit; 270 | 271 | 272 | wire [4:0] error_capture_code_segment; 273 | wire error_capture_code_direction; 274 | 275 | wire bit_de_stuff; 276 | wire bit_de_stuff_tx; 277 | 278 | wire rule5; 279 | 280 | /* Rx state machine */ 281 | wire go_rx_idle; 282 | wire go_rx_id1; 283 | wire go_rx_rtr1; 284 | wire go_rx_ide; 285 | wire go_rx_id2; 286 | wire go_rx_rtr2; 287 | wire go_rx_r1; 288 | wire go_rx_r0; 289 | wire go_rx_dlc; 290 | wire go_rx_data; 291 | wire go_rx_crc; 292 | wire go_rx_crc_lim; 293 | wire go_rx_ack; 294 | wire go_rx_ack_lim; 295 | wire go_rx_eof; 296 | 297 | wire last_bit_of_inter; 298 | 299 | wire go_crc_enable; 300 | wire rst_crc_enable; 301 | 302 | wire bit_de_stuff_set; 303 | wire bit_de_stuff_reset; 304 | 305 | wire go_early_tx; 306 | 307 | wire [14:0] calculated_crc; 308 | wire [15:0] r_calculated_crc; 309 | wire remote_rq; 310 | wire [3:0] limited_data_len; 311 | wire form_err; 312 | 313 | wire error_frame_ended; 314 | wire overload_frame_ended; 315 | wire bit_err; 316 | wire ack_err; 317 | wire stuff_err; 318 | 319 | wire id_ok; // If received ID matches ID set in registers 320 | wire no_byte0; // There is no byte 0 (RTR bit set to 1 or DLC field equal to 0). Signal used for acceptance filter. 321 | wire no_byte1; // There is no byte 1 (RTR bit set to 1 or DLC field equal to 1). Signal used for acceptance filter. 322 | 323 | wire [2:0] header_len; 324 | wire storing_header; 325 | wire [3:0] limited_data_len_minus1; 326 | wire reset_wr_fifo; 327 | wire err; 328 | 329 | wire arbitration_field; 330 | 331 | wire [18:0] basic_chain; 332 | wire [63:0] basic_chain_data; 333 | wire [18:0] extended_chain_std; 334 | wire [38:0] extended_chain_ext; 335 | wire [63:0] extended_chain_data_std; 336 | wire [63:0] extended_chain_data_ext; 337 | 338 | wire rst_tx_pointer; 339 | 340 | wire [7:0] r_tx_data_0; 341 | wire [7:0] r_tx_data_1; 342 | wire [7:0] r_tx_data_2; 343 | wire [7:0] r_tx_data_3; 344 | wire [7:0] r_tx_data_4; 345 | wire [7:0] r_tx_data_5; 346 | wire [7:0] r_tx_data_6; 347 | wire [7:0] r_tx_data_7; 348 | wire [7:0] r_tx_data_8; 349 | wire [7:0] r_tx_data_9; 350 | wire [7:0] r_tx_data_10; 351 | wire [7:0] r_tx_data_11; 352 | wire [7:0] r_tx_data_12; 353 | 354 | wire bit_err_exc1; 355 | wire bit_err_exc2; 356 | wire bit_err_exc3; 357 | wire bit_err_exc4; 358 | wire bit_err_exc5; 359 | wire bit_err_exc6; 360 | wire error_flag_over; 361 | wire overload_flag_over; 362 | 363 | wire [5:0] limited_tx_cnt_ext; 364 | wire [5:0] limited_tx_cnt_std; 365 | 366 | assign go_rx_idle = sample_point & sampled_bit & last_bit_of_inter | bus_free & (~node_bus_off); 367 | assign go_rx_id1 = sample_point & (~sampled_bit) & (rx_idle | last_bit_of_inter); 368 | assign go_rx_rtr1 = (~bit_de_stuff) & sample_point & rx_id1 & (bit_cnt[3:0] == 4'd10); 369 | assign go_rx_ide = (~bit_de_stuff) & sample_point & rx_rtr1; 370 | assign go_rx_id2 = (~bit_de_stuff) & sample_point & rx_ide & sampled_bit; 371 | assign go_rx_rtr2 = (~bit_de_stuff) & sample_point & rx_id2 & (bit_cnt[4:0] == 5'd17); 372 | assign go_rx_r1 = (~bit_de_stuff) & sample_point & rx_rtr2; 373 | assign go_rx_r0 = (~bit_de_stuff) & sample_point & (rx_ide & (~sampled_bit) | rx_r1); 374 | assign go_rx_dlc = (~bit_de_stuff) & sample_point & rx_r0; 375 | assign go_rx_data = (~bit_de_stuff) & sample_point & rx_dlc & (bit_cnt[1:0] == 2'd3) & (sampled_bit | (|data_len[2:0])) & (~remote_rq); 376 | assign go_rx_crc = (~bit_de_stuff) & sample_point & (rx_dlc & (bit_cnt[1:0] == 2'd3) & ((~sampled_bit) & (~(|data_len[2:0])) | remote_rq) | 377 | rx_data & (bit_cnt[5:0] == ((limited_data_len<<3) - 1'b1))); // overflow works ok at max value (8<<3 = 64 = 0). 0-1 = 6'h3f 378 | assign go_rx_crc_lim = (~bit_de_stuff) & sample_point & rx_crc & (bit_cnt[3:0] == 4'd14); 379 | assign go_rx_ack = (~bit_de_stuff) & sample_point & rx_crc_lim; 380 | assign go_rx_ack_lim = sample_point & rx_ack; 381 | assign go_rx_eof = sample_point & rx_ack_lim; 382 | assign go_rx_inter = ((sample_point & rx_eof & (eof_cnt == 3'd6)) | error_frame_ended | overload_frame_ended) & (~overload_request); 383 | 384 | assign go_error_frame = (form_err | stuff_err | bit_err | ack_err | (crc_err & go_rx_eof)); 385 | assign error_frame_ended = (error_cnt2 == 3'd7) & tx_point; 386 | assign overload_frame_ended = (overload_cnt2 == 3'd7) & tx_point; 387 | 388 | assign go_overload_frame = ( sample_point & ((~sampled_bit) | overload_request) & (rx_eof & (~transmitter) & (eof_cnt == 3'd6) | error_frame_ended | overload_frame_ended) | 389 | sample_point & (~sampled_bit) & rx_inter & (bit_cnt[1:0] < 2'd2) | 390 | sample_point & (~sampled_bit) & ((error_cnt2 == 3'd7) | (overload_cnt2 == 3'd7)) 391 | ) 392 | & (~overload_frame_blocked) 393 | ; 394 | 395 | 396 | assign go_crc_enable = hard_sync | go_tx; 397 | assign rst_crc_enable = go_rx_crc; 398 | 399 | assign bit_de_stuff_set = go_rx_id1 & (~go_error_frame); 400 | assign bit_de_stuff_reset = go_rx_ack | go_error_frame | go_overload_frame; 401 | 402 | assign remote_rq = ((~ide) & rtr1) | (ide & rtr2); 403 | assign limited_data_len = (data_len < 4'h8)? data_len : 4'h8; 404 | 405 | assign ack_err = rx_ack & sample_point & sampled_bit & tx_state & (~self_test_mode); 406 | assign bit_err = (tx_state | error_frame | overload_frame | rx_ack) & sample_point & (tx != sampled_bit) & (~bit_err_exc1) & (~bit_err_exc2) & (~bit_err_exc3) & (~bit_err_exc4) & (~bit_err_exc5) & (~bit_err_exc6) & (~reset_mode); 407 | assign bit_err_exc1 = tx_state & arbitration_field & tx; 408 | assign bit_err_exc2 = rx_ack & tx; 409 | assign bit_err_exc3 = error_frame & node_error_passive & (error_cnt1 < 3'd7); 410 | assign bit_err_exc4 = (error_frame & (error_cnt1 == 3'd7) & (~enable_error_cnt2)) | (overload_frame & (overload_cnt1 == 3'd7) & (~enable_overload_cnt2)); 411 | assign bit_err_exc5 = (error_frame & (error_cnt2 == 3'd7)) | (overload_frame & (overload_cnt2 == 3'd7)); 412 | assign bit_err_exc6 = (eof_cnt == 3'd6) & rx_eof & (~transmitter); 413 | 414 | assign arbitration_field = rx_id1 | rx_rtr1 | rx_ide | rx_id2 | rx_rtr2; 415 | 416 | assign last_bit_of_inter = rx_inter & (bit_cnt[1:0] == 2'd2); 417 | assign not_first_bit_of_inter = rx_inter & (bit_cnt[1:0] != 2'd0); 418 | 419 | 420 | // Rx idle state 421 | always @(posedge clk or posedge rst) begin 422 | if(rst) begin 423 | rx_idle <= 1'b0; 424 | end else if(go_rx_id1 | go_error_frame) begin 425 | rx_idle <=#Tp 1'b0; 426 | end else if(go_rx_idle) begin 427 | rx_idle <=#Tp 1'b1; 428 | end 429 | end 430 | 431 | 432 | // Rx id1 state 433 | always @(posedge clk or posedge rst) begin 434 | if(rst) begin 435 | rx_id1 <= 1'b0; 436 | end else if(go_rx_rtr1 | go_error_frame) begin 437 | rx_id1 <=#Tp 1'b0; 438 | end else if(go_rx_id1) begin 439 | rx_id1 <=#Tp 1'b1; 440 | end 441 | end 442 | 443 | 444 | // Rx rtr1 state 445 | always @(posedge clk or posedge rst) begin 446 | if(rst) begin 447 | rx_rtr1 <= 1'b0; 448 | end else if(go_rx_ide | go_error_frame) begin 449 | rx_rtr1 <=#Tp 1'b0; 450 | end else if(go_rx_rtr1) begin 451 | rx_rtr1 <=#Tp 1'b1; 452 | end 453 | end 454 | 455 | 456 | // Rx ide state 457 | always @(posedge clk or posedge rst) begin 458 | if(rst) begin 459 | rx_ide <= 1'b0; 460 | end else if(go_rx_r0 | go_rx_id2 | go_error_frame) begin 461 | rx_ide <=#Tp 1'b0; 462 | end else if(go_rx_ide) begin 463 | rx_ide <=#Tp 1'b1; 464 | end 465 | end 466 | 467 | 468 | // Rx id2 state 469 | always @(posedge clk or posedge rst) begin 470 | if(rst) begin 471 | rx_id2 <= 1'b0; 472 | end else if(go_rx_rtr2 | go_error_frame) begin 473 | rx_id2 <=#Tp 1'b0; 474 | end else if(go_rx_id2) begin 475 | rx_id2 <=#Tp 1'b1; 476 | end 477 | end 478 | 479 | 480 | // Rx rtr2 state 481 | always @(posedge clk or posedge rst) begin 482 | if(rst) begin 483 | rx_rtr2 <= 1'b0; 484 | end else if(go_rx_r1 | go_error_frame) begin 485 | rx_rtr2 <=#Tp 1'b0; 486 | end else if(go_rx_rtr2) begin 487 | rx_rtr2 <=#Tp 1'b1; 488 | end 489 | end 490 | 491 | 492 | // Rx r0 state 493 | always @(posedge clk or posedge rst) begin 494 | if(rst) begin 495 | rx_r1 <= 1'b0; 496 | end else if(go_rx_r0 | go_error_frame) begin 497 | rx_r1 <=#Tp 1'b0; 498 | end else if(go_rx_r1) begin 499 | rx_r1 <=#Tp 1'b1; 500 | end 501 | end 502 | 503 | 504 | // Rx r0 state 505 | always @(posedge clk or posedge rst) begin 506 | if(rst) begin 507 | rx_r0 <= 1'b0; 508 | end else if(go_rx_dlc | go_error_frame) begin 509 | rx_r0 <=#Tp 1'b0; 510 | end else if(go_rx_r0) begin 511 | rx_r0 <=#Tp 1'b1; 512 | end 513 | end 514 | 515 | 516 | // Rx dlc state 517 | always @(posedge clk or posedge rst) begin 518 | if(rst) begin 519 | rx_dlc <= 1'b0; 520 | end else if(go_rx_data | go_rx_crc | go_error_frame) begin 521 | rx_dlc <=#Tp 1'b0; 522 | end else if(go_rx_dlc) begin 523 | rx_dlc <=#Tp 1'b1; 524 | end 525 | end 526 | 527 | 528 | // Rx data state 529 | always @(posedge clk or posedge rst) begin 530 | if(rst) begin 531 | rx_data <= 1'b0; 532 | end else if(go_rx_crc | go_error_frame) begin 533 | rx_data <=#Tp 1'b0; 534 | end else if(go_rx_data) begin 535 | rx_data <=#Tp 1'b1; 536 | end 537 | end 538 | 539 | 540 | // Rx crc state 541 | always @(posedge clk or posedge rst) begin 542 | if(rst) begin 543 | rx_crc <= 1'b0; 544 | end else if(go_rx_crc_lim | go_error_frame) begin 545 | rx_crc <=#Tp 1'b0; 546 | end else if(go_rx_crc) begin 547 | rx_crc <=#Tp 1'b1; 548 | end 549 | end 550 | 551 | 552 | // Rx crc delimiter state 553 | always @(posedge clk or posedge rst) begin 554 | if(rst) begin 555 | rx_crc_lim <= 1'b0; 556 | end else if(go_rx_ack | go_error_frame) begin 557 | rx_crc_lim <=#Tp 1'b0; 558 | end else if(go_rx_crc_lim) begin 559 | rx_crc_lim <=#Tp 1'b1; 560 | end 561 | end 562 | 563 | 564 | // Rx ack state 565 | always @(posedge clk or posedge rst) begin 566 | if(rst) begin 567 | rx_ack <= 1'b0; 568 | end else if(go_rx_ack_lim | go_error_frame) begin 569 | rx_ack <=#Tp 1'b0; 570 | end else if(go_rx_ack) begin 571 | rx_ack <=#Tp 1'b1; 572 | end 573 | end 574 | 575 | 576 | // Rx ack delimiter state 577 | always @(posedge clk or posedge rst) begin 578 | if(rst) begin 579 | rx_ack_lim <= 1'b0; 580 | end else if(go_rx_eof | go_error_frame) begin 581 | rx_ack_lim <=#Tp 1'b0; 582 | end else if(go_rx_ack_lim) begin 583 | rx_ack_lim <=#Tp 1'b1; 584 | end 585 | end 586 | 587 | 588 | // Rx eof state 589 | always @(posedge clk or posedge rst) begin 590 | if(rst) begin 591 | rx_eof <= 1'b0; 592 | end else if(go_rx_inter | go_error_frame | go_overload_frame) begin 593 | rx_eof <=#Tp 1'b0; 594 | end else if(go_rx_eof) begin 595 | rx_eof <=#Tp 1'b1; 596 | end 597 | end 598 | 599 | 600 | 601 | // Interframe space 602 | always @(posedge clk or posedge rst) begin 603 | if(rst) begin 604 | rx_inter <= 1'b0; 605 | end else if(go_rx_idle | go_rx_id1 | go_overload_frame | go_error_frame) begin 606 | rx_inter <=#Tp 1'b0; 607 | end else if(go_rx_inter) begin 608 | rx_inter <=#Tp 1'b1; 609 | end 610 | end 611 | 612 | 613 | // ID register 614 | always @(posedge clk or posedge rst) begin 615 | if(rst) begin 616 | id <= 29'h0; 617 | end else if(sample_point & (rx_id1 | rx_id2) & (~bit_de_stuff)) begin 618 | id <=#Tp {id[27:0], sampled_bit}; 619 | end 620 | end 621 | 622 | 623 | // rtr1 bit 624 | always @(posedge clk or posedge rst) begin 625 | if(rst) begin 626 | rtr1 <= 1'b0; 627 | end else if(sample_point & rx_rtr1 & (~bit_de_stuff)) begin 628 | rtr1 <=#Tp sampled_bit; 629 | end 630 | end 631 | 632 | 633 | // rtr2 bit 634 | always @(posedge clk or posedge rst) begin 635 | if(rst) begin 636 | rtr2 <= 1'b0; 637 | end else if(sample_point & rx_rtr2 & (~bit_de_stuff)) begin 638 | rtr2 <=#Tp sampled_bit; 639 | end 640 | end 641 | 642 | 643 | // ide bit 644 | always @(posedge clk or posedge rst) begin 645 | if(rst) begin 646 | ide <= 1'b0; 647 | end else if(sample_point & rx_ide & (~bit_de_stuff)) begin 648 | ide <=#Tp sampled_bit; 649 | end 650 | end 651 | 652 | 653 | // Data length 654 | always @(posedge clk or posedge rst) begin 655 | if(rst) begin 656 | data_len <= 4'b0; 657 | end else if(sample_point & rx_dlc & (~bit_de_stuff)) begin 658 | data_len <=#Tp {data_len[2:0], sampled_bit}; 659 | end 660 | end 661 | 662 | 663 | // Data 664 | always @(posedge clk or posedge rst) begin 665 | if(rst) begin 666 | tmp_data <= 8'h0; 667 | end else if(sample_point & rx_data & (~bit_de_stuff)) begin 668 | tmp_data <=#Tp {tmp_data[6:0], sampled_bit}; 669 | end 670 | end 671 | 672 | 673 | always @(posedge clk or posedge rst) begin 674 | if(rst) begin 675 | write_data_to_tmp_fifo <= 1'b0; 676 | end else if(sample_point & rx_data & (~bit_de_stuff) & (&bit_cnt[2:0])) begin 677 | write_data_to_tmp_fifo <=#Tp 1'b1; 678 | end else begin 679 | write_data_to_tmp_fifo <=#Tp 1'b0; 680 | end 681 | end 682 | 683 | 684 | always @(posedge clk or posedge rst) begin 685 | if(rst) begin 686 | byte_cnt <= 3'h0; 687 | end else if(write_data_to_tmp_fifo) begin 688 | byte_cnt <=#Tp byte_cnt + 1'b1; 689 | end else if(sample_point & go_rx_crc_lim) begin 690 | byte_cnt <=#Tp 3'h0; 691 | end 692 | end 693 | 694 | 695 | always @(posedge clk) begin 696 | if(write_data_to_tmp_fifo) begin 697 | tmp_fifo[byte_cnt] <=#Tp tmp_data; 698 | end 699 | end 700 | 701 | 702 | 703 | // CRC 704 | always @(posedge clk or posedge rst) begin 705 | if(rst) begin 706 | crc_in <= 15'h0; 707 | end else if(sample_point & rx_crc & (~bit_de_stuff)) begin 708 | crc_in <=#Tp {crc_in[13:0], sampled_bit}; 709 | end 710 | end 711 | 712 | 713 | // bit_cnt 714 | always @(posedge clk or posedge rst) begin 715 | if(rst) begin 716 | bit_cnt <= 6'd0; 717 | end 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) begin 718 | bit_cnt <=#Tp 6'd0; 719 | end else if(sample_point & (~bit_de_stuff)) begin 720 | bit_cnt <=#Tp bit_cnt + 1'b1; 721 | end 722 | end 723 | 724 | 725 | // eof_cnt 726 | always @(posedge clk or posedge rst) begin 727 | if(rst) begin 728 | eof_cnt <= 3'd0; 729 | end else if(sample_point) begin 730 | if(go_rx_inter | go_error_frame | go_overload_frame) begin 731 | eof_cnt <=#Tp 3'd0; 732 | end else if(rx_eof) begin 733 | eof_cnt <=#Tp eof_cnt + 1'b1; 734 | end 735 | end 736 | end 737 | 738 | 739 | // Enabling bit de-stuffing 740 | always @(posedge clk or posedge rst) begin 741 | if(rst) begin 742 | bit_stuff_cnt_en <= 1'b0; 743 | end else if(bit_de_stuff_set) begin 744 | bit_stuff_cnt_en <=#Tp 1'b1; 745 | end else if(bit_de_stuff_reset) begin 746 | bit_stuff_cnt_en <=#Tp 1'b0; 747 | end 748 | end 749 | 750 | 751 | // bit_stuff_cnt 752 | always @(posedge clk or posedge rst) begin 753 | if(rst) begin 754 | bit_stuff_cnt <= 3'h1; 755 | end else if(bit_de_stuff_reset) begin 756 | bit_stuff_cnt <=#Tp 3'h1; 757 | end else if(sample_point & bit_stuff_cnt_en) begin 758 | if(bit_stuff_cnt == 3'h5) begin 759 | bit_stuff_cnt <=#Tp 3'h1; 760 | end else if(sampled_bit == sampled_bit_q) begin 761 | bit_stuff_cnt <=#Tp bit_stuff_cnt + 1'b1; 762 | end else begin 763 | bit_stuff_cnt <=#Tp 3'h1; 764 | end 765 | end 766 | end 767 | 768 | 769 | // bit_stuff_cnt_tx 770 | always @(posedge clk or posedge rst) begin 771 | if(rst) begin 772 | bit_stuff_cnt_tx <= 3'h1; 773 | end else if(reset_mode || bit_de_stuff_reset) begin 774 | bit_stuff_cnt_tx <=#Tp 3'h1; 775 | end else if(tx_point_q & bit_stuff_cnt_en) begin 776 | if(bit_stuff_cnt_tx == 3'h5) begin 777 | bit_stuff_cnt_tx <=#Tp 3'h1; 778 | end else if(tx == tx_q) begin 779 | bit_stuff_cnt_tx <=#Tp bit_stuff_cnt_tx + 1'b1; 780 | end else begin 781 | bit_stuff_cnt_tx <=#Tp 3'h1; 782 | end 783 | end 784 | end 785 | 786 | 787 | assign bit_de_stuff = bit_stuff_cnt == 3'h5; 788 | assign bit_de_stuff_tx = bit_stuff_cnt_tx == 3'h5; 789 | 790 | 791 | 792 | // stuff_err 793 | assign stuff_err = sample_point & bit_stuff_cnt_en & bit_de_stuff & (sampled_bit == sampled_bit_q); 794 | 795 | 796 | 797 | // Generating delayed signals 798 | always @(posedge clk or posedge rst) begin 799 | if(rst) begin 800 | reset_mode_q <=#Tp 1'b0; 801 | node_bus_off_q <=#Tp 1'b0; 802 | end else begin 803 | reset_mode_q <=#Tp reset_mode; 804 | node_bus_off_q <=#Tp node_bus_off; 805 | end 806 | end 807 | 808 | 809 | 810 | always @(posedge clk or posedge rst) begin 811 | if(rst) begin 812 | crc_enable <= 1'b0; 813 | end else if(rst_crc_enable) begin 814 | crc_enable <=#Tp 1'b0; 815 | end else if(go_crc_enable) begin 816 | crc_enable <=#Tp 1'b1; 817 | end 818 | end 819 | 820 | 821 | // CRC error generation 822 | always @(posedge clk or posedge rst) begin 823 | if(rst) begin 824 | crc_err <= 1'b0; 825 | end else if(reset_mode | error_frame_ended) begin 826 | crc_err <=#Tp 1'b0; 827 | end else if(go_rx_ack) begin 828 | crc_err <=#Tp crc_in != calculated_crc; 829 | end 830 | end 831 | 832 | 833 | // Conditions for form error 834 | assign form_err = sample_point & ( ((~bit_de_stuff) & rx_crc_lim & (~sampled_bit) ) | 835 | ( rx_ack_lim & (~sampled_bit) ) | 836 | ((eof_cnt < 3'd6)& rx_eof & (~sampled_bit) & (~transmitter) ) | 837 | ( & rx_eof & (~sampled_bit) & transmitter ) 838 | ); 839 | 840 | 841 | always @(posedge clk or posedge rst) begin 842 | if(rst) begin 843 | ack_err_latched <= 1'b0; 844 | end else if(reset_mode | error_frame_ended | go_overload_frame) begin 845 | ack_err_latched <=#Tp 1'b0; 846 | end else if(ack_err) begin 847 | ack_err_latched <=#Tp 1'b1; 848 | end 849 | end 850 | 851 | 852 | always @(posedge clk or posedge rst) begin 853 | if(rst) begin 854 | bit_err_latched <= 1'b0; 855 | end else if(reset_mode | error_frame_ended | go_overload_frame) begin 856 | bit_err_latched <=#Tp 1'b0; 857 | end else if(bit_err) begin 858 | bit_err_latched <=#Tp 1'b1; 859 | end 860 | end 861 | 862 | 863 | 864 | // Rule 5 (Fault confinement). 865 | assign rule5 = bit_err & ( (~node_error_passive) & error_frame & (error_cnt1 < 3'd7) 866 | | overload_frame & (overload_cnt1 < 3'd7) 867 | ); 868 | 869 | // Rule 3 exception 1 - first part (Fault confinement). 870 | always @(posedge clk or posedge rst) begin 871 | if(rst) begin 872 | rule3_exc1_1 <= 1'b0; 873 | end else if(error_flag_over | rule3_exc1_2) begin 874 | rule3_exc1_1 <=#Tp 1'b0; 875 | end else if(transmitter & node_error_passive & ack_err) begin 876 | rule3_exc1_1 <=#Tp 1'b1; 877 | end 878 | end 879 | 880 | 881 | // Rule 3 exception 1 - second part (Fault confinement). 882 | always @(posedge clk or posedge rst) begin 883 | if(rst) begin 884 | rule3_exc1_2 <= 1'b0; 885 | end else if(go_error_frame | rule3_exc1_2) begin 886 | rule3_exc1_2 <=#Tp 1'b0; 887 | end else if(rule3_exc1_1 & (error_cnt1 < 3'd7) & sample_point & (~sampled_bit)) begin 888 | rule3_exc1_2 <=#Tp 1'b1; 889 | end 890 | end 891 | 892 | 893 | always @(posedge clk or posedge rst) begin 894 | if(rst) begin 895 | stuff_err_latched <= 1'b0; 896 | end else if(reset_mode | error_frame_ended | go_overload_frame) begin 897 | stuff_err_latched <=#Tp 1'b0; 898 | end else if(stuff_err) begin 899 | stuff_err_latched <=#Tp 1'b1; 900 | end 901 | end 902 | 903 | 904 | 905 | always @(posedge clk or posedge rst) begin 906 | if(rst) begin 907 | form_err_latched <= 1'b0; 908 | end else if(reset_mode | error_frame_ended | go_overload_frame) begin 909 | form_err_latched <=#Tp 1'b0; 910 | end else if(form_err) begin 911 | form_err_latched <=#Tp 1'b1; 912 | end 913 | end 914 | 915 | 916 | 917 | // Instantiation of the RX CRC module 918 | can_crc i_can_crc_rx 919 | ( 920 | .clk(clk), 921 | .data(sampled_bit), 922 | .enable(crc_enable & sample_point & (~bit_de_stuff)), 923 | .initialize(go_crc_enable), 924 | .crc(calculated_crc) 925 | ); 926 | 927 | 928 | 929 | 930 | assign no_byte0 = rtr1 | (data_len<4'h1); 931 | assign no_byte1 = rtr1 | (data_len<4'h2); 932 | 933 | can_acf i_can_acf 934 | ( 935 | .clk(clk), 936 | .rst(rst), 937 | 938 | .id(id), 939 | 940 | /* Mode register */ 941 | .reset_mode(reset_mode), 942 | .acceptance_filter_mode(acceptance_filter_mode), 943 | 944 | // Clock Divider register 945 | .extended_mode(extended_mode), 946 | 947 | /* This section is for BASIC and EXTENDED mode */ 948 | /* Acceptance code register */ 949 | .acceptance_code_0(acceptance_code_0), 950 | 951 | /* Acceptance mask register */ 952 | .acceptance_mask_0(acceptance_mask_0), 953 | /* End: This section is for BASIC and EXTENDED mode */ 954 | 955 | /* This section is for EXTENDED mode */ 956 | /* Acceptance code register */ 957 | .acceptance_code_1(acceptance_code_1), 958 | .acceptance_code_2(acceptance_code_2), 959 | .acceptance_code_3(acceptance_code_3), 960 | 961 | /* Acceptance mask register */ 962 | .acceptance_mask_1(acceptance_mask_1), 963 | .acceptance_mask_2(acceptance_mask_2), 964 | .acceptance_mask_3(acceptance_mask_3), 965 | /* End: This section is for EXTENDED mode */ 966 | 967 | .go_rx_crc_lim(go_rx_crc_lim), 968 | .go_rx_inter(go_rx_inter), 969 | .go_error_frame(go_error_frame), 970 | 971 | .data0(tmp_fifo[0]), 972 | .data1(tmp_fifo[1]), 973 | .rtr1(rtr1), 974 | .rtr2(rtr2), 975 | .ide(ide), 976 | .no_byte0(no_byte0), 977 | .no_byte1(no_byte1), 978 | 979 | .id_ok(id_ok) 980 | ); 981 | 982 | 983 | 984 | 985 | assign header_len[2:0] = extended_mode ? (ide? (3'h5) : (3'h3)) : 3'h2; 986 | assign storing_header = header_cnt < header_len; 987 | assign limited_data_len_minus1[3:0] = remote_rq? 4'hf : ((data_len < 4'h8)? (data_len -1'b1) : 4'h7); // - 1 because counter counts from 0 988 | assign reset_wr_fifo = (data_cnt == (limited_data_len_minus1 + {1'b0, header_len})) || reset_mode; 989 | 990 | assign err = form_err | stuff_err | bit_err | ack_err | form_err_latched | stuff_err_latched | bit_err_latched | ack_err_latched | crc_err; 991 | 992 | 993 | 994 | // Write enable signal for 64-byte rx fifo 995 | always @(posedge clk or posedge rst) begin 996 | if(rst) begin 997 | wr_fifo <= 1'b0; 998 | end else if(reset_wr_fifo) begin 999 | wr_fifo <=#Tp 1'b0; 1000 | end else if(go_rx_inter & id_ok & (~error_frame_ended) & ((~tx_state) | self_rx_request)) begin 1001 | wr_fifo <=#Tp 1'b1; 1002 | end 1003 | end 1004 | 1005 | 1006 | // Header counter. Header length depends on the mode of operation and frame format. 1007 | always @(posedge clk or posedge rst) begin 1008 | if(rst) begin 1009 | header_cnt <= 3'h0; 1010 | end else if(reset_wr_fifo) begin 1011 | header_cnt <=#Tp 3'h0; 1012 | end else if(wr_fifo & storing_header) begin 1013 | header_cnt <=#Tp header_cnt + 1'h1; 1014 | end 1015 | end 1016 | 1017 | 1018 | // Data counter. Length of the data is limited to 8 bytes. 1019 | always @(posedge clk or posedge rst) begin 1020 | if(rst) begin 1021 | data_cnt <= 4'h0; 1022 | end else if(reset_wr_fifo) begin 1023 | data_cnt <=#Tp 4'h0; 1024 | end else if(wr_fifo) begin 1025 | data_cnt <=#Tp data_cnt + 4'h1; 1026 | end 1027 | end 1028 | 1029 | 1030 | // Multiplexing data that is stored to 64-byte fifo depends on the mode of operation and frame format 1031 | always @(extended_mode or ide or data_cnt or header_cnt or header_len or 1032 | storing_header or id or rtr1 or rtr2 or data_len or 1033 | tmp_fifo[0] or tmp_fifo[2] or tmp_fifo[4] or tmp_fifo[6] or 1034 | tmp_fifo[1] or tmp_fifo[3] or tmp_fifo[5] or tmp_fifo[7]) begin 1035 | 1036 | casex ({storing_header, extended_mode, ide, header_cnt}) /* synthesis parallel_case */ 1037 | 6'b1_1_1_000 : data_for_fifo = {1'b1, rtr2, 2'h0, data_len}; // extended mode, extended format header 1038 | 6'b1_1_1_001 : data_for_fifo = id[28:21]; // extended mode, extended format header 1039 | 6'b1_1_1_010 : data_for_fifo = id[20:13]; // extended mode, extended format header 1040 | 6'b1_1_1_011 : data_for_fifo = id[12:5]; // extended mode, extended format header 1041 | 6'b1_1_1_100 : data_for_fifo = {id[4:0], 3'h0}; // extended mode, extended format header 1042 | 6'b1_1_0_000 : data_for_fifo = {1'b0, rtr1, 2'h0, data_len}; // extended mode, standard format header 1043 | 6'b1_1_0_001 : data_for_fifo = id[10:3]; // extended mode, standard format header 1044 | 6'b1_1_0_010 : data_for_fifo = {id[2:0], rtr1, 4'h0}; // extended mode, standard format header 1045 | 6'b1_0_x_000 : data_for_fifo = id[10:3]; // normal mode header 1046 | 6'b1_0_x_001 : data_for_fifo = {id[2:0], rtr1, data_len}; // normal mode header 1047 | default : data_for_fifo = tmp_fifo[data_cnt - {1'b0, header_len}]; // data 1048 | endcase 1049 | end 1050 | 1051 | 1052 | 1053 | 1054 | // Instantiation of the RX fifo module 1055 | can_fifo i_can_fifo 1056 | ( 1057 | .clk(clk), 1058 | .rst(rst), 1059 | 1060 | .wr(wr_fifo), 1061 | 1062 | .data_in(data_for_fifo), 1063 | .addr(addr[5:0]), 1064 | .data_out(data_out), 1065 | .fifo_selected(fifo_selected), 1066 | 1067 | .reset_mode(reset_mode), 1068 | .release_buffer(release_buffer), 1069 | .extended_mode(extended_mode), 1070 | .overrun(overrun), 1071 | .info_empty(info_empty), 1072 | .info_cnt(rx_message_counter) 1073 | 1074 | `ifdef CAN_BIST 1075 | , 1076 | .mbist_si_i(mbist_si_i), 1077 | .mbist_so_o(mbist_so_o), 1078 | .mbist_ctrl_i(mbist_ctrl_i) 1079 | `endif 1080 | ); 1081 | 1082 | 1083 | // Transmitting error frame. 1084 | always @(posedge clk or posedge rst) begin 1085 | if(rst) begin 1086 | error_frame <= 1'b0; 1087 | //end else if(reset_mode || error_frame_ended || go_overload_frame) begin 1088 | end else if(set_reset_mode || error_frame_ended || go_overload_frame) begin 1089 | error_frame <=#Tp 1'b0; 1090 | end else if(go_error_frame) begin 1091 | error_frame <=#Tp 1'b1; 1092 | end 1093 | end 1094 | 1095 | 1096 | 1097 | always @(posedge clk or posedge rst) begin 1098 | if(rst) begin 1099 | error_cnt1 <= 3'd0; 1100 | end else if(error_frame_ended | go_error_frame | go_overload_frame) begin 1101 | error_cnt1 <=#Tp 3'd0; 1102 | end else if(error_frame & tx_point & (error_cnt1 < 3'd7)) begin 1103 | error_cnt1 <=#Tp error_cnt1 + 1'b1; 1104 | end 1105 | end 1106 | 1107 | 1108 | 1109 | assign error_flag_over = ((~node_error_passive) & sample_point & (error_cnt1 == 3'd7) | node_error_passive & sample_point & (passive_cnt == 3'h6)) & (~enable_error_cnt2); 1110 | 1111 | 1112 | always @(posedge clk or posedge rst) begin 1113 | if(rst) begin 1114 | error_flag_over_latched <= 1'b0; 1115 | end else if(error_frame_ended | go_error_frame | go_overload_frame) begin 1116 | error_flag_over_latched <=#Tp 1'b0; 1117 | end else if(error_flag_over) begin 1118 | error_flag_over_latched <=#Tp 1'b1; 1119 | end 1120 | end 1121 | 1122 | 1123 | always @(posedge clk or posedge rst) begin 1124 | if(rst) begin 1125 | enable_error_cnt2 <= 1'b0; 1126 | end else if(error_frame_ended | go_error_frame | go_overload_frame) begin 1127 | enable_error_cnt2 <=#Tp 1'b0; 1128 | end else if(error_frame & (error_flag_over & sampled_bit)) begin 1129 | enable_error_cnt2 <=#Tp 1'b1; 1130 | end 1131 | end 1132 | 1133 | 1134 | always @(posedge clk or posedge rst) begin 1135 | if(rst) begin 1136 | error_cnt2 <= 3'd0; 1137 | end else if(error_frame_ended | go_error_frame | go_overload_frame) begin 1138 | error_cnt2 <=#Tp 3'd0; 1139 | end else if(enable_error_cnt2 & tx_point) begin 1140 | error_cnt2 <=#Tp error_cnt2 + 1'b1; 1141 | end 1142 | end 1143 | 1144 | 1145 | always @(posedge clk or posedge rst) begin 1146 | if(rst) begin 1147 | delayed_dominant_cnt <= 3'h0; 1148 | end else if(enable_error_cnt2 | go_error_frame | enable_overload_cnt2 | go_overload_frame) begin 1149 | delayed_dominant_cnt <=#Tp 3'h0; 1150 | end else if(sample_point & (~sampled_bit) & ((error_cnt1 == 3'd7) | (overload_cnt1 == 3'd7))) begin 1151 | delayed_dominant_cnt <=#Tp delayed_dominant_cnt + 1'b1; 1152 | end 1153 | end 1154 | 1155 | 1156 | // passive_cnt 1157 | always @(posedge clk or posedge rst) begin 1158 | if(rst) begin 1159 | passive_cnt <= 3'h1; 1160 | end else if(error_frame_ended | go_error_frame | go_overload_frame | first_compare_bit) begin 1161 | passive_cnt <=#Tp 3'h1; 1162 | end else if(sample_point & (passive_cnt < 3'h6)) begin 1163 | if(error_frame & (~enable_error_cnt2) & (sampled_bit == sampled_bit_q)) begin 1164 | passive_cnt <=#Tp passive_cnt + 1'b1; 1165 | end else begin 1166 | passive_cnt <=#Tp 3'h1; 1167 | end 1168 | end 1169 | end 1170 | 1171 | 1172 | // When comparing 6 equal bits, first is always equal 1173 | always @(posedge clk or posedge rst) begin 1174 | if(rst) begin 1175 | first_compare_bit <= 1'b0; 1176 | end else if(go_error_frame) begin 1177 | first_compare_bit <=#Tp 1'b1; 1178 | end else if(sample_point) begin 1179 | first_compare_bit <= 1'b0; 1180 | end 1181 | end 1182 | 1183 | 1184 | // Transmitting overload frame. 1185 | always @(posedge clk or posedge rst) begin 1186 | if(rst) begin 1187 | overload_frame <= 1'b0; 1188 | end else if(overload_frame_ended | go_error_frame) begin 1189 | overload_frame <=#Tp 1'b0; 1190 | end else if(go_overload_frame) begin 1191 | overload_frame <=#Tp 1'b1; 1192 | end 1193 | end 1194 | 1195 | 1196 | always @(posedge clk or posedge rst) begin 1197 | if(rst) begin 1198 | overload_cnt1 <= 3'd0; 1199 | end else if(overload_frame_ended | go_error_frame | go_overload_frame) begin 1200 | overload_cnt1 <=#Tp 3'd0; 1201 | end else if(overload_frame & tx_point & (overload_cnt1 < 3'd7)) begin 1202 | overload_cnt1 <=#Tp overload_cnt1 + 1'b1; 1203 | end 1204 | end 1205 | 1206 | 1207 | assign overload_flag_over = sample_point & (overload_cnt1 == 3'd7) & (~enable_overload_cnt2); 1208 | 1209 | 1210 | always @(posedge clk or posedge rst) begin 1211 | if(rst) begin 1212 | enable_overload_cnt2 <= 1'b0; 1213 | end else if(overload_frame_ended | go_error_frame | go_overload_frame) begin 1214 | enable_overload_cnt2 <=#Tp 1'b0; 1215 | end else if(overload_frame & (overload_flag_over & sampled_bit)) begin 1216 | enable_overload_cnt2 <=#Tp 1'b1; 1217 | end 1218 | end 1219 | 1220 | 1221 | always @(posedge clk or posedge rst) begin 1222 | if(rst) begin 1223 | overload_cnt2 <= 3'd0; 1224 | end else if(overload_frame_ended | go_error_frame | go_overload_frame) begin 1225 | overload_cnt2 <=#Tp 3'd0; 1226 | end else if(enable_overload_cnt2 & tx_point) begin 1227 | overload_cnt2 <=#Tp overload_cnt2 + 1'b1; 1228 | end 1229 | end 1230 | 1231 | 1232 | always @(posedge clk or posedge rst) begin 1233 | if(rst) begin 1234 | overload_request_cnt <= 2'b0; 1235 | end else if(go_error_frame | go_rx_id1) begin 1236 | overload_request_cnt <=#Tp 2'b0; 1237 | end else if(overload_request & overload_frame) begin 1238 | overload_request_cnt <=#Tp overload_request_cnt + 1'b1; 1239 | end 1240 | end 1241 | 1242 | 1243 | always @(posedge clk or posedge rst) begin 1244 | if(rst) begin 1245 | overload_frame_blocked <= 1'b0; 1246 | end else if(go_error_frame | go_rx_id1) begin 1247 | overload_frame_blocked <=#Tp 1'b0; 1248 | end else if(overload_request & overload_frame & overload_request_cnt == 2'h2) begin // This is a second sequential overload_request 1249 | overload_frame_blocked <=#Tp 1'b1; 1250 | end 1251 | end 1252 | 1253 | 1254 | assign send_ack = (~tx_state) & rx_ack & (~err) & (~listen_only_mode); 1255 | 1256 | 1257 | 1258 | always @(reset_mode or node_bus_off or tx_state or go_tx or bit_de_stuff_tx or tx_bit or tx_q or 1259 | send_ack or go_overload_frame or overload_frame or overload_cnt1 or 1260 | go_error_frame or error_frame or error_cnt1 or node_error_passive) begin 1261 | 1262 | if(reset_mode | node_bus_off) begin 1263 | // Reset or node_bus_off 1264 | tx_next = 1'b1; 1265 | end else begin 1266 | if(go_error_frame | error_frame) begin 1267 | // Transmitting error frame 1268 | if(error_cnt1 < 3'd6) begin 1269 | if(node_error_passive) begin 1270 | tx_next = 1'b1; 1271 | end else begin 1272 | tx_next = 1'b0; 1273 | end 1274 | end else begin 1275 | tx_next = 1'b1; 1276 | end 1277 | end else if(go_overload_frame | overload_frame) begin 1278 | // Transmitting overload frame 1279 | if(overload_cnt1 < 3'd6) begin 1280 | tx_next = 1'b0; 1281 | end else begin 1282 | tx_next = 1'b1; 1283 | end 1284 | end else if(go_tx | tx_state) begin 1285 | // Transmitting message 1286 | tx_next = ((~bit_de_stuff_tx) & tx_bit) | (bit_de_stuff_tx & (~tx_q)); 1287 | end else if(send_ack) begin 1288 | // Acknowledge 1289 | tx_next = 1'b0; 1290 | end else begin 1291 | tx_next = 1'b1; 1292 | end 1293 | end 1294 | end 1295 | 1296 | 1297 | always @(posedge clk or posedge rst) begin 1298 | if(rst) begin 1299 | tx <= 1'b1; 1300 | end else if(reset_mode) begin 1301 | tx <= 1'b1; 1302 | end else if(tx_point) begin 1303 | tx <=#Tp tx_next; 1304 | end 1305 | end 1306 | 1307 | 1308 | always @(posedge clk or posedge rst) begin 1309 | if(rst) begin 1310 | tx_q <=#Tp 1'b0; 1311 | end else if(reset_mode) begin 1312 | tx_q <=#Tp 1'b0; 1313 | end else if(tx_point) begin 1314 | tx_q <=#Tp tx & (~go_early_tx_latched); 1315 | end 1316 | end 1317 | 1318 | 1319 | /* Delayed tx point */ 1320 | always @(posedge clk or posedge rst) begin 1321 | if(rst) begin 1322 | tx_point_q <=#Tp 1'b0; 1323 | end else if(reset_mode) begin 1324 | tx_point_q <=#Tp 1'b0; 1325 | end else begin 1326 | tx_point_q <=#Tp tx_point; 1327 | end 1328 | end 1329 | 1330 | 1331 | /* Changing bit order from [7:0] to [0:7] */ 1332 | can_ibo i_ibo_tx_data_0 (.di(tx_data_0), .do(r_tx_data_0)); 1333 | can_ibo i_ibo_tx_data_1 (.di(tx_data_1), .do(r_tx_data_1)); 1334 | can_ibo i_ibo_tx_data_2 (.di(tx_data_2), .do(r_tx_data_2)); 1335 | can_ibo i_ibo_tx_data_3 (.di(tx_data_3), .do(r_tx_data_3)); 1336 | can_ibo i_ibo_tx_data_4 (.di(tx_data_4), .do(r_tx_data_4)); 1337 | can_ibo i_ibo_tx_data_5 (.di(tx_data_5), .do(r_tx_data_5)); 1338 | can_ibo i_ibo_tx_data_6 (.di(tx_data_6), .do(r_tx_data_6)); 1339 | can_ibo i_ibo_tx_data_7 (.di(tx_data_7), .do(r_tx_data_7)); 1340 | can_ibo i_ibo_tx_data_8 (.di(tx_data_8), .do(r_tx_data_8)); 1341 | can_ibo i_ibo_tx_data_9 (.di(tx_data_9), .do(r_tx_data_9)); 1342 | can_ibo i_ibo_tx_data_10 (.di(tx_data_10), .do(r_tx_data_10)); 1343 | can_ibo i_ibo_tx_data_11 (.di(tx_data_11), .do(r_tx_data_11)); 1344 | can_ibo i_ibo_tx_data_12 (.di(tx_data_12), .do(r_tx_data_12)); 1345 | 1346 | /* Changing bit order from [14:0] to [0:14] */ 1347 | can_ibo i_calculated_crc0 (.di(calculated_crc[14:7]), .do(r_calculated_crc[7:0])); 1348 | can_ibo i_calculated_crc1 (.di({calculated_crc[6:0], 1'b0}), .do(r_calculated_crc[15:8])); 1349 | 1350 | 1351 | assign basic_chain = {r_tx_data_1[7:4], 2'h0, r_tx_data_1[3:0], r_tx_data_0[7:0], 1'b0}; 1352 | assign basic_chain_data = {r_tx_data_9, r_tx_data_8, r_tx_data_7, r_tx_data_6, r_tx_data_5, r_tx_data_4, r_tx_data_3, r_tx_data_2}; 1353 | assign extended_chain_std = {r_tx_data_0[7:4], 2'h0, r_tx_data_0[1], r_tx_data_2[2:0], r_tx_data_1[7:0], 1'b0}; 1354 | assign extended_chain_ext = {r_tx_data_0[7:4], 2'h0, r_tx_data_0[1], r_tx_data_4[4:0], r_tx_data_3[7:0], r_tx_data_2[7:3], 1'b1, 1'b1, r_tx_data_2[2:0], r_tx_data_1[7:0], 1'b0}; 1355 | assign extended_chain_data_std = {r_tx_data_10, r_tx_data_9, r_tx_data_8, r_tx_data_7, r_tx_data_6, r_tx_data_5, r_tx_data_4, r_tx_data_3}; 1356 | assign extended_chain_data_ext = {r_tx_data_12, r_tx_data_11, r_tx_data_10, r_tx_data_9, r_tx_data_8, r_tx_data_7, r_tx_data_6, r_tx_data_5}; 1357 | 1358 | always @(extended_mode or rx_data or tx_pointer or extended_chain_data_std or extended_chain_data_ext or rx_crc or r_calculated_crc or 1359 | r_tx_data_0 or extended_chain_ext or extended_chain_std or basic_chain_data or basic_chain or 1360 | finish_msg) begin 1361 | 1362 | if(extended_mode) begin 1363 | if(rx_data) begin 1364 | // data stage 1365 | if(r_tx_data_0[0]) begin 1366 | // Extended frame 1367 | tx_bit = extended_chain_data_ext[tx_pointer]; 1368 | end else begin 1369 | tx_bit = extended_chain_data_std[tx_pointer]; 1370 | end 1371 | end else if(rx_crc) begin 1372 | tx_bit = r_calculated_crc[tx_pointer]; 1373 | end else if(finish_msg) begin 1374 | tx_bit = 1'b1; 1375 | end else begin 1376 | if(r_tx_data_0[0]) begin 1377 | // Extended frame 1378 | tx_bit = extended_chain_ext[tx_pointer]; 1379 | end else begin 1380 | tx_bit = extended_chain_std[tx_pointer]; 1381 | end 1382 | end 1383 | end else begin 1384 | // Basic mode 1385 | if(rx_data) begin // data stage 1386 | tx_bit = basic_chain_data[tx_pointer]; 1387 | end else if(rx_crc) begin 1388 | tx_bit = r_calculated_crc[tx_pointer]; 1389 | end else if(finish_msg) begin 1390 | tx_bit = 1'b1; 1391 | end else begin 1392 | tx_bit = basic_chain[tx_pointer]; 1393 | end 1394 | end 1395 | end 1396 | 1397 | 1398 | assign limited_tx_cnt_ext = tx_data_0[3] ? 6'h3f : ((tx_data_0[2:0] <<3) - 1'b1); 1399 | assign limited_tx_cnt_std = tx_data_1[3] ? 6'h3f : ((tx_data_1[2:0] <<3) - 1'b1); 1400 | 1401 | assign rst_tx_pointer = ((~bit_de_stuff_tx) & tx_point & (~rx_data) & extended_mode & r_tx_data_0[0] & tx_pointer == 6'd38 ) | // arbitration + control for extended format 1402 | ((~bit_de_stuff_tx) & tx_point & (~rx_data) & extended_mode & (~r_tx_data_0[0]) & tx_pointer == 6'd18 ) | // arbitration + control for extended format 1403 | ((~bit_de_stuff_tx) & tx_point & (~rx_data) & (~extended_mode) & tx_pointer == 6'd18 ) | // arbitration + control for standard format 1404 | ((~bit_de_stuff_tx) & tx_point & rx_data & extended_mode & tx_pointer == limited_tx_cnt_ext) | // data (overflow is OK here) 1405 | ((~bit_de_stuff_tx) & tx_point & rx_data & (~extended_mode) & tx_pointer == limited_tx_cnt_std) | // data (overflow is OK here) 1406 | ( tx_point & rx_crc_lim ) | // crc 1407 | (go_rx_idle ) | // at the end 1408 | (reset_mode ) | 1409 | (overload_frame ) | 1410 | (error_frame ) ; 1411 | 1412 | always @(posedge clk or posedge rst) begin 1413 | if(rst) begin 1414 | tx_pointer <= 6'h0; 1415 | end else if(rst_tx_pointer) begin 1416 | tx_pointer <=#Tp 6'h0; 1417 | end else if(go_early_tx | (tx_point & (tx_state | go_tx) & (~bit_de_stuff_tx))) begin 1418 | tx_pointer <=#Tp tx_pointer + 1'b1; 1419 | end 1420 | end 1421 | 1422 | 1423 | assign tx_successful = transmitter & go_rx_inter & (~go_error_frame) & (~error_frame_ended) & (~overload_frame_ended) & (~arbitration_lost); 1424 | 1425 | 1426 | always @(posedge clk or posedge rst) begin 1427 | if(rst) begin 1428 | need_to_tx <= 1'b0; 1429 | end else if(tx_successful | reset_mode | (abort_tx & (~transmitting)) | ((~tx_state) & tx_state_q & single_shot_transmission)) begin 1430 | need_to_tx <=#Tp 1'h0; 1431 | end else if(tx_request & sample_point) begin 1432 | need_to_tx <=#Tp 1'b1; 1433 | end 1434 | end 1435 | 1436 | 1437 | 1438 | assign go_early_tx = (~listen_only_mode) & need_to_tx & (~tx_state) & (~suspend | (susp_cnt == 3'h7)) & sample_point & (~sampled_bit) & (rx_idle | last_bit_of_inter); 1439 | assign go_tx = (~listen_only_mode) & need_to_tx & (~tx_state) & (~suspend | (sample_point & (susp_cnt == 3'h7))) & (go_early_tx | rx_idle); 1440 | 1441 | // go_early_tx latched (for proper bit_de_stuff generation) 1442 | always @(posedge clk or posedge rst) begin 1443 | if(rst) begin 1444 | go_early_tx_latched <= 1'b0; 1445 | end else if(reset_mode || tx_point) begin 1446 | go_early_tx_latched <=#Tp 1'b0; 1447 | end else if(go_early_tx) begin 1448 | go_early_tx_latched <=#Tp 1'b1; 1449 | end 1450 | end 1451 | 1452 | 1453 | 1454 | // Tx state 1455 | always @(posedge clk or posedge rst) begin 1456 | if(rst) begin 1457 | tx_state <= 1'b0; 1458 | end else if(reset_mode | go_rx_inter | error_frame | arbitration_lost) begin 1459 | tx_state <=#Tp 1'b0; 1460 | end else if(go_tx) begin 1461 | tx_state <=#Tp 1'b1; 1462 | end 1463 | end 1464 | 1465 | always @(posedge clk or posedge rst) begin 1466 | if(rst) begin 1467 | tx_state_q <=#Tp 1'b0; 1468 | end else if(reset_mode) begin 1469 | tx_state_q <=#Tp 1'b0; 1470 | end else begin 1471 | tx_state_q <=#Tp tx_state; 1472 | end 1473 | end 1474 | 1475 | 1476 | 1477 | // Node is a transmitter 1478 | always @(posedge clk or posedge rst) begin 1479 | if(rst) begin 1480 | transmitter <= 1'b0; 1481 | end else if(go_tx) begin 1482 | transmitter <=#Tp 1'b1; 1483 | end else if(reset_mode | go_rx_idle | suspend & go_rx_id1) begin 1484 | transmitter <=#Tp 1'b0; 1485 | end 1486 | end 1487 | 1488 | 1489 | 1490 | // Signal "transmitting" signals that the core is a transmitting (message, error frame or overload frame). No synchronization is done meanwhile. 1491 | // Node might be both transmitter or receiver (sending error or overload frame) 1492 | always @(posedge clk or posedge rst) begin 1493 | if(rst) begin 1494 | transmitting <= 1'b0; 1495 | end else if(go_error_frame | go_overload_frame | go_tx | send_ack) begin 1496 | transmitting <=#Tp 1'b1; 1497 | end else if(reset_mode | go_rx_idle | (go_rx_id1 & (~tx_state)) | (arbitration_lost & tx_state)) begin 1498 | transmitting <=#Tp 1'b0; 1499 | end 1500 | end 1501 | 1502 | 1503 | always @(posedge clk or posedge rst) begin 1504 | if(rst) begin 1505 | suspend <= 1'b0; 1506 | end else if(reset_mode | (sample_point & (susp_cnt == 3'h7))) begin 1507 | suspend <=#Tp 1'b0; 1508 | end else if(not_first_bit_of_inter & transmitter & node_error_passive) begin 1509 | suspend <=#Tp 1'b1; 1510 | end 1511 | end 1512 | 1513 | 1514 | always @(posedge clk or posedge rst) begin 1515 | if(rst) begin 1516 | susp_cnt_en <= 1'b0; 1517 | end else if(reset_mode | (sample_point & (susp_cnt == 3'h7))) begin 1518 | susp_cnt_en <=#Tp 1'b0; 1519 | end else if(suspend & sample_point & last_bit_of_inter) begin 1520 | susp_cnt_en <=#Tp 1'b1; 1521 | end 1522 | end 1523 | 1524 | 1525 | always @(posedge clk or posedge rst) begin 1526 | if(rst) begin 1527 | susp_cnt <= 3'h0; 1528 | end else if(reset_mode | (sample_point & (susp_cnt == 3'h7))) begin 1529 | susp_cnt <=#Tp 3'h0; 1530 | end else if(susp_cnt_en & sample_point) begin 1531 | susp_cnt <=#Tp susp_cnt + 1'b1; 1532 | end 1533 | end 1534 | 1535 | 1536 | always @(posedge clk or posedge rst) begin 1537 | if(rst) begin 1538 | finish_msg <= 1'b0; 1539 | end else if(go_rx_idle | go_rx_id1 | error_frame | reset_mode) begin 1540 | finish_msg <=#Tp 1'b0; 1541 | end else if(go_rx_crc_lim) begin 1542 | finish_msg <=#Tp 1'b1; 1543 | end 1544 | end 1545 | 1546 | 1547 | always @(posedge clk or posedge rst) begin 1548 | if(rst) begin 1549 | arbitration_lost <= 1'b0; 1550 | end else if(go_rx_idle | error_frame_ended) begin 1551 | arbitration_lost <=#Tp 1'b0; 1552 | end else if(transmitter & sample_point & tx & arbitration_field & ~sampled_bit) begin 1553 | arbitration_lost <=#Tp 1'b1; 1554 | end 1555 | end 1556 | 1557 | 1558 | always @(posedge clk or posedge rst) begin 1559 | if(rst) begin 1560 | arbitration_lost_q <=#Tp 1'b0; 1561 | end else begin 1562 | arbitration_lost_q <=#Tp arbitration_lost; 1563 | end 1564 | end 1565 | 1566 | 1567 | always @(posedge clk or posedge rst) begin 1568 | if(rst) begin 1569 | arbitration_field_d <=#Tp 1'b0; 1570 | end else if(sample_point) begin 1571 | arbitration_field_d <=#Tp arbitration_field; 1572 | end 1573 | end 1574 | 1575 | 1576 | assign set_arbitration_lost_irq = arbitration_lost & (~arbitration_lost_q) & (~arbitration_blocked); 1577 | 1578 | 1579 | always @(posedge clk or posedge rst) begin 1580 | if(rst) begin 1581 | arbitration_cnt <= 5'h0; 1582 | end else if(sample_point && !bit_de_stuff) begin 1583 | if(arbitration_field_d) begin 1584 | arbitration_cnt <=#Tp arbitration_cnt + 1'b1; 1585 | end else begin 1586 | arbitration_cnt <=#Tp 5'h0; 1587 | end 1588 | end 1589 | end 1590 | 1591 | 1592 | always @(posedge clk or posedge rst) begin 1593 | if(rst) begin 1594 | arbitration_lost_capture <= 5'h0; 1595 | end else if(set_arbitration_lost_irq) begin 1596 | arbitration_lost_capture <=#Tp arbitration_cnt; 1597 | end 1598 | end 1599 | 1600 | 1601 | always @(posedge clk or posedge rst) begin 1602 | if(rst) begin 1603 | arbitration_blocked <= 1'b0; 1604 | end else if(read_arbitration_lost_capture_reg) begin 1605 | arbitration_blocked <=#Tp 1'b0; 1606 | end else if(set_arbitration_lost_irq) begin 1607 | arbitration_blocked <=#Tp 1'b1; 1608 | end 1609 | end 1610 | 1611 | 1612 | always @(posedge clk or posedge rst) begin 1613 | if(rst) begin 1614 | rx_err_cnt <= 9'h0; 1615 | end else if(we_rx_err_cnt & (~node_bus_off)) begin 1616 | rx_err_cnt <=#Tp {1'b0, data_in}; 1617 | end else if(set_reset_mode) begin 1618 | rx_err_cnt <=#Tp 9'h0; 1619 | end else begin 1620 | if((~listen_only_mode) & (~transmitter | arbitration_lost)) begin 1621 | if(go_rx_ack_lim & (~go_error_frame) & (~crc_err) & (rx_err_cnt > 9'h0)) begin 1622 | if(rx_err_cnt > 9'd127) begin 1623 | rx_err_cnt <=#Tp 9'd127; 1624 | end else begin 1625 | rx_err_cnt <=#Tp rx_err_cnt - 1'b1; 1626 | end 1627 | end else if(rx_err_cnt < 9'd128) begin 1628 | if(go_error_frame & (~rule5)) begin // 1 (rule 5 is just the opposite then rule 1 exception 1629 | rx_err_cnt <=#Tp rx_err_cnt + 1'b1; 1630 | end else if( (error_flag_over & (~error_flag_over_latched) & sample_point & (~sampled_bit) & (error_cnt1 == 3'd7) ) | // 2 1631 | (go_error_frame & rule5 ) | // 5 1632 | (sample_point & (~sampled_bit) & (delayed_dominant_cnt == 3'h7)) ) begin // 6 1633 | 1634 | rx_err_cnt <=#Tp rx_err_cnt + 4'h8; 1635 | end 1636 | end 1637 | end 1638 | end 1639 | end 1640 | 1641 | 1642 | always @(posedge clk or posedge rst) begin 1643 | if(rst) begin 1644 | tx_err_cnt <= 9'h0; 1645 | end else if(we_tx_err_cnt) begin 1646 | tx_err_cnt <=#Tp {1'b0, data_in}; 1647 | end else begin 1648 | if(set_reset_mode) begin 1649 | tx_err_cnt <=#Tp 9'd128; 1650 | end else if((tx_err_cnt > 9'd0) & (tx_successful | bus_free)) begin 1651 | tx_err_cnt <=#Tp tx_err_cnt - 1'h1; 1652 | end else if(transmitter & (~arbitration_lost)) begin 1653 | if( (sample_point & (~sampled_bit) & (delayed_dominant_cnt == 3'h7) ) | // 6 1654 | (go_error_frame & rule5 ) | // 4 (rule 5 is the same as rule 4) 1655 | (go_error_frame & (~(transmitter & node_error_passive & ack_err)) & (~(transmitter & stuff_err & 1656 | arbitration_field & sample_point & tx & (~sampled_bit))) ) | // 3 1657 | (error_frame & rule3_exc1_2) ) begin // 3 1658 | 1659 | tx_err_cnt <=#Tp tx_err_cnt + 4'h8; 1660 | end 1661 | end 1662 | end 1663 | end 1664 | 1665 | 1666 | always @(posedge clk or posedge rst) begin 1667 | if(rst) begin 1668 | node_error_passive <= 1'b0; 1669 | end else if((rx_err_cnt < 128) & (tx_err_cnt < 9'd128)) begin 1670 | node_error_passive <=#Tp 1'b0; 1671 | end else if(((rx_err_cnt >= 128) | (tx_err_cnt >= 9'd128)) & (error_frame_ended | go_error_frame | (~reset_mode) & reset_mode_q) & (~node_bus_off)) begin 1672 | node_error_passive <=#Tp 1'b1; 1673 | end 1674 | end 1675 | 1676 | 1677 | assign node_error_active = ~(node_error_passive | node_bus_off); 1678 | 1679 | 1680 | always @(posedge clk or posedge rst) begin 1681 | if(rst) begin 1682 | node_bus_off <= 1'b0; 1683 | end else if((rx_err_cnt == 9'h0) & (tx_err_cnt == 9'd0) & (~reset_mode) | (we_tx_err_cnt & (data_in < 8'd255))) begin 1684 | node_bus_off <=#Tp 1'b0; 1685 | end else if((tx_err_cnt >= 9'd256) | (we_tx_err_cnt & (data_in == 8'd255))) begin 1686 | node_bus_off <=#Tp 1'b1; 1687 | end 1688 | end 1689 | 1690 | 1691 | 1692 | always @(posedge clk or posedge rst) begin 1693 | if(rst) begin 1694 | bus_free_cnt <= 4'h0; 1695 | end else if(sample_point) begin 1696 | if(sampled_bit & bus_free_cnt_en & (bus_free_cnt < 4'd10)) begin 1697 | bus_free_cnt <=#Tp bus_free_cnt + 1'b1; 1698 | end else begin 1699 | bus_free_cnt <=#Tp 4'h0; 1700 | end 1701 | end 1702 | end 1703 | 1704 | 1705 | always @(posedge clk or posedge rst) begin 1706 | if(rst) begin 1707 | bus_free_cnt_en <= 1'b0; 1708 | end else if((~reset_mode) & reset_mode_q | node_bus_off_q & (~reset_mode)) begin 1709 | bus_free_cnt_en <=#Tp 1'b1; 1710 | end else if(sample_point & sampled_bit & (bus_free_cnt==4'd10) & (~node_bus_off)) begin 1711 | bus_free_cnt_en <=#Tp 1'b0; 1712 | end 1713 | end 1714 | 1715 | 1716 | always @(posedge clk or posedge rst) begin 1717 | if(rst) begin 1718 | bus_free <= 1'b0; 1719 | end else if(sample_point & sampled_bit & (bus_free_cnt==4'd10) && waiting_for_bus_free) begin 1720 | bus_free <=#Tp 1'b1; 1721 | end else begin 1722 | bus_free <=#Tp 1'b0; 1723 | end 1724 | end 1725 | 1726 | 1727 | always @(posedge clk or posedge rst) begin 1728 | if(rst) begin 1729 | waiting_for_bus_free <= 1'b1; 1730 | end else if(bus_free & (~node_bus_off)) begin 1731 | waiting_for_bus_free <=#Tp 1'b0; 1732 | end else if(node_bus_off_q & (~reset_mode)) begin 1733 | waiting_for_bus_free <=#Tp 1'b1; 1734 | end 1735 | end 1736 | 1737 | 1738 | assign bus_off_on = ~node_bus_off; 1739 | 1740 | assign set_reset_mode = node_bus_off & (~node_bus_off_q); 1741 | assign error_status = extended_mode? ((rx_err_cnt >= error_warning_limit) | (tx_err_cnt >= error_warning_limit)) : 1742 | ((rx_err_cnt >= 9'd96) | (tx_err_cnt >= 9'd96)) ; 1743 | 1744 | assign transmit_status = transmitting || (extended_mode && waiting_for_bus_free); 1745 | assign receive_status = extended_mode ? (waiting_for_bus_free || (!rx_idle) && (!transmitting)) : 1746 | ((!waiting_for_bus_free) && (!rx_idle) && (!transmitting)); 1747 | 1748 | /* Error code capture register */ 1749 | always @(posedge clk or posedge rst) begin 1750 | if(rst) begin 1751 | error_capture_code <= 8'h0; 1752 | end else if(read_error_code_capture_reg) begin 1753 | error_capture_code <=#Tp 8'h0; 1754 | end else if(set_bus_error_irq) begin 1755 | error_capture_code <=#Tp {error_capture_code_type[7:6], error_capture_code_direction, error_capture_code_segment[4:0]}; 1756 | end 1757 | end 1758 | 1759 | 1760 | 1761 | assign error_capture_code_segment[0] = rx_idle | rx_ide | (rx_id2 & (bit_cnt<6'd13)) | rx_r1 | rx_r0 | rx_dlc | rx_ack | rx_ack_lim | error_frame & node_error_active; 1762 | assign error_capture_code_segment[1] = rx_idle | rx_id1 | rx_id2 | rx_dlc | rx_data | rx_ack_lim | rx_eof | rx_inter | error_frame & node_error_passive; 1763 | assign error_capture_code_segment[2] = (rx_id1 & (bit_cnt>6'd7)) | rx_rtr1 | rx_ide | rx_id2 | rx_rtr2 | rx_r1 | error_frame & node_error_passive | overload_frame; 1764 | assign error_capture_code_segment[3] = (rx_id2 & (bit_cnt>6'd4)) | rx_rtr2 | rx_r1 | rx_r0 | rx_dlc | rx_data | rx_crc | rx_crc_lim | rx_ack | rx_ack_lim | rx_eof | overload_frame; 1765 | assign error_capture_code_segment[4] = rx_crc_lim | rx_ack | rx_ack_lim | rx_eof | rx_inter | error_frame | overload_frame; 1766 | assign error_capture_code_direction = ~transmitting; 1767 | 1768 | 1769 | always @(bit_err or form_err or stuff_err) begin 1770 | if(bit_err) begin 1771 | error_capture_code_type[7:6] = 2'b00; 1772 | end else if(form_err) begin 1773 | error_capture_code_type[7:6] = 2'b01; 1774 | end else if(stuff_err) begin 1775 | error_capture_code_type[7:6] = 2'b10; 1776 | end else begin 1777 | error_capture_code_type[7:6] = 2'b11; 1778 | end 1779 | end 1780 | 1781 | 1782 | assign set_bus_error_irq = go_error_frame & (~error_capture_code_blocked); 1783 | 1784 | 1785 | always @(posedge clk or posedge rst) begin 1786 | if(rst) begin 1787 | error_capture_code_blocked <= 1'b0; 1788 | end else if(read_error_code_capture_reg) begin 1789 | error_capture_code_blocked <=#Tp 1'b0; 1790 | end else if(set_bus_error_irq) begin 1791 | error_capture_code_blocked <=#Tp 1'b1; 1792 | end 1793 | end 1794 | 1795 | 1796 | endmodule 1797 | 1798 | -------------------------------------------------------------------------------- /can_btl.v: -------------------------------------------------------------------------------- 1 | /* vim: colorcolumn=80 2 | * 3 | * This file is part of a verilog CAN controller that is SJA1000 compatible. 4 | * 5 | * Authors: 6 | * * Igor Mohor 7 | * Author of the original version at 8 | * http://www.opencores.org/projects/can/ 9 | * (which has been unmaintained since about 2009) 10 | * 11 | * * David Piegdon 12 | * Picked up project for cleanup and bugfixes in 2019 13 | * 14 | * Any additional information is available in the LICENSE file. 15 | * 16 | * Copyright (C) 2002, 2003, 2004, 2019 Authors 17 | * 18 | * This source file may be used and distributed without restriction provided 19 | * that this copyright statement is not removed from the file and that any 20 | * derivative work contains the original copyright notice and the associated 21 | * disclaimer. 22 | * 23 | * This source file is free software; you can redistribute it and/or modify it 24 | * under the terms of the GNU Lesser General Public License as published by the 25 | * Free Software Foundation; either version 2.1 of the License, or (at your 26 | * option) any later version. 27 | * 28 | * This source is distributed in the hope that it will be useful, but WITHOUT 29 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 30 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 31 | * details. 32 | * 33 | * You should have received a copy of the GNU Lesser General Public License 34 | * along with this source; if not, download it from 35 | * http://www.opencores.org/lgpl.shtml 36 | * 37 | * The CAN protocol is developed by Robert Bosch GmbH and protected by patents. 38 | * Anybody who wants to implement this CAN IP core on silicon has to obtain 39 | * a CAN protocol license from Bosch. 40 | */ 41 | 42 | `default_nettype none 43 | 44 | `include "can_top_defines.v" 45 | 46 | module can_btl( 47 | input wire clk, 48 | input wire rst, 49 | input wire rx, 50 | input wire tx, 51 | 52 | /* Bus Timing 0 register */ 53 | input wire [5:0] baud_r_presc, 54 | input wire [1:0] sync_jump_width, 55 | 56 | /* Bus Timing 1 register */ 57 | input wire [3:0] time_segment1, 58 | input wire [2:0] time_segment2, 59 | input wire triple_sampling, 60 | 61 | /* Output signals from this module */ 62 | output reg sample_point, 63 | output reg sampled_bit, 64 | output reg sampled_bit_q, 65 | output reg tx_point, 66 | output wire hard_sync, 67 | 68 | /* From can_bsp module */ 69 | input wire rx_idle, 70 | input wire rx_inter, 71 | input wire transmitting, 72 | input wire transmitter, 73 | input wire go_rx_inter, 74 | input wire tx_next, 75 | 76 | input wire go_overload_frame, 77 | input wire go_error_frame, 78 | input wire go_tx, 79 | input wire send_ack, 80 | input wire node_error_passive); 81 | 82 | parameter Tp = 1; 83 | 84 | reg [6:0] clk_cnt; 85 | reg clk_en; 86 | reg clk_en_q; 87 | reg sync_blocked; 88 | reg hard_sync_blocked; 89 | reg [4:0] quant_cnt; 90 | reg [3:0] delay; 91 | reg sync; 92 | reg seg1; 93 | reg seg2; 94 | reg resync_latched; 95 | reg [1:0] sample; 96 | reg tx_next_sp; 97 | 98 | wire go_sync; 99 | wire go_seg1; 100 | wire go_seg2; 101 | wire [7:0] preset_cnt; 102 | wire sync_window; 103 | wire resync; 104 | 105 | assign preset_cnt = (baud_r_presc + 1'b1)<<1; // (BRP+1)*2 106 | assign hard_sync = (rx_idle | rx_inter) & (~rx) & sampled_bit & (~hard_sync_blocked); // Hard synchronization 107 | assign resync = (~rx_idle) & (~rx_inter) & (~rx) & sampled_bit & (~sync_blocked); // Re-synchronization 108 | 109 | // Generating general enable signal that defines baud rate 110 | always @(posedge clk or posedge rst) begin 111 | if(rst) begin 112 | clk_cnt <= 7'h0; 113 | end else if(clk_cnt >= (preset_cnt-1'b1)) begin 114 | clk_cnt <=#Tp 7'h0; 115 | end else begin 116 | clk_cnt <=#Tp clk_cnt + 1'b1; 117 | end 118 | end 119 | 120 | always @(posedge clk or posedge rst) begin 121 | if(rst) begin 122 | clk_en <= 1'b0; 123 | end else if({1'b0, clk_cnt} == (preset_cnt-1'b1)) begin 124 | clk_en <=#Tp 1'b1; 125 | end else begin 126 | clk_en <=#Tp 1'b0; 127 | end 128 | end 129 | 130 | always @(posedge clk or posedge rst) begin 131 | if(rst) begin 132 | clk_en_q <= 1'b0; 133 | end else begin 134 | clk_en_q <=#Tp clk_en; 135 | end 136 | end 137 | 138 | // Changing states 139 | assign go_sync = clk_en_q & seg2 & (quant_cnt[2:0] == time_segment2) & (~hard_sync) & (~resync); 140 | assign go_seg1 = clk_en_q & (sync | hard_sync | (resync & seg2 & sync_window) | (resync_latched & sync_window)); 141 | assign go_seg2 = clk_en_q & (seg1 & (~hard_sync) & (quant_cnt == (time_segment1 + delay))); 142 | 143 | always @(posedge clk or posedge rst) begin 144 | if(rst) begin 145 | tx_point <= 1'b0; 146 | end else begin 147 | // When transmitter we should transmit as soon as possible. 148 | tx_point <=#Tp ~tx_point & seg2 & ( 149 | clk_en & (quant_cnt[2:0] == time_segment2) 150 | | (clk_en | clk_en_q) & (resync | hard_sync) 151 | ); 152 | end 153 | end 154 | 155 | /* When early edge is detected outside of the SJW field, synchronization request is latched and performed when 156 | SJW is reached */ 157 | always @(posedge clk or posedge rst) begin 158 | if(rst) begin 159 | resync_latched <= 1'b0; 160 | end else if(resync & seg2 & (~sync_window)) begin 161 | resync_latched <=#Tp 1'b1; 162 | end else if(go_seg1) begin 163 | resync_latched <= 1'b0; 164 | end 165 | end 166 | 167 | // Synchronization stage/segment 168 | always @(posedge clk or posedge rst) begin 169 | if(rst) begin 170 | sync <= 1'b0; 171 | end else if(clk_en_q) begin 172 | sync <=#Tp go_sync; 173 | end 174 | end 175 | 176 | // Seg1 stage/segment (together with propagation segment which is 1 quant long) 177 | always @(posedge clk or posedge rst) begin 178 | if(rst) begin 179 | seg1 <= 1'b1; 180 | end else if(go_seg1) begin 181 | seg1 <=#Tp 1'b1; 182 | end else if(go_seg2) begin 183 | seg1 <=#Tp 1'b0; 184 | end 185 | end 186 | 187 | // Seg2 stage/segment 188 | always @(posedge clk or posedge rst) begin 189 | if(rst) begin 190 | seg2 <= 1'b0; 191 | end else if(go_seg2) begin 192 | seg2 <=#Tp 1'b1; 193 | end else if(go_sync | go_seg1) begin 194 | seg2 <=#Tp 1'b0; 195 | end 196 | end 197 | 198 | // Quant counter 199 | always @(posedge clk or posedge rst) begin 200 | if(rst) begin 201 | quant_cnt <= 5'h0; 202 | end else if(go_sync | go_seg1 | go_seg2) begin 203 | quant_cnt <=#Tp 5'h0; 204 | end else if(clk_en_q) begin 205 | quant_cnt <=#Tp quant_cnt + 1'b1; 206 | end 207 | end 208 | 209 | // When late edge is detected (in seg1 stage), stage seg1 is prolonged. 210 | always @(posedge clk or posedge rst) begin 211 | if(rst) begin 212 | delay <= 4'h0; 213 | end else if(resync & seg1 & (~transmitting | transmitting & (tx_next_sp | (tx & (~rx))))) begin 214 | // when transmitting 0 with positive error delay is set to 0 215 | delay <=#Tp (quant_cnt > {3'h0, sync_jump_width})? ({2'h0, sync_jump_width} + 1'b1) : (quant_cnt + 1'b1); 216 | end else if(go_sync | go_seg1) begin 217 | delay <=#Tp 4'h0; 218 | end 219 | end 220 | 221 | // If early edge appears within this window (in seg2 stage), phase error is fully compensated 222 | assign sync_window = ((time_segment2 - quant_cnt[2:0]) < ( sync_jump_width + 1'b1)); 223 | 224 | // Sampling data (memorizing two samples all the time). 225 | always @(posedge clk or posedge rst) begin 226 | if(rst) begin 227 | sample <= 2'b11; 228 | end else if(clk_en_q) begin 229 | sample <= {sample[0], rx}; 230 | end 231 | end 232 | 233 | // When enabled, tripple sampling is done here. 234 | always @(posedge clk or posedge rst) begin 235 | if(rst) begin 236 | sampled_bit <= 1'b1; 237 | sampled_bit_q <= 1'b1; 238 | sample_point <= 1'b0; 239 | end else if(go_error_frame) begin 240 | sampled_bit_q <=#Tp sampled_bit; 241 | sample_point <=#Tp 1'b0; 242 | end else if(clk_en_q & (~hard_sync)) begin 243 | if(seg1 & (quant_cnt == (time_segment1 + delay))) begin 244 | sample_point <=#Tp 1'b1; 245 | sampled_bit_q <=#Tp sampled_bit; 246 | if(triple_sampling) begin 247 | sampled_bit <=#Tp (sample[0] & sample[1]) | ( sample[0] & rx) | (sample[1] & rx); 248 | end else begin 249 | sampled_bit <=#Tp rx; 250 | end 251 | end 252 | end else begin 253 | sample_point <=#Tp 1'b0; 254 | end 255 | end 256 | 257 | // tx_next_sp shows next value that will be driven on the TX. When driving 1 and receiving 0 we 258 | // need to synchronize (even when we are a transmitter) 259 | always @(posedge clk or posedge rst) begin 260 | if(rst) begin 261 | tx_next_sp <= 1'b0; 262 | end else if(go_overload_frame | (go_error_frame & (~node_error_passive)) | go_tx | send_ack) begin 263 | tx_next_sp <=#Tp 1'b0; 264 | end else if(go_error_frame & node_error_passive) begin 265 | tx_next_sp <=#Tp 1'b1; 266 | end else if(sample_point) begin 267 | tx_next_sp <=#Tp tx_next; 268 | end 269 | end 270 | 271 | // Blocking synchronization (can occur only once in a bit time) 272 | always @(posedge clk or posedge rst) begin 273 | if(rst) begin 274 | sync_blocked <=#Tp 1'b1; 275 | end else if(clk_en_q) begin 276 | if(resync) begin 277 | sync_blocked <=#Tp 1'b1; 278 | end else if(go_seg2) begin 279 | sync_blocked <=#Tp 1'b0; 280 | end 281 | end 282 | end 283 | 284 | // Blocking hard synchronization when occurs once or when we are transmitting a msg 285 | always @(posedge clk or posedge rst) begin 286 | if(rst) begin 287 | hard_sync_blocked <=#Tp 1'b0; 288 | end else if(hard_sync & clk_en_q | (transmitting & transmitter | go_tx) & tx_point & (~tx_next)) begin 289 | hard_sync_blocked <=#Tp 1'b1; 290 | end else if(go_rx_inter | (rx_idle | rx_inter) & sample_point & sampled_bit) begin 291 | // When a glitch performed synchronization 292 | hard_sync_blocked <=#Tp 1'b0; 293 | end 294 | end 295 | 296 | endmodule 297 | -------------------------------------------------------------------------------- /can_crc.v: -------------------------------------------------------------------------------- 1 | /* vim: colorcolumn=80 2 | * 3 | * This file is part of a verilog CAN controller that is SJA1000 compatible. 4 | * 5 | * Authors: 6 | * * Igor Mohor 7 | * Author of the original version at 8 | * http://www.opencores.org/projects/can/ 9 | * (which has been unmaintained since about 2009) 10 | * 11 | * * David Piegdon 12 | * Picked up project for cleanup and bugfixes in 2019 13 | * 14 | * Any additional information is available in the LICENSE file. 15 | * 16 | * Copyright (C) 2002, 2003, 2004, 2019 Authors 17 | * 18 | * This source file may be used and distributed without restriction provided 19 | * that this copyright statement is not removed from the file and that any 20 | * derivative work contains the original copyright notice and the associated 21 | * disclaimer. 22 | * 23 | * This source file is free software; you can redistribute it and/or modify it 24 | * under the terms of the GNU Lesser General Public License as published by the 25 | * Free Software Foundation; either version 2.1 of the License, or (at your 26 | * option) any later version. 27 | * 28 | * This source is distributed in the hope that it will be useful, but WITHOUT 29 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 30 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 31 | * details. 32 | * 33 | * You should have received a copy of the GNU Lesser General Public License 34 | * along with this source; if not, download it from 35 | * http://www.opencores.org/lgpl.shtml 36 | * 37 | * The CAN protocol is developed by Robert Bosch GmbH and protected by patents. 38 | * Anybody who wants to implement this CAN IP core on silicon has to obtain 39 | * a CAN protocol license from Bosch. 40 | */ 41 | 42 | `default_nettype none 43 | 44 | module can_crc( 45 | input wire clk, 46 | input wire data, 47 | input wire enable, 48 | input wire initialize, 49 | output reg [14:0] crc); 50 | 51 | parameter Tp = 1; 52 | 53 | wire crc_next = data ^ crc[14]; 54 | wire [14:0] crc_tmp = {crc[13:0], 1'b0}; 55 | 56 | always @(posedge clk) 57 | begin 58 | if(initialize) begin 59 | crc <=#Tp 15'h0; 60 | end else if(enable) begin 61 | if(crc_next) begin 62 | crc <=#Tp crc_tmp ^ 15'h4599; 63 | end else begin 64 | crc <=#Tp crc_tmp; 65 | end 66 | end 67 | end 68 | 69 | endmodule 70 | -------------------------------------------------------------------------------- /can_fifo.v: -------------------------------------------------------------------------------- 1 | /* vim: colorcolumn=80 2 | * 3 | * This file is part of a verilog CAN controller that is SJA1000 compatible. 4 | * 5 | * Authors: 6 | * * Igor Mohor 7 | * Author of the original version at 8 | * http://www.opencores.org/projects/can/ 9 | * (which has been unmaintained since about 2009) 10 | * 11 | * * David Piegdon 12 | * Picked up project for cleanup and bugfixes in 2019 13 | * 14 | * Any additional information is available in the LICENSE file. 15 | * 16 | * Copyright (C) 2002, 2003, 2004, 2019 Authors 17 | * 18 | * This source file may be used and distributed without restriction provided 19 | * that this copyright statement is not removed from the file and that any 20 | * derivative work contains the original copyright notice and the associated 21 | * disclaimer. 22 | * 23 | * This source file is free software; you can redistribute it and/or modify it 24 | * under the terms of the GNU Lesser General Public License as published by the 25 | * Free Software Foundation; either version 2.1 of the License, or (at your 26 | * option) any later version. 27 | * 28 | * This source is distributed in the hope that it will be useful, but WITHOUT 29 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 30 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 31 | * details. 32 | * 33 | * You should have received a copy of the GNU Lesser General Public License 34 | * along with this source; if not, download it from 35 | * http://www.opencores.org/lgpl.shtml 36 | * 37 | * The CAN protocol is developed by Robert Bosch GmbH and protected by patents. 38 | * Anybody who wants to implement this CAN IP core on silicon has to obtain 39 | * a CAN protocol license from Bosch. 40 | */ 41 | 42 | `default_nettype none 43 | 44 | `include "can_top_defines.v" 45 | 46 | module can_fifo( 47 | input wire clk, 48 | input wire rst, 49 | input wire wr, 50 | input wire [7:0] data_in, 51 | input wire [5:0] addr, 52 | output wire [7:0] data_out, 53 | input wire fifo_selected, 54 | 55 | input wire reset_mode, 56 | input wire release_buffer, 57 | input wire extended_mode, 58 | output wire overrun, 59 | output wire info_empty, 60 | output reg [6:0] info_cnt 61 | 62 | `ifdef CAN_BIST 63 | , 64 | input wire mbist_si_i, 65 | output wire mbist_so_o, 66 | input wire [`CAN_MBIST_CTRL_WIDTH - 1:0] mbist_ctrl_i // bist chain shift control 67 | `endif 68 | ); 69 | 70 | parameter Tp = 1; 71 | 72 | `ifdef CAN_BIST 73 | wire mbist_s_0; 74 | `endif 75 | 76 | `ifdef ALTERA_RAM 77 | `else 78 | `ifdef ACTEL_APA_RAM 79 | `else 80 | `ifdef XILINX_RAM 81 | `else 82 | `ifdef ARTISAN_RAM 83 | reg overrun_info[0:63]; 84 | `else 85 | `ifdef VIRTUALSILICON_RAM 86 | reg overrun_info[0:63]; 87 | `else 88 | reg [7:0] fifo [0:63]; 89 | reg [3:0] length_fifo[0:63]; 90 | reg overrun_info[0:63]; 91 | `endif 92 | `endif 93 | `endif 94 | `endif 95 | `endif 96 | 97 | reg [5:0] rd_pointer; 98 | reg [5:0] wr_pointer; 99 | reg [5:0] read_address; 100 | reg [5:0] wr_info_pointer; 101 | reg [5:0] rd_info_pointer; 102 | reg wr_q; 103 | reg [3:0] len_cnt; 104 | reg [6:0] fifo_cnt; 105 | reg latch_overrun; 106 | reg initialize_memories; 107 | 108 | wire [3:0] length_info; 109 | wire write_length_info; 110 | wire fifo_empty; 111 | wire fifo_full; 112 | wire info_full; 113 | 114 | assign write_length_info = (~wr) & wr_q; 115 | 116 | // Delayed write signal 117 | always @(posedge clk or posedge rst) begin 118 | if(rst) begin 119 | wr_q <=#Tp 1'b0; 120 | end else if(reset_mode) begin 121 | wr_q <=#Tp 1'b0; 122 | end else begin 123 | wr_q <=#Tp wr; 124 | end 125 | end 126 | 127 | // length counter 128 | always @(posedge clk or posedge rst) begin 129 | if(rst) begin 130 | len_cnt <= 4'h0; 131 | end else if(reset_mode | write_length_info) begin 132 | len_cnt <=#Tp 4'h0; 133 | end else if(wr & (~fifo_full)) begin 134 | len_cnt <=#Tp len_cnt + 1'b1; 135 | end 136 | end 137 | 138 | // wr_info_pointer 139 | always @(posedge clk or posedge rst) begin 140 | if(rst) begin 141 | wr_info_pointer <= 6'h0; 142 | end else if(write_length_info & (~info_full) | initialize_memories) begin 143 | wr_info_pointer <=#Tp wr_info_pointer + 1'b1; 144 | end else if(reset_mode) begin 145 | wr_info_pointer <=#Tp rd_info_pointer; 146 | end 147 | end 148 | 149 | // rd_info_pointer 150 | always @(posedge clk or posedge rst) begin 151 | if(rst) begin 152 | rd_info_pointer <= 6'h0; 153 | end else if(release_buffer & (~info_full)) begin 154 | rd_info_pointer <=#Tp rd_info_pointer + 1'b1; 155 | end 156 | end 157 | 158 | // rd_pointer 159 | always @(posedge clk or posedge rst) begin 160 | if(rst) begin 161 | rd_pointer <= 5'h0; 162 | end else if(release_buffer & (~fifo_empty)) begin 163 | rd_pointer <=#Tp rd_pointer + {2'h0, length_info}; 164 | end 165 | end 166 | 167 | // wr_pointer 168 | always @(posedge clk or posedge rst) begin 169 | if(rst) begin 170 | wr_pointer <= 5'h0; 171 | end else if(reset_mode) begin 172 | wr_pointer <=#Tp rd_pointer; 173 | end else if(wr & (~fifo_full)) begin 174 | wr_pointer <=#Tp wr_pointer + 1'b1; 175 | end 176 | end 177 | 178 | // latch_overrun 179 | always @(posedge clk or posedge rst) begin 180 | if(rst) begin 181 | latch_overrun <= 1'b0; 182 | end else if(reset_mode | write_length_info) begin 183 | latch_overrun <=#Tp 1'b0; 184 | end else if(wr & fifo_full) begin 185 | latch_overrun <=#Tp 1'b1; 186 | end 187 | end 188 | 189 | // Counting data in fifo 190 | always @(posedge clk or posedge rst) begin 191 | if(rst) begin 192 | fifo_cnt <= 7'h0; 193 | end else if(reset_mode) begin 194 | fifo_cnt <=#Tp 7'h0; 195 | end else if(wr & (~release_buffer) & (~fifo_full)) begin 196 | fifo_cnt <=#Tp fifo_cnt + 1'b1; 197 | end else if((~wr) & release_buffer & (~fifo_empty)) begin 198 | fifo_cnt <=#Tp fifo_cnt - {3'h0, length_info}; 199 | end else if(wr & release_buffer & (~fifo_full) & (~fifo_empty)) begin 200 | fifo_cnt <=#Tp fifo_cnt - {3'h0, length_info} + 1'b1; 201 | end 202 | end 203 | 204 | assign fifo_full = fifo_cnt == 7'd64; 205 | assign fifo_empty = fifo_cnt == 7'd0; 206 | 207 | // Counting data in length_fifo and overrun_info fifo 208 | always @(posedge clk or posedge rst) begin 209 | if(rst) begin 210 | info_cnt <=#Tp 7'h0; 211 | end else if(reset_mode) begin 212 | info_cnt <=#Tp 7'h0; 213 | end else if(write_length_info ^ release_buffer) begin 214 | if(release_buffer & (~info_empty)) begin 215 | info_cnt <=#Tp info_cnt - 1'b1; 216 | end else if(write_length_info & (~info_full)) begin 217 | info_cnt <=#Tp info_cnt + 1'b1; 218 | end 219 | end 220 | end 221 | 222 | assign info_full = info_cnt == 7'd64; 223 | assign info_empty = info_cnt == 7'd0; 224 | 225 | // Selecting which address will be used for reading data from rx fifo 226 | always @(extended_mode or rd_pointer or addr) begin 227 | if(extended_mode) begin 228 | // extended mode 229 | read_address = rd_pointer + (addr - 6'd16); 230 | end else begin 231 | // normal mode 232 | read_address = rd_pointer + (addr - 6'd20); 233 | end 234 | end 235 | 236 | always @(posedge clk or posedge rst) begin 237 | if(rst) begin 238 | initialize_memories <= 1'b1; 239 | end else if(&wr_info_pointer) begin 240 | initialize_memories <=#Tp 1'b0; 241 | end 242 | end 243 | 244 | `ifdef ALTERA_RAM 245 | // altera_ram_64x8_sync fifo 246 | lpm_ram_dp fifo 247 | ( 248 | .q (data_out), 249 | .rdclock (clk), 250 | .wrclock (clk), 251 | .data (data_in), 252 | .wren (wr & (~fifo_full)), 253 | .rden (fifo_selected), 254 | .wraddress (wr_pointer), 255 | .rdaddress (read_address) 256 | ); 257 | defparam fifo.lpm_width = 8; 258 | defparam fifo.lpm_widthad = 6; 259 | defparam fifo.lpm_numwords = 64; 260 | 261 | // altera_ram_64x4_sync info_fifo 262 | lpm_ram_dp info_fifo 263 | ( 264 | .q (length_info), 265 | .rdclock (clk), 266 | .wrclock (clk), 267 | .data (len_cnt & {4{~initialize_memories}}), 268 | .wren (write_length_info & (~info_full) | initialize_memories), 269 | .wraddress (wr_info_pointer), 270 | .rdaddress (rd_info_pointer) 271 | ); 272 | defparam info_fifo.lpm_width = 4; 273 | defparam info_fifo.lpm_widthad = 6; 274 | defparam info_fifo.lpm_numwords = 64; 275 | 276 | // altera_ram_64x1_sync overrun_fifo 277 | lpm_ram_dp overrun_fifo 278 | ( 279 | .q (overrun), 280 | .rdclock (clk), 281 | .wrclock (clk), 282 | .data ((latch_overrun | (wr & fifo_full)) & (~initialize_memories)), 283 | .wren (write_length_info & (~info_full) | initialize_memories), 284 | .wraddress (wr_info_pointer), 285 | .rdaddress (rd_info_pointer) 286 | ); 287 | defparam overrun_fifo.lpm_width = 1; 288 | defparam overrun_fifo.lpm_widthad = 6; 289 | defparam overrun_fifo.lpm_numwords = 64; 290 | 291 | `else 292 | `ifdef ACTEL_APA_RAM 293 | actel_ram_64x8_sync fifo 294 | ( 295 | .DO (data_out), 296 | .RCLOCK (clk), 297 | .WCLOCK (clk), 298 | .DI (data_in), 299 | .PO (), // parity not used 300 | .WRB (~(wr & (~fifo_full))), 301 | .RDB (~fifo_selected), 302 | .WADDR (wr_pointer), 303 | .RADDR (read_address) 304 | ); 305 | 306 | actel_ram_64x4_sync info_fifo 307 | ( 308 | .DO (length_info), 309 | .RCLOCK (clk), 310 | .WCLOCK (clk), 311 | .DI (len_cnt & {4{~initialize_memories}}), 312 | .PO (), // parity not used 313 | .WRB (~(write_length_info & (~info_full) | initialize_memories)), 314 | .RDB (1'b0), // always enabled 315 | .WADDR (wr_info_pointer), 316 | .RADDR (rd_info_pointer) 317 | ); 318 | 319 | actel_ram_64x1_sync overrun_fifo 320 | ( 321 | .DO (overrun), 322 | .RCLOCK (clk), 323 | .WCLOCK (clk), 324 | .DI ((latch_overrun | (wr & fifo_full)) & (~initialize_memories)), 325 | .PO (), // parity not used 326 | .WRB (~(write_length_info & (~info_full) | initialize_memories)), 327 | .RDB (1'b0), // always enabled 328 | .WADDR (wr_info_pointer), 329 | .RADDR (rd_info_pointer) 330 | ); 331 | `else 332 | `ifdef XILINX_RAM 333 | 334 | RAMB4_S8_S8 fifo 335 | ( 336 | .DOA(), 337 | .DOB(data_out), 338 | .ADDRA({3'h0, wr_pointer}), 339 | .CLKA(clk), 340 | .DIA(data_in), 341 | .ENA(1'b1), 342 | .RSTA(1'b0), 343 | .WEA(wr & (~fifo_full)), 344 | .ADDRB({3'h0, read_address}), 345 | .CLKB(clk), 346 | .DIB(8'h0), 347 | .ENB(1'b1), 348 | .RSTB(1'b0), 349 | .WEB(1'b0) 350 | ); 351 | 352 | RAMB4_S4_S4 info_fifo 353 | ( 354 | .DOA(), 355 | .DOB(length_info), 356 | .ADDRA({4'h0, wr_info_pointer}), 357 | .CLKA(clk), 358 | .DIA(len_cnt & {4{~initialize_memories}}), 359 | .ENA(1'b1), 360 | .RSTA(1'b0), 361 | .WEA(write_length_info & (~info_full) | initialize_memories), 362 | .ADDRB({4'h0, rd_info_pointer}), 363 | .CLKB(clk), 364 | .DIB(4'h0), 365 | .ENB(1'b1), 366 | .RSTB(1'b0), 367 | .WEB(1'b0) 368 | ); 369 | 370 | RAMB4_S1_S1 overrun_fifo 371 | ( 372 | .DOA(), 373 | .DOB(overrun), 374 | .ADDRA({6'h0, wr_info_pointer}), 375 | .CLKA(clk), 376 | .DIA((latch_overrun | (wr & fifo_full)) & (~initialize_memories)), 377 | .ENA(1'b1), 378 | .RSTA(1'b0), 379 | .WEA(write_length_info & (~info_full) | initialize_memories), 380 | .ADDRB({6'h0, rd_info_pointer}), 381 | .CLKB(clk), 382 | .DIB(1'h0), 383 | .ENB(1'b1), 384 | .RSTB(1'b0), 385 | .WEB(1'b0) 386 | ); 387 | 388 | `else 389 | `ifdef VIRTUALSILICON_RAM 390 | 391 | `ifdef CAN_BIST 392 | vs_hdtp_64x8_bist 393 | `else 394 | vs_hdtp_64x8 395 | `endif 396 | fifo 397 | ( 398 | .RCK (clk), 399 | .WCK (clk), 400 | .RADR (read_address), 401 | .WADR (wr_pointer), 402 | .DI (data_in), 403 | .DOUT (data_out), 404 | .REN (~fifo_selected), 405 | .WEN (~(wr & (~fifo_full))) 406 | `ifdef CAN_BIST 407 | , 408 | .mbist_si_i (mbist_si_i), 409 | .mbist_so_o (mbist_s_0), 410 | .mbist_ctrl_i (mbist_ctrl_i) 411 | `endif 412 | ); 413 | 414 | `ifdef CAN_BIST 415 | vs_hdtp_64x4_bist 416 | `else 417 | vs_hdtp_64x4 418 | `endif 419 | info_fifo 420 | ( 421 | .RCK (clk), 422 | .WCK (clk), 423 | .RADR (rd_info_pointer), 424 | .WADR (wr_info_pointer), 425 | .DI (len_cnt & {4{~initialize_memories}}), 426 | .DOUT (length_info), 427 | .REN (1'b0), 428 | .WEN (~(write_length_info & (~info_full) | initialize_memories)) 429 | `ifdef CAN_BIST 430 | , 431 | .mbist_si_i (mbist_s_0), 432 | .mbist_so_o (mbist_so_o), 433 | .mbist_ctrl_i (mbist_ctrl_i) 434 | `endif 435 | ); 436 | 437 | // overrun_info 438 | always @(posedge clk) begin 439 | if(write_length_info & (~info_full) | initialize_memories) begin 440 | overrun_info[wr_info_pointer] <=#Tp (latch_overrun | (wr & fifo_full)) & (~initialize_memories); 441 | end 442 | end 443 | 444 | // reading overrun 445 | assign overrun = overrun_info[rd_info_pointer]; 446 | 447 | `else 448 | `ifdef ARTISAN_RAM 449 | 450 | `ifdef CAN_BIST 451 | art_hstp_64x8_bist fifo 452 | ( 453 | .CLKR (clk), 454 | .CLKW (clk), 455 | .AR (read_address), 456 | .AW (wr_pointer), 457 | .D (data_in), 458 | .Q (data_out), 459 | .REN (~fifo_selected), 460 | .WEN (~(wr & (~fifo_full))), 461 | .mbist_si_i (mbist_si_i), 462 | .mbist_so_o (mbist_s_0), 463 | .mbist_ctrl_i (mbist_ctrl_i) 464 | ); 465 | art_hstp_64x4_bist info_fifo 466 | ( 467 | .CLKR (clk), 468 | .CLKW (clk), 469 | .AR (rd_info_pointer), 470 | .AW (wr_info_pointer), 471 | .D (len_cnt & {4{~initialize_memories}}), 472 | .Q (length_info), 473 | .REN (1'b0), 474 | .WEN (~(write_length_info & (~info_full) | initialize_memories)), 475 | .mbist_si_i (mbist_s_0), 476 | .mbist_so_o (mbist_so_o), 477 | .mbist_ctrl_i (mbist_ctrl_i) 478 | ); 479 | `else 480 | art_hsdp_64x8 fifo 481 | ( 482 | .CENA (1'b0), 483 | .CENB (1'b0), 484 | .CLKA (clk), 485 | .CLKB (clk), 486 | .AA (read_address), 487 | .AB (wr_pointer), 488 | .DA (8'h00), 489 | .DB (data_in), 490 | .QA (data_out), 491 | .QB (), 492 | .OENA (~fifo_selected), 493 | .OENB (1'b1), 494 | .WENA (1'b1), 495 | .WENB (~(wr & (~fifo_full))) 496 | ); 497 | art_hsdp_64x4 info_fifo 498 | ( 499 | .CENA (1'b0), 500 | .CENB (1'b0), 501 | .CLKA (clk), 502 | .CLKB (clk), 503 | .AA (rd_info_pointer), 504 | .AB (wr_info_pointer), 505 | .DA (4'h0), 506 | .DB (len_cnt & {4{~initialize_memories}}), 507 | .QA (length_info), 508 | .QB (), 509 | .OENA (1'b0), 510 | .OENB (1'b1), 511 | .WENA (1'b1), 512 | .WENB (~(write_length_info & (~info_full) | initialize_memories)) 513 | ); 514 | `endif 515 | 516 | // overrun_info 517 | always @(posedge clk) begin 518 | if(write_length_info & (~info_full) | initialize_memories) begin 519 | overrun_info[wr_info_pointer] <=#Tp (latch_overrun | (wr & fifo_full)) & (~initialize_memories); 520 | end 521 | end 522 | 523 | // reading overrun 524 | assign overrun = overrun_info[rd_info_pointer]; 525 | 526 | `else 527 | // writing data to fifo 528 | always @(posedge clk) begin 529 | if(wr & (~fifo_full)) begin 530 | fifo[wr_pointer] <=#Tp data_in; 531 | end 532 | end 533 | 534 | // reading from fifo 535 | assign data_out = fifo[read_address]; 536 | 537 | // writing length_fifo 538 | always @(posedge clk) begin 539 | if(write_length_info & (~info_full) | initialize_memories) begin 540 | length_fifo[wr_info_pointer] <=#Tp len_cnt & {4{~initialize_memories}}; 541 | end 542 | end 543 | 544 | // reading length_fifo 545 | assign length_info = length_fifo[rd_info_pointer]; 546 | 547 | // overrun_info 548 | always @(posedge clk) begin 549 | if(write_length_info & (~info_full) | initialize_memories) begin 550 | overrun_info[wr_info_pointer] <=#Tp (latch_overrun | (wr & fifo_full)) & (~initialize_memories); 551 | end 552 | end 553 | 554 | // reading overrun 555 | assign overrun = overrun_info[rd_info_pointer]; 556 | 557 | `endif 558 | `endif 559 | `endif 560 | `endif 561 | `endif 562 | 563 | endmodule 564 | -------------------------------------------------------------------------------- /can_ibo.v: -------------------------------------------------------------------------------- 1 | /* vim: colorcolumn=80 2 | * 3 | * This file is part of a verilog CAN controller that is SJA1000 compatible. 4 | * 5 | * Authors: 6 | * * Igor Mohor 7 | * Author of the original version at 8 | * http://www.opencores.org/projects/can/ 9 | * (which has been unmaintained since about 2009) 10 | * 11 | * * David Piegdon 12 | * Picked up project for cleanup and bugfixes in 2019 13 | * 14 | * Any additional information is available in the LICENSE file. 15 | * 16 | * Copyright (C) 2002, 2003, 2004, 2019 Authors 17 | * 18 | * This source file may be used and distributed without restriction provided 19 | * that this copyright statement is not removed from the file and that any 20 | * derivative work contains the original copyright notice and the associated 21 | * disclaimer. 22 | * 23 | * This source file is free software; you can redistribute it and/or modify it 24 | * under the terms of the GNU Lesser General Public License as published by the 25 | * Free Software Foundation; either version 2.1 of the License, or (at your 26 | * option) any later version. 27 | * 28 | * This source is distributed in the hope that it will be useful, but WITHOUT 29 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 30 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 31 | * details. 32 | * 33 | * You should have received a copy of the GNU Lesser General Public License 34 | * along with this source; if not, download it from 35 | * http://www.opencores.org/lgpl.shtml 36 | * 37 | * The CAN protocol is developed by Robert Bosch GmbH and protected by patents. 38 | * Anybody who wants to implement this CAN IP core on silicon has to obtain 39 | * a CAN protocol license from Bosch. 40 | */ 41 | 42 | `default_nettype none 43 | 44 | // This module only inverts bit order 45 | module can_ibo( 46 | input wire [7:0] di, 47 | output wire [7:0] do); 48 | 49 | assign do[0] = di[7]; 50 | assign do[1] = di[6]; 51 | assign do[2] = di[5]; 52 | assign do[3] = di[4]; 53 | assign do[4] = di[3]; 54 | assign do[5] = di[2]; 55 | assign do[6] = di[1]; 56 | assign do[7] = di[0]; 57 | 58 | endmodule 59 | -------------------------------------------------------------------------------- /can_register.v: -------------------------------------------------------------------------------- 1 | /* vim: colorcolumn=80 2 | * 3 | * This file is part of a verilog CAN controller that is SJA1000 compatible. 4 | * 5 | * Authors: 6 | * * Igor Mohor 7 | * Author of the original version at 8 | * http://www.opencores.org/projects/can/ 9 | * (which has been unmaintained since about 2009) 10 | * 11 | * * David Piegdon 12 | * Picked up project for cleanup and bugfixes in 2019 13 | * 14 | * Any additional information is available in the LICENSE file. 15 | * 16 | * Copyright (C) 2002, 2003, 2004, 2019 Authors 17 | * 18 | * This source file may be used and distributed without restriction provided 19 | * that this copyright statement is not removed from the file and that any 20 | * derivative work contains the original copyright notice and the associated 21 | * disclaimer. 22 | * 23 | * This source file is free software; you can redistribute it and/or modify it 24 | * under the terms of the GNU Lesser General Public License as published by the 25 | * Free Software Foundation; either version 2.1 of the License, or (at your 26 | * option) any later version. 27 | * 28 | * This source is distributed in the hope that it will be useful, but WITHOUT 29 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 30 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 31 | * details. 32 | * 33 | * You should have received a copy of the GNU Lesser General Public License 34 | * along with this source; if not, download it from 35 | * http://www.opencores.org/lgpl.shtml 36 | * 37 | * The CAN protocol is developed by Robert Bosch GmbH and protected by patents. 38 | * Anybody who wants to implement this CAN IP core on silicon has to obtain 39 | * a CAN protocol license from Bosch. 40 | */ 41 | 42 | `default_nettype none 43 | 44 | module can_register( 45 | input wire [WIDTH-1:0] data_in, 46 | output reg [WIDTH-1:0] data_out, 47 | input wire we, 48 | input wire clk); 49 | 50 | parameter WIDTH = 8; 51 | 52 | always @(posedge clk) begin 53 | if(we) begin 54 | data_out <=#1 data_in; 55 | end 56 | end 57 | 58 | endmodule 59 | -------------------------------------------------------------------------------- /can_register_asyn.v: -------------------------------------------------------------------------------- 1 | /* vim: colorcolumn=80 2 | * 3 | * This file is part of a verilog CAN controller that is SJA1000 compatible. 4 | * 5 | * Authors: 6 | * * Igor Mohor 7 | * Author of the original version at 8 | * http://www.opencores.org/projects/can/ 9 | * (which has been unmaintained since about 2009) 10 | * 11 | * * David Piegdon 12 | * Picked up project for cleanup and bugfixes in 2019 13 | * 14 | * Any additional information is available in the LICENSE file. 15 | * 16 | * Copyright (C) 2002, 2003, 2004, 2019 Authors 17 | * 18 | * This source file may be used and distributed without restriction provided 19 | * that this copyright statement is not removed from the file and that any 20 | * derivative work contains the original copyright notice and the associated 21 | * disclaimer. 22 | * 23 | * This source file is free software; you can redistribute it and/or modify it 24 | * under the terms of the GNU Lesser General Public License as published by the 25 | * Free Software Foundation; either version 2.1 of the License, or (at your 26 | * option) any later version. 27 | * 28 | * This source is distributed in the hope that it will be useful, but WITHOUT 29 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 30 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 31 | * details. 32 | * 33 | * You should have received a copy of the GNU Lesser General Public License 34 | * along with this source; if not, download it from 35 | * http://www.opencores.org/lgpl.shtml 36 | * 37 | * The CAN protocol is developed by Robert Bosch GmbH and protected by patents. 38 | * Anybody who wants to implement this CAN IP core on silicon has to obtain 39 | * a CAN protocol license from Bosch. 40 | */ 41 | 42 | `default_nettype none 43 | 44 | module can_register_asyn( 45 | input wire [WIDTH-1:0] data_in, 46 | output reg [WIDTH-1:0] data_out, 47 | input wire we, 48 | input wire clk, 49 | input wire rst); 50 | 51 | parameter WIDTH = 8; 52 | parameter RESET_VALUE = 0; 53 | 54 | always @(posedge clk or posedge rst) begin 55 | if(rst) begin 56 | data_out <=#1 RESET_VALUE; 57 | end else if(we) begin 58 | data_out <=#1 data_in; 59 | end 60 | end 61 | 62 | endmodule 63 | -------------------------------------------------------------------------------- /can_register_asyn_syn.v: -------------------------------------------------------------------------------- 1 | /* vim: colorcolumn=80 2 | * 3 | * This file is part of a verilog CAN controller that is SJA1000 compatible. 4 | * 5 | * Authors: 6 | * * Igor Mohor 7 | * Author of the original version at 8 | * http://www.opencores.org/projects/can/ 9 | * (which has been unmaintained since about 2009) 10 | * 11 | * * David Piegdon 12 | * Picked up project for cleanup and bugfixes in 2019 13 | * 14 | * Any additional information is available in the LICENSE file. 15 | * 16 | * Copyright (C) 2002, 2003, 2004, 2019 Authors 17 | * 18 | * This source file may be used and distributed without restriction provided 19 | * that this copyright statement is not removed from the file and that any 20 | * derivative work contains the original copyright notice and the associated 21 | * disclaimer. 22 | * 23 | * This source file is free software; you can redistribute it and/or modify it 24 | * under the terms of the GNU Lesser General Public License as published by the 25 | * Free Software Foundation; either version 2.1 of the License, or (at your 26 | * option) any later version. 27 | * 28 | * This source is distributed in the hope that it will be useful, but WITHOUT 29 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 30 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 31 | * details. 32 | * 33 | * You should have received a copy of the GNU Lesser General Public License 34 | * along with this source; if not, download it from 35 | * http://www.opencores.org/lgpl.shtml 36 | * 37 | * The CAN protocol is developed by Robert Bosch GmbH and protected by patents. 38 | * Anybody who wants to implement this CAN IP core on silicon has to obtain 39 | * a CAN protocol license from Bosch. 40 | */ 41 | 42 | `default_nettype none 43 | 44 | module can_register_asyn_syn( 45 | input wire [WIDTH-1:0] data_in, 46 | output reg [WIDTH-1:0] data_out, 47 | input wire we, 48 | input wire clk, 49 | input wire rst, 50 | input wire rst_sync); 51 | 52 | parameter WIDTH = 8; 53 | parameter RESET_VALUE = 0; 54 | 55 | always @(posedge clk or posedge rst) begin 56 | if(rst) begin 57 | data_out <=#1 RESET_VALUE; 58 | end else if(rst_sync) begin 59 | data_out <=#1 RESET_VALUE; 60 | end else if(we) begin 61 | data_out <=#1 data_in; 62 | end 63 | end 64 | 65 | endmodule 66 | -------------------------------------------------------------------------------- /can_register_syn.v: -------------------------------------------------------------------------------- 1 | /* vim: colorcolumn=80 2 | * 3 | * This file is part of a verilog CAN controller that is SJA1000 compatible. 4 | * 5 | * Authors: 6 | * * Igor Mohor 7 | * Author of the original version at 8 | * http://www.opencores.org/projects/can/ 9 | * (which has been unmaintained since about 2009) 10 | * 11 | * * David Piegdon 12 | * Picked up project for cleanup and bugfixes in 2019 13 | * 14 | * Any additional information is available in the LICENSE file. 15 | * 16 | * Copyright (C) 2002, 2003, 2004, 2019 Authors 17 | * 18 | * This source file may be used and distributed without restriction provided 19 | * that this copyright statement is not removed from the file and that any 20 | * derivative work contains the original copyright notice and the associated 21 | * disclaimer. 22 | * 23 | * This source file is free software; you can redistribute it and/or modify it 24 | * under the terms of the GNU Lesser General Public License as published by the 25 | * Free Software Foundation; either version 2.1 of the License, or (at your 26 | * option) any later version. 27 | * 28 | * This source is distributed in the hope that it will be useful, but WITHOUT 29 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 30 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 31 | * details. 32 | * 33 | * You should have received a copy of the GNU Lesser General Public License 34 | * along with this source; if not, download it from 35 | * http://www.opencores.org/lgpl.shtml 36 | * 37 | * The CAN protocol is developed by Robert Bosch GmbH and protected by patents. 38 | * Anybody who wants to implement this CAN IP core on silicon has to obtain 39 | * a CAN protocol license from Bosch. 40 | */ 41 | 42 | `default_nettype none 43 | 44 | module can_register_syn( 45 | input wire [WIDTH-1:0] data_in, 46 | output reg [WIDTH-1:0] data_out, 47 | input wire we, 48 | input wire clk, 49 | input wire rst_sync); 50 | 51 | parameter WIDTH = 8; 52 | parameter RESET_VALUE = 0; 53 | 54 | always @(posedge clk) 55 | begin 56 | if(rst_sync) begin 57 | data_out <=#1 RESET_VALUE; 58 | end else if(we) begin 59 | data_out <=#1 data_in; 60 | end 61 | end 62 | 63 | endmodule 64 | -------------------------------------------------------------------------------- /can_registers.v: -------------------------------------------------------------------------------- 1 | /* vim: colorcolumn=80 2 | * 3 | * This file is part of a verilog CAN controller that is SJA1000 compatible. 4 | * 5 | * Authors: 6 | * * Igor Mohor 7 | * Author of the original version at 8 | * http://www.opencores.org/projects/can/ 9 | * (which has been unmaintained since about 2009) 10 | * 11 | * * David Piegdon 12 | * Picked up project for cleanup and bugfixes in 2019 13 | * 14 | * Any additional information is available in the LICENSE file. 15 | * 16 | * Copyright (C) 2002, 2003, 2004, 2019 Authors 17 | * 18 | * This source file may be used and distributed without restriction provided 19 | * that this copyright statement is not removed from the file and that any 20 | * derivative work contains the original copyright notice and the associated 21 | * disclaimer. 22 | * 23 | * This source file is free software; you can redistribute it and/or modify it 24 | * under the terms of the GNU Lesser General Public License as published by the 25 | * Free Software Foundation; either version 2.1 of the License, or (at your 26 | * option) any later version. 27 | * 28 | * This source is distributed in the hope that it will be useful, but WITHOUT 29 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 30 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 31 | * details. 32 | * 33 | * You should have received a copy of the GNU Lesser General Public License 34 | * along with this source; if not, download it from 35 | * http://www.opencores.org/lgpl.shtml 36 | * 37 | * The CAN protocol is developed by Robert Bosch GmbH and protected by patents. 38 | * Anybody who wants to implement this CAN IP core on silicon has to obtain 39 | * a CAN protocol license from Bosch. 40 | */ 41 | 42 | `default_nettype none 43 | 44 | `include "can_top_defines.v" 45 | `include "can_register_asyn_syn.v" 46 | `include "can_register_asyn.v" 47 | `include "can_register.v" 48 | 49 | module can_registers( 50 | input wire clk, 51 | input wire rst, 52 | input wire cs, 53 | input wire we, 54 | input wire [7:0] addr, 55 | input wire [7:0] data_in, 56 | output reg [7:0] data_out, 57 | output reg irq_n, 58 | 59 | input wire sample_point, 60 | input wire transmitting, 61 | input wire set_reset_mode, 62 | input wire node_bus_off, 63 | input wire error_status, 64 | input wire [7:0] rx_err_cnt, 65 | input wire [7:0] tx_err_cnt, 66 | input wire transmit_status, 67 | input wire receive_status, 68 | input wire tx_successful, 69 | input wire need_to_tx, 70 | input wire overrun, 71 | input wire info_empty, 72 | input wire set_bus_error_irq, 73 | input wire set_arbitration_lost_irq, 74 | input wire [4:0] arbitration_lost_capture, 75 | input wire node_error_passive, 76 | input wire node_error_active, 77 | input wire [6:0] rx_message_counter, 78 | 79 | /* Mode register */ 80 | output wire reset_mode, 81 | output wire listen_only_mode, 82 | output wire acceptance_filter_mode, 83 | output wire self_test_mode, 84 | 85 | /* Command register */ 86 | output wire clear_data_overrun, 87 | output wire release_buffer, 88 | output wire abort_tx, 89 | output wire tx_request, 90 | output reg self_rx_request, 91 | output reg single_shot_transmission, 92 | input wire tx_state, 93 | input wire tx_state_q, 94 | output wire overload_request, 95 | input wire overload_frame, 96 | 97 | /* Arbitration Lost Capture Register */ 98 | output wire read_arbitration_lost_capture_reg, 99 | 100 | /* Error Code Capture Register */ 101 | output wire read_error_code_capture_reg, 102 | input wire [7:0] error_capture_code, 103 | 104 | /* Bus Timing 0 register */ 105 | output wire [5:0] baud_r_presc, 106 | output wire [1:0] sync_jump_width, 107 | 108 | /* Bus Timing 1 register */ 109 | output wire [3:0] time_segment1, 110 | output wire [2:0] time_segment2, 111 | output wire triple_sampling, 112 | 113 | /* Error Warning Limit register */ 114 | output wire [7:0] error_warning_limit, 115 | 116 | /* Rx Error Counter register */ 117 | output wire we_rx_err_cnt, 118 | 119 | /* Tx Error Counter register */ 120 | output wire we_tx_err_cnt, 121 | 122 | /* Clock Divider register */ 123 | output wire extended_mode, 124 | output wire clkout, 125 | 126 | /* This section is for BASIC and EXTENDED mode */ 127 | /* Acceptance code register */ 128 | output wire [7:0] acceptance_code_0, 129 | /* Acceptance mask register */ 130 | output wire [7:0] acceptance_mask_0, 131 | /* End: This section is for BASIC and EXTENDED mode */ 132 | 133 | /* This section is for EXTENDED mode */ 134 | /* Acceptance code register */ 135 | output wire [7:0] acceptance_code_1, 136 | output wire [7:0] acceptance_code_2, 137 | output wire [7:0] acceptance_code_3, 138 | /* Acceptance mask register */ 139 | output wire [7:0] acceptance_mask_1, 140 | output wire [7:0] acceptance_mask_2, 141 | output wire [7:0] acceptance_mask_3, 142 | /* End: This section is for EXTENDED mode */ 143 | 144 | /* Tx data registers. Holding identifier (basic mode), tx frame information (extended mode) and data */ 145 | output wire [7:0] tx_data_0, 146 | output wire [7:0] tx_data_1, 147 | output wire [7:0] tx_data_2, 148 | output wire [7:0] tx_data_3, 149 | output wire [7:0] tx_data_4, 150 | output wire [7:0] tx_data_5, 151 | output wire [7:0] tx_data_6, 152 | output wire [7:0] tx_data_7, 153 | output wire [7:0] tx_data_8, 154 | output wire [7:0] tx_data_9, 155 | output wire [7:0] tx_data_10, 156 | output wire [7:0] tx_data_11, 157 | output wire [7:0] tx_data_12 158 | /* End: Tx data registers */ 159 | ); 160 | 161 | parameter Tp = 1; 162 | 163 | reg tx_successful_q; 164 | reg overrun_q; 165 | reg overrun_status; 166 | reg transmission_complete; 167 | reg transmit_buffer_status_q; 168 | reg receive_buffer_status; 169 | reg error_status_q; 170 | reg node_bus_off_q; 171 | reg node_error_passive_q; 172 | reg transmit_buffer_status; 173 | 174 | // Some interrupts exist in basic mode and in extended mode. Since they are in different registers they need to be multiplexed. 175 | wire data_overrun_irq_en; 176 | wire error_warning_irq_en; 177 | wire transmit_irq_en; 178 | wire receive_irq_en; 179 | 180 | wire [7:0] irq_reg; 181 | wire irq; 182 | 183 | wire we_mode = cs & we & (addr == 8'd0); 184 | wire we_command = cs & we & (addr == 8'd1); 185 | wire we_bus_timing_0 = cs & we & (addr == 8'd6) & reset_mode; 186 | wire we_bus_timing_1 = cs & we & (addr == 8'd7) & reset_mode; 187 | wire we_clock_divider_low = cs & we & (addr == 8'd31); 188 | wire we_clock_divider_hi = we_clock_divider_low & reset_mode; 189 | 190 | wire read = cs & (~we); 191 | wire read_irq_reg = read & (addr == 8'd3); 192 | assign read_arbitration_lost_capture_reg = read & extended_mode & (addr == 8'd11); 193 | assign read_error_code_capture_reg = read & extended_mode & (addr == 8'd12); 194 | 195 | /* This section is for BASIC and EXTENDED mode */ 196 | wire we_acceptance_code_0 = cs & we & reset_mode & ((~extended_mode) & (addr == 8'd4) | extended_mode & (addr == 8'd16)); 197 | wire we_acceptance_mask_0 = cs & we & reset_mode & ((~extended_mode) & (addr == 8'd5) | extended_mode & (addr == 8'd20)); 198 | wire we_tx_data_0 = cs & we & (~reset_mode) & ((~extended_mode) & (addr == 8'd10) | extended_mode & (addr == 8'd16)) & transmit_buffer_status; 199 | wire we_tx_data_1 = cs & we & (~reset_mode) & ((~extended_mode) & (addr == 8'd11) | extended_mode & (addr == 8'd17)) & transmit_buffer_status; 200 | wire we_tx_data_2 = cs & we & (~reset_mode) & ((~extended_mode) & (addr == 8'd12) | extended_mode & (addr == 8'd18)) & transmit_buffer_status; 201 | wire we_tx_data_3 = cs & we & (~reset_mode) & ((~extended_mode) & (addr == 8'd13) | extended_mode & (addr == 8'd19)) & transmit_buffer_status; 202 | wire we_tx_data_4 = cs & we & (~reset_mode) & ((~extended_mode) & (addr == 8'd14) | extended_mode & (addr == 8'd20)) & transmit_buffer_status; 203 | wire we_tx_data_5 = cs & we & (~reset_mode) & ((~extended_mode) & (addr == 8'd15) | extended_mode & (addr == 8'd21)) & transmit_buffer_status; 204 | wire we_tx_data_6 = cs & we & (~reset_mode) & ((~extended_mode) & (addr == 8'd16) | extended_mode & (addr == 8'd22)) & transmit_buffer_status; 205 | wire we_tx_data_7 = cs & we & (~reset_mode) & ((~extended_mode) & (addr == 8'd17) | extended_mode & (addr == 8'd23)) & transmit_buffer_status; 206 | wire we_tx_data_8 = cs & we & (~reset_mode) & ((~extended_mode) & (addr == 8'd18) | extended_mode & (addr == 8'd24)) & transmit_buffer_status; 207 | wire we_tx_data_9 = cs & we & (~reset_mode) & ((~extended_mode) & (addr == 8'd19) | extended_mode & (addr == 8'd25)) & transmit_buffer_status; 208 | wire we_tx_data_10 = cs & we & (~reset_mode) & ( extended_mode & (addr == 8'd26)) & transmit_buffer_status; 209 | wire we_tx_data_11 = cs & we & (~reset_mode) & ( extended_mode & (addr == 8'd27)) & transmit_buffer_status; 210 | wire we_tx_data_12 = cs & we & (~reset_mode) & ( extended_mode & (addr == 8'd28)) & transmit_buffer_status; 211 | /* End: This section is for BASIC and EXTENDED mode */ 212 | 213 | /* This section is for EXTENDED mode */ 214 | wire we_interrupt_enable = cs & we & (addr == 8'd4) & extended_mode; 215 | wire we_error_warning_limit = cs & we & (addr == 8'd13) & reset_mode & extended_mode; 216 | assign we_rx_err_cnt = cs & we & (addr == 8'd14) & reset_mode & extended_mode; 217 | assign we_tx_err_cnt = cs & we & (addr == 8'd15) & reset_mode & extended_mode; 218 | wire we_acceptance_code_1 = cs & we & (addr == 8'd17) & reset_mode & extended_mode; 219 | wire we_acceptance_code_2 = cs & we & (addr == 8'd18) & reset_mode & extended_mode; 220 | wire we_acceptance_code_3 = cs & we & (addr == 8'd19) & reset_mode & extended_mode; 221 | wire we_acceptance_mask_1 = cs & we & (addr == 8'd21) & reset_mode & extended_mode; 222 | wire we_acceptance_mask_2 = cs & we & (addr == 8'd22) & reset_mode & extended_mode; 223 | wire we_acceptance_mask_3 = cs & we & (addr == 8'd23) & reset_mode & extended_mode; 224 | /* End: This section is for EXTENDED mode */ 225 | 226 | always @(posedge clk) begin 227 | tx_successful_q <=#Tp tx_successful; 228 | overrun_q <=#Tp overrun; 229 | transmit_buffer_status_q <=#Tp transmit_buffer_status; 230 | error_status_q <=#Tp error_status; 231 | node_bus_off_q <=#Tp node_bus_off; 232 | node_error_passive_q <=#Tp node_error_passive; 233 | end 234 | 235 | /* Mode register */ 236 | wire [0:0] mode; 237 | wire [4:1] mode_basic; 238 | wire [3:1] mode_ext; 239 | wire receive_irq_en_basic; 240 | wire transmit_irq_en_basic; 241 | wire error_irq_en_basic; 242 | wire overrun_irq_en_basic; 243 | 244 | can_register_asyn_syn #(1, 1'h1) MODE_REG0 245 | ( .data_in(data_in[0]), 246 | .data_out(mode[0]), 247 | .we(we_mode), 248 | .clk(clk), 249 | .rst(rst), 250 | .rst_sync(set_reset_mode) 251 | ); 252 | 253 | can_register_asyn #(4, 0) MODE_REG_BASIC 254 | ( .data_in(data_in[4:1]), 255 | .data_out(mode_basic[4:1]), 256 | .we(we_mode), 257 | .clk(clk), 258 | .rst(rst) 259 | ); 260 | 261 | can_register_asyn #(3, 0) MODE_REG_EXT 262 | ( .data_in(data_in[3:1]), 263 | .data_out(mode_ext[3:1]), 264 | .we(we_mode & reset_mode), 265 | .clk(clk), 266 | .rst(rst) 267 | ); 268 | 269 | assign reset_mode = mode[0]; 270 | assign listen_only_mode = extended_mode & mode_ext[1]; 271 | assign self_test_mode = extended_mode & mode_ext[2]; 272 | assign acceptance_filter_mode = extended_mode & mode_ext[3]; 273 | 274 | assign receive_irq_en_basic = mode_basic[1]; 275 | assign transmit_irq_en_basic = mode_basic[2]; 276 | assign error_irq_en_basic = mode_basic[3]; 277 | assign overrun_irq_en_basic = mode_basic[4]; 278 | /* End Mode register */ 279 | 280 | /* Command register */ 281 | wire [4:0] command; 282 | can_register_asyn_syn #(1, 1'h0) COMMAND_REG0 283 | ( .data_in(data_in[0]), 284 | .data_out(command[0]), 285 | .we(we_command), 286 | .clk(clk), 287 | .rst(rst), 288 | .rst_sync(command[0] & sample_point | reset_mode) 289 | ); 290 | 291 | can_register_asyn_syn #(1, 1'h0) COMMAND_REG1 292 | ( .data_in(data_in[1]), 293 | .data_out(command[1]), 294 | .we(we_command), 295 | .clk(clk), 296 | .rst(rst), 297 | .rst_sync(sample_point & (tx_request | (abort_tx & ~transmitting)) | reset_mode) 298 | ); 299 | 300 | can_register_asyn_syn #(2, 2'h0) COMMAND_REG 301 | ( .data_in(data_in[3:2]), 302 | .data_out(command[3:2]), 303 | .we(we_command), 304 | .clk(clk), 305 | .rst(rst), 306 | .rst_sync(|command[3:2] | reset_mode) 307 | ); 308 | 309 | can_register_asyn_syn #(1, 1'h0) COMMAND_REG4 310 | ( .data_in(data_in[4]), 311 | .data_out(command[4]), 312 | .we(we_command), 313 | .clk(clk), 314 | .rst(rst), 315 | .rst_sync(command[4] & sample_point | reset_mode) 316 | ); 317 | 318 | always @(posedge clk or posedge rst) begin 319 | if(rst) begin 320 | self_rx_request <= 1'b0; 321 | end else if(command[4] & (~command[0])) begin 322 | self_rx_request <=#Tp 1'b1; 323 | end else if((~tx_state) & tx_state_q) begin 324 | self_rx_request <=#Tp 1'b0; 325 | end 326 | end 327 | 328 | assign clear_data_overrun = command[3]; 329 | assign release_buffer = command[2]; 330 | assign tx_request = command[0] | command[4]; 331 | assign abort_tx = command[1] & (~tx_request); 332 | 333 | always @(posedge clk or posedge rst) begin 334 | if(rst) begin 335 | single_shot_transmission <= 1'b0; 336 | end else if(tx_request & command[1] & sample_point) begin 337 | single_shot_transmission <=#Tp 1'b1; 338 | end else if((~tx_state) & tx_state_q) begin 339 | single_shot_transmission <=#Tp 1'b0; 340 | end 341 | end 342 | 343 | /* 344 | can_register_asyn_syn #(1, 1'h0) COMMAND_REG_OVERLOAD // Uncomment this to enable overload requests !!! 345 | ( .data_in(data_in[5]), 346 | .data_out(overload_request), 347 | .we(we_command), 348 | .clk(clk), 349 | .rst(rst), 350 | .rst_sync(overload_frame & ~overload_frame_q) 351 | ); 352 | 353 | reg overload_frame_q; 354 | 355 | always @(posedge clk or posedge rst) begin 356 | if(rst) begin 357 | overload_frame_q <= 1'b0; 358 | end else begin 359 | overload_frame_q <=#Tp overload_frame; 360 | end 361 | end 362 | */ 363 | 364 | assign overload_request = 0; // Overload requests are not supported, yet !!! 365 | 366 | /* End Command register */ 367 | 368 | /* Status register */ 369 | 370 | wire [7:0] status; 371 | 372 | assign status[7] = node_bus_off; 373 | assign status[6] = error_status; 374 | assign status[5] = transmit_status; 375 | assign status[4] = receive_status; 376 | assign status[3] = transmission_complete; 377 | assign status[2] = transmit_buffer_status; 378 | assign status[1] = overrun_status; 379 | assign status[0] = receive_buffer_status; 380 | 381 | always @(posedge clk or posedge rst) begin 382 | if(rst) begin 383 | transmission_complete <= 1'b1; 384 | end else if(tx_successful & (~tx_successful_q) | abort_tx) begin 385 | transmission_complete <=#Tp 1'b1; 386 | end else if(tx_request) begin 387 | transmission_complete <=#Tp 1'b0; 388 | end 389 | end 390 | 391 | always @(posedge clk or posedge rst) begin 392 | if(rst) begin 393 | transmit_buffer_status <= 1'b1; 394 | end else if(tx_request) begin 395 | transmit_buffer_status <=#Tp 1'b0; 396 | end else if(reset_mode || !need_to_tx) begin 397 | transmit_buffer_status <=#Tp 1'b1; 398 | end 399 | end 400 | 401 | always @(posedge clk or posedge rst) begin 402 | if(rst) begin 403 | overrun_status <= 1'b0; 404 | end else if(overrun & (~overrun_q)) begin 405 | overrun_status <=#Tp 1'b1; 406 | end else if(reset_mode || clear_data_overrun) begin 407 | overrun_status <=#Tp 1'b0; 408 | end 409 | end 410 | 411 | always @(posedge clk or posedge rst) begin 412 | if(rst) begin 413 | receive_buffer_status <= 1'b0; 414 | end else if(reset_mode || release_buffer) begin 415 | receive_buffer_status <=#Tp 1'b0; 416 | end else if(~info_empty) begin 417 | receive_buffer_status <=#Tp 1'b1; 418 | end 419 | end 420 | 421 | /* End Status register */ 422 | 423 | /* Interrupt Enable register (extended mode) */ 424 | wire [7:0] irq_en_ext; 425 | wire bus_error_irq_en; 426 | wire arbitration_lost_irq_en; 427 | wire error_passive_irq_en; 428 | wire data_overrun_irq_en_ext; 429 | wire error_warning_irq_en_ext; 430 | wire transmit_irq_en_ext; 431 | wire receive_irq_en_ext; 432 | 433 | can_register #(8) IRQ_EN_REG 434 | ( .data_in(data_in), 435 | .data_out(irq_en_ext), 436 | .we(we_interrupt_enable), 437 | .clk(clk) 438 | ); 439 | 440 | assign bus_error_irq_en = irq_en_ext[7]; 441 | assign arbitration_lost_irq_en = irq_en_ext[6]; 442 | assign error_passive_irq_en = irq_en_ext[5]; 443 | assign data_overrun_irq_en_ext = irq_en_ext[3]; 444 | assign error_warning_irq_en_ext = irq_en_ext[2]; 445 | assign transmit_irq_en_ext = irq_en_ext[1]; 446 | assign receive_irq_en_ext = irq_en_ext[0]; 447 | /* End Bus Timing 0 register */ 448 | 449 | /* Bus Timing 0 register */ 450 | wire [7:0] bus_timing_0; 451 | can_register #(8) BUS_TIMING_0_REG 452 | ( .data_in(data_in), 453 | .data_out(bus_timing_0), 454 | .we(we_bus_timing_0), 455 | .clk(clk) 456 | ); 457 | 458 | assign baud_r_presc = bus_timing_0[5:0]; 459 | assign sync_jump_width = bus_timing_0[7:6]; 460 | /* End Bus Timing 0 register */ 461 | 462 | /* Bus Timing 1 register */ 463 | wire [7:0] bus_timing_1; 464 | can_register #(8) BUS_TIMING_1_REG 465 | ( .data_in(data_in), 466 | .data_out(bus_timing_1), 467 | .we(we_bus_timing_1), 468 | .clk(clk) 469 | ); 470 | 471 | assign time_segment1 = bus_timing_1[3:0]; 472 | assign time_segment2 = bus_timing_1[6:4]; 473 | assign triple_sampling = bus_timing_1[7]; 474 | /* End Bus Timing 1 register */ 475 | 476 | /* Error Warning Limit register */ 477 | can_register_asyn #(8, 96) ERROR_WARNING_REG 478 | ( .data_in(data_in), 479 | .data_out(error_warning_limit), 480 | .we(we_error_warning_limit), 481 | .clk(clk), 482 | .rst(rst) 483 | ); 484 | /* End Error Warning Limit register */ 485 | 486 | /* Clock Divider register */ 487 | wire [7:0] clock_divider; 488 | wire clock_off; 489 | wire [2:0] cd; 490 | reg [2:0] clkout_div; 491 | reg [2:0] clkout_cnt; 492 | reg clkout_tmp; 493 | 494 | can_register_asyn #(1, 0) CLOCK_DIVIDER_REG_7 495 | ( .data_in(data_in[7]), 496 | .data_out(clock_divider[7]), 497 | .we(we_clock_divider_hi), 498 | .clk(clk), 499 | .rst(rst) 500 | ); 501 | 502 | assign clock_divider[6:4] = 3'h0; 503 | 504 | can_register_asyn #(1, 0) CLOCK_DIVIDER_REG_3 505 | ( .data_in(data_in[3]), 506 | .data_out(clock_divider[3]), 507 | .we(we_clock_divider_hi), 508 | .clk(clk), 509 | .rst(rst) 510 | ); 511 | 512 | can_register_asyn #(3, 0) CLOCK_DIVIDER_REG_LOW 513 | ( .data_in(data_in[2:0]), 514 | .data_out(clock_divider[2:0]), 515 | .we(we_clock_divider_low), 516 | .clk(clk), 517 | .rst(rst) 518 | ); 519 | 520 | assign extended_mode = clock_divider[7]; 521 | assign clock_off = clock_divider[3]; 522 | assign cd[2:0] = clock_divider[2:0]; 523 | 524 | always @(cd) begin 525 | case (cd) /* synthesis full_case parallel_case */ 526 | 3'b000 : clkout_div = 3'd0; 527 | 3'b001 : clkout_div = 3'd1; 528 | 3'b010 : clkout_div = 3'd2; 529 | 3'b011 : clkout_div = 3'd3; 530 | 3'b100 : clkout_div = 3'd4; 531 | 3'b101 : clkout_div = 3'd5; 532 | 3'b110 : clkout_div = 3'd6; 533 | 3'b111 : clkout_div = 3'd0; 534 | endcase 535 | end 536 | 537 | always @(posedge clk or posedge rst) begin 538 | if(rst) begin 539 | clkout_cnt <= 3'h0; 540 | end else if(clkout_cnt == clkout_div) begin 541 | clkout_cnt <=#Tp 3'h0; 542 | end else begin 543 | clkout_cnt <= clkout_cnt + 1'b1; 544 | end 545 | end 546 | 547 | always @(posedge clk or posedge rst) begin 548 | if(rst) begin 549 | clkout_tmp <= 1'b0; 550 | end else if(clkout_cnt == clkout_div) begin 551 | clkout_tmp <=#Tp ~clkout_tmp; 552 | end 553 | end 554 | 555 | assign clkout = clock_off ? 1'b1 : ((&cd)? clk : clkout_tmp); 556 | 557 | /* End Clock Divider register */ 558 | 559 | 560 | /* This section is for BASIC and EXTENDED mode */ 561 | 562 | /* Acceptance code register */ 563 | can_register #(8) ACCEPTANCE_CODE_REG0 564 | ( .data_in(data_in), 565 | .data_out(acceptance_code_0), 566 | .we(we_acceptance_code_0), 567 | .clk(clk) 568 | ); 569 | /* End: Acceptance code register */ 570 | 571 | 572 | /* Acceptance mask register */ 573 | can_register #(8) ACCEPTANCE_MASK_REG0 574 | ( .data_in(data_in), 575 | .data_out(acceptance_mask_0), 576 | .we(we_acceptance_mask_0), 577 | .clk(clk) 578 | ); 579 | /* End: Acceptance mask register */ 580 | /* End: This section is for BASIC and EXTENDED mode */ 581 | 582 | 583 | /* Tx data 0 register. */ 584 | can_register #(8) TX_DATA_REG0 585 | ( .data_in(data_in), 586 | .data_out(tx_data_0), 587 | .we(we_tx_data_0), 588 | .clk(clk) 589 | ); 590 | /* End: Tx data 0 register. */ 591 | 592 | /* Tx data 1 register. */ 593 | can_register #(8) TX_DATA_REG1 594 | ( .data_in(data_in), 595 | .data_out(tx_data_1), 596 | .we(we_tx_data_1), 597 | .clk(clk) 598 | ); 599 | /* End: Tx data 1 register. */ 600 | 601 | /* Tx data 2 register. */ 602 | can_register #(8) TX_DATA_REG2 603 | ( .data_in(data_in), 604 | .data_out(tx_data_2), 605 | .we(we_tx_data_2), 606 | .clk(clk) 607 | ); 608 | /* End: Tx data 2 register. */ 609 | 610 | /* Tx data 3 register. */ 611 | can_register #(8) TX_DATA_REG3 612 | ( .data_in(data_in), 613 | .data_out(tx_data_3), 614 | .we(we_tx_data_3), 615 | .clk(clk) 616 | ); 617 | /* End: Tx data 3 register. */ 618 | 619 | /* Tx data 4 register. */ 620 | can_register #(8) TX_DATA_REG4 621 | ( .data_in(data_in), 622 | .data_out(tx_data_4), 623 | .we(we_tx_data_4), 624 | .clk(clk) 625 | ); 626 | /* End: Tx data 4 register. */ 627 | 628 | /* Tx data 5 register. */ 629 | can_register #(8) TX_DATA_REG5 630 | ( .data_in(data_in), 631 | .data_out(tx_data_5), 632 | .we(we_tx_data_5), 633 | .clk(clk) 634 | ); 635 | /* End: Tx data 5 register. */ 636 | 637 | /* Tx data 6 register. */ 638 | can_register #(8) TX_DATA_REG6 639 | ( .data_in(data_in), 640 | .data_out(tx_data_6), 641 | .we(we_tx_data_6), 642 | .clk(clk) 643 | ); 644 | /* End: Tx data 6 register. */ 645 | 646 | /* Tx data 7 register. */ 647 | can_register #(8) TX_DATA_REG7 648 | ( .data_in(data_in), 649 | .data_out(tx_data_7), 650 | .we(we_tx_data_7), 651 | .clk(clk) 652 | ); 653 | /* End: Tx data 7 register. */ 654 | 655 | /* Tx data 8 register. */ 656 | can_register #(8) TX_DATA_REG8 657 | ( .data_in(data_in), 658 | .data_out(tx_data_8), 659 | .we(we_tx_data_8), 660 | .clk(clk) 661 | ); 662 | /* End: Tx data 8 register. */ 663 | 664 | /* Tx data 9 register. */ 665 | can_register #(8) TX_DATA_REG9 666 | ( .data_in(data_in), 667 | .data_out(tx_data_9), 668 | .we(we_tx_data_9), 669 | .clk(clk) 670 | ); 671 | /* End: Tx data 9 register. */ 672 | 673 | /* Tx data 10 register. */ 674 | can_register #(8) TX_DATA_REG10 675 | ( .data_in(data_in), 676 | .data_out(tx_data_10), 677 | .we(we_tx_data_10), 678 | .clk(clk) 679 | ); 680 | /* End: Tx data 10 register. */ 681 | 682 | /* Tx data 11 register. */ 683 | can_register #(8) TX_DATA_REG11 684 | ( .data_in(data_in), 685 | .data_out(tx_data_11), 686 | .we(we_tx_data_11), 687 | .clk(clk) 688 | ); 689 | /* End: Tx data 11 register. */ 690 | 691 | /* Tx data 12 register. */ 692 | can_register #(8) TX_DATA_REG12 693 | ( .data_in(data_in), 694 | .data_out(tx_data_12), 695 | .we(we_tx_data_12), 696 | .clk(clk) 697 | ); 698 | /* End: Tx data 12 register. */ 699 | 700 | 701 | 702 | /* This section is for EXTENDED mode */ 703 | 704 | /* Acceptance code register 1 */ 705 | can_register #(8) ACCEPTANCE_CODE_REG1 706 | ( .data_in(data_in), 707 | .data_out(acceptance_code_1), 708 | .we(we_acceptance_code_1), 709 | .clk(clk) 710 | ); 711 | /* End: Acceptance code register */ 712 | 713 | /* Acceptance code register 2 */ 714 | can_register #(8) ACCEPTANCE_CODE_REG2 715 | ( .data_in(data_in), 716 | .data_out(acceptance_code_2), 717 | .we(we_acceptance_code_2), 718 | .clk(clk) 719 | ); 720 | /* End: Acceptance code register */ 721 | 722 | /* Acceptance code register 3 */ 723 | can_register #(8) ACCEPTANCE_CODE_REG3 724 | ( .data_in(data_in), 725 | .data_out(acceptance_code_3), 726 | .we(we_acceptance_code_3), 727 | .clk(clk) 728 | ); 729 | /* End: Acceptance code register */ 730 | 731 | /* Acceptance mask register 1 */ 732 | can_register #(8) ACCEPTANCE_MASK_REG1 733 | ( .data_in(data_in), 734 | .data_out(acceptance_mask_1), 735 | .we(we_acceptance_mask_1), 736 | .clk(clk) 737 | ); 738 | /* End: Acceptance code register */ 739 | 740 | /* Acceptance mask register 2 */ 741 | can_register #(8) ACCEPTANCE_MASK_REG2 742 | ( .data_in(data_in), 743 | .data_out(acceptance_mask_2), 744 | .we(we_acceptance_mask_2), 745 | .clk(clk) 746 | ); 747 | /* End: Acceptance code register */ 748 | 749 | /* Acceptance mask register 3 */ 750 | can_register #(8) ACCEPTANCE_MASK_REG3 751 | ( .data_in(data_in), 752 | .data_out(acceptance_mask_3), 753 | .we(we_acceptance_mask_3), 754 | .clk(clk) 755 | ); 756 | /* End: Acceptance code register */ 757 | 758 | 759 | /* End: This section is for EXTENDED mode */ 760 | 761 | // Reading data from registers 762 | always @( addr or extended_mode or mode or bus_timing_0 or bus_timing_1 or clock_divider or 763 | acceptance_code_0 or acceptance_code_1 or acceptance_code_2 or acceptance_code_3 or 764 | acceptance_mask_0 or acceptance_mask_1 or acceptance_mask_2 or acceptance_mask_3 or 765 | reset_mode or tx_data_0 or tx_data_1 or tx_data_2 or tx_data_3 or tx_data_4 or 766 | tx_data_5 or tx_data_6 or tx_data_7 or tx_data_8 or tx_data_9 or status or 767 | error_warning_limit or rx_err_cnt or tx_err_cnt or irq_en_ext or irq_reg or mode_ext or 768 | arbitration_lost_capture or rx_message_counter or mode_basic or error_capture_code 769 | ) begin 770 | case({extended_mode, addr[4:0]}) /* synthesis parallel_case */ 771 | {1'h1, 5'd00} : data_out = {4'b0000, mode_ext[3:1], mode[0]}; // extended mode 772 | {1'h1, 5'd01} : data_out = 8'h0; // extended mode 773 | {1'h1, 5'd02} : data_out = status; // extended mode 774 | {1'h1, 5'd03} : data_out = irq_reg; // extended mode 775 | {1'h1, 5'd04} : data_out = irq_en_ext; // extended mode 776 | {1'h1, 5'd06} : data_out = bus_timing_0; // extended mode 777 | {1'h1, 5'd07} : data_out = bus_timing_1; // extended mode 778 | {1'h1, 5'd11} : data_out = {3'h0, arbitration_lost_capture[4:0]}; // extended mode 779 | {1'h1, 5'd12} : data_out = error_capture_code; // extended mode 780 | {1'h1, 5'd13} : data_out = error_warning_limit; // extended mode 781 | {1'h1, 5'd14} : data_out = rx_err_cnt; // extended mode 782 | {1'h1, 5'd15} : data_out = tx_err_cnt; // extended mode 783 | {1'h1, 5'd16} : data_out = acceptance_code_0; // extended mode 784 | {1'h1, 5'd17} : data_out = acceptance_code_1; // extended mode 785 | {1'h1, 5'd18} : data_out = acceptance_code_2; // extended mode 786 | {1'h1, 5'd19} : data_out = acceptance_code_3; // extended mode 787 | {1'h1, 5'd20} : data_out = acceptance_mask_0; // extended mode 788 | {1'h1, 5'd21} : data_out = acceptance_mask_1; // extended mode 789 | {1'h1, 5'd22} : data_out = acceptance_mask_2; // extended mode 790 | {1'h1, 5'd23} : data_out = acceptance_mask_3; // extended mode 791 | {1'h1, 5'd24} : data_out = 8'h0; // extended mode 792 | {1'h1, 5'd25} : data_out = 8'h0; // extended mode 793 | {1'h1, 5'd26} : data_out = 8'h0; // extended mode 794 | {1'h1, 5'd27} : data_out = 8'h0; // extended mode 795 | {1'h1, 5'd28} : data_out = 8'h0; // extended mode 796 | {1'h1, 5'd29} : data_out = {1'b0, rx_message_counter}; // extended mode 797 | {1'h1, 5'd31} : data_out = clock_divider; // extended mode 798 | {1'h0, 5'd00} : data_out = {3'b001, mode_basic[4:1], mode[0]}; // basic mode 799 | {1'h0, 5'd01} : data_out = 8'hff; // basic mode 800 | {1'h0, 5'd02} : data_out = status; // basic mode 801 | {1'h0, 5'd03} : data_out = {4'he, irq_reg[3:0]}; // basic mode 802 | {1'h0, 5'd04} : data_out = reset_mode? acceptance_code_0 : 8'hff; // basic mode 803 | {1'h0, 5'd05} : data_out = reset_mode? acceptance_mask_0 : 8'hff; // basic mode 804 | {1'h0, 5'd06} : data_out = reset_mode? bus_timing_0 : 8'hff; // basic mode 805 | {1'h0, 5'd07} : data_out = reset_mode? bus_timing_1 : 8'hff; // basic mode 806 | {1'h0, 5'd10} : data_out = reset_mode? 8'hff : tx_data_0; // basic mode 807 | {1'h0, 5'd11} : data_out = reset_mode? 8'hff : tx_data_1; // basic mode 808 | {1'h0, 5'd12} : data_out = reset_mode? 8'hff : tx_data_2; // basic mode 809 | {1'h0, 5'd13} : data_out = reset_mode? 8'hff : tx_data_3; // basic mode 810 | {1'h0, 5'd14} : data_out = reset_mode? 8'hff : tx_data_4; // basic mode 811 | {1'h0, 5'd15} : data_out = reset_mode? 8'hff : tx_data_5; // basic mode 812 | {1'h0, 5'd16} : data_out = reset_mode? 8'hff : tx_data_6; // basic mode 813 | {1'h0, 5'd17} : data_out = reset_mode? 8'hff : tx_data_7; // basic mode 814 | {1'h0, 5'd18} : data_out = reset_mode? 8'hff : tx_data_8; // basic mode 815 | {1'h0, 5'd19} : data_out = reset_mode? 8'hff : tx_data_9; // basic mode 816 | {1'h0, 5'd31} : data_out = clock_divider; // basic mode 817 | default : data_out = 8'h0; // the rest is read as 0 818 | endcase 819 | end 820 | 821 | // Some interrupts exist in basic mode and in extended mode. Since they are in different registers they need to be multiplexed. 822 | assign data_overrun_irq_en = extended_mode ? data_overrun_irq_en_ext : overrun_irq_en_basic; 823 | assign error_warning_irq_en = extended_mode ? error_warning_irq_en_ext : error_irq_en_basic; 824 | assign transmit_irq_en = extended_mode ? transmit_irq_en_ext : transmit_irq_en_basic; 825 | assign receive_irq_en = extended_mode ? receive_irq_en_ext : receive_irq_en_basic; 826 | 827 | reg data_overrun_irq; 828 | always @(posedge clk or posedge rst) begin 829 | if(rst) begin 830 | data_overrun_irq <= 1'b0; 831 | end else if(overrun & (~overrun_q) & data_overrun_irq_en) begin 832 | data_overrun_irq <=#Tp 1'b1; 833 | end else if(reset_mode || read_irq_reg) begin 834 | data_overrun_irq <=#Tp 1'b0; 835 | end 836 | end 837 | 838 | reg transmit_irq; 839 | always @(posedge clk or posedge rst) begin 840 | if(rst) begin 841 | transmit_irq <= 1'b0; 842 | end else if(reset_mode || read_irq_reg) begin 843 | transmit_irq <=#Tp 1'b0; 844 | end else if(transmit_buffer_status & (~transmit_buffer_status_q) & transmit_irq_en) begin 845 | transmit_irq <=#Tp 1'b1; 846 | end 847 | end 848 | 849 | reg receive_irq; 850 | always @(posedge clk or posedge rst) begin 851 | if(rst) begin 852 | receive_irq <= 1'b0; 853 | end else if((~info_empty) & (~receive_irq) & receive_irq_en) begin 854 | receive_irq <=#Tp 1'b1; 855 | end else if(reset_mode || release_buffer) begin 856 | receive_irq <=#Tp 1'b0; 857 | end 858 | end 859 | 860 | reg error_irq; 861 | always @(posedge clk or posedge rst) begin 862 | if(rst) begin 863 | error_irq <= 1'b0; 864 | end else if(((error_status ^ error_status_q) | (node_bus_off ^ node_bus_off_q)) & error_warning_irq_en) begin 865 | error_irq <=#Tp 1'b1; 866 | end else if(read_irq_reg) begin 867 | error_irq <=#Tp 1'b0; 868 | end 869 | end 870 | 871 | reg bus_error_irq; 872 | always @(posedge clk or posedge rst) begin 873 | if(rst) begin 874 | bus_error_irq <= 1'b0; 875 | end else if(set_bus_error_irq & bus_error_irq_en) begin 876 | bus_error_irq <=#Tp 1'b1; 877 | end else if(reset_mode || read_irq_reg) begin 878 | bus_error_irq <=#Tp 1'b0; 879 | end 880 | end 881 | 882 | reg arbitration_lost_irq; 883 | always @(posedge clk or posedge rst) begin 884 | if(rst) begin 885 | arbitration_lost_irq <= 1'b0; 886 | end else if(set_arbitration_lost_irq & arbitration_lost_irq_en) begin 887 | arbitration_lost_irq <=#Tp 1'b1; 888 | end else if(reset_mode || read_irq_reg) begin 889 | arbitration_lost_irq <=#Tp 1'b0; 890 | end 891 | end 892 | 893 | reg error_passive_irq; 894 | always @(posedge clk or posedge rst) begin 895 | if(rst) begin 896 | error_passive_irq <= 1'b0; 897 | end else if((node_error_passive & (~node_error_passive_q) | (~node_error_passive) & node_error_passive_q & node_error_active) & error_passive_irq_en) begin 898 | error_passive_irq <=#Tp 1'b1; 899 | end else if(reset_mode || read_irq_reg) begin 900 | error_passive_irq <=#Tp 1'b0; 901 | end 902 | end 903 | 904 | assign irq_reg = {bus_error_irq, arbitration_lost_irq, error_passive_irq, 1'b0, data_overrun_irq, error_irq, transmit_irq, receive_irq}; 905 | 906 | assign irq = data_overrun_irq | transmit_irq | receive_irq | error_irq | bus_error_irq | arbitration_lost_irq | error_passive_irq; 907 | 908 | always @(posedge clk or posedge rst) begin 909 | if(rst) begin 910 | irq_n <= 1'b1; 911 | end else if(read_irq_reg || release_buffer) begin 912 | irq_n <=#Tp 1'b1; 913 | end else if(irq) begin 914 | irq_n <=#Tp 1'b0; 915 | end 916 | end 917 | 918 | endmodule 919 | 920 | -------------------------------------------------------------------------------- /can_top.v: -------------------------------------------------------------------------------- 1 | /* vim: colorcolumn=80 2 | * 3 | * This file is part of a verilog CAN controller that is SJA1000 compatible. 4 | * 5 | * Authors: 6 | * * Igor Mohor 7 | * Author of the original version at 8 | * http://www.opencores.org/projects/can/ 9 | * (which has been unmaintained since about 2009) 10 | * 11 | * * David Piegdon 12 | * Picked up project for cleanup and bugfixes in 2019 13 | * 14 | * Any additional information is available in the LICENSE file. 15 | * 16 | * Copyright (C) 2002, 2003, 2004, 2019 Authors 17 | * 18 | * This source file may be used and distributed without restriction provided 19 | * that this copyright statement is not removed from the file and that any 20 | * derivative work contains the original copyright notice and the associated 21 | * disclaimer. 22 | * 23 | * This source file is free software; you can redistribute it and/or modify it 24 | * under the terms of the GNU Lesser General Public License as published by the 25 | * Free Software Foundation; either version 2.1 of the License, or (at your 26 | * option) any later version. 27 | * 28 | * This source is distributed in the hope that it will be useful, but WITHOUT 29 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 30 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 31 | * details. 32 | * 33 | * You should have received a copy of the GNU Lesser General Public License 34 | * along with this source; if not, download it from 35 | * http://www.opencores.org/lgpl.shtml 36 | * 37 | * The CAN protocol is developed by Robert Bosch GmbH and protected by patents. 38 | * Anybody who wants to implement this CAN IP core on silicon has to obtain 39 | * a CAN protocol license from Bosch. 40 | */ 41 | 42 | `default_nettype none 43 | 44 | `include "can_top_defines.v" 45 | `include "can_registers.v" 46 | `include "can_btl.v" 47 | `include "can_bsp.v" 48 | 49 | /* 50 | * Internal CAN controller implementation, 51 | * without an explicit bus adapter. 52 | */ 53 | 54 | module can_controller( 55 | input wire rst_i, 56 | input wire cs_i, 57 | input wire we_i, 58 | input wire [7:0] addr_i, 59 | input wire [7:0] data_i, 60 | output reg [7:0] data_o, 61 | 62 | input wire clk_i, 63 | input wire rx_i, 64 | output wire tx_o, 65 | output wire bus_off_on_o, 66 | output wire irq_n_o, 67 | output wire clkout_o 68 | 69 | `ifdef CAN_BIST 70 | , 71 | input wire mbist_si_i, // bist scan serial in 72 | output wire mbist_so_o, // bist scan serial out 73 | input wire [`CAN_MBIST_CTRL_WIDTH - 1:0] mbist_ctrl_i // bist chain shift control 74 | `endif 75 | ); 76 | 77 | parameter Tp = 1; 78 | 79 | reg data_out_fifo_selected; 80 | 81 | wire [7:0] data_out_fifo; 82 | wire [7:0] data_out_regs; 83 | 84 | /* Mode register */ 85 | wire reset_mode; 86 | wire listen_only_mode; 87 | wire acceptance_filter_mode; 88 | wire self_test_mode; 89 | 90 | /* Command register */ 91 | wire release_buffer; 92 | wire tx_request; 93 | wire abort_tx; 94 | wire self_rx_request; 95 | wire single_shot_transmission; 96 | wire tx_state; 97 | wire tx_state_q; 98 | wire overload_request; 99 | wire overload_frame; 100 | 101 | /* Arbitration Lost Capture Register */ 102 | wire read_arbitration_lost_capture_reg; 103 | 104 | /* Error Code Capture Register */ 105 | wire read_error_code_capture_reg; 106 | wire [7:0] error_capture_code; 107 | 108 | /* Bus Timing 0 register */ 109 | wire [5:0] baud_r_presc; 110 | wire [1:0] sync_jump_width; 111 | 112 | /* Bus Timing 1 register */ 113 | wire [3:0] time_segment1; 114 | wire [2:0] time_segment2; 115 | wire triple_sampling; 116 | 117 | /* Error Warning Limit register */ 118 | wire [7:0] error_warning_limit; 119 | 120 | /* Rx Error Counter register */ 121 | wire we_rx_err_cnt; 122 | 123 | /* Tx Error Counter register */ 124 | wire we_tx_err_cnt; 125 | 126 | /* Clock Divider register */ 127 | wire extended_mode; 128 | 129 | /* This section is for BASIC and EXTENDED mode */ 130 | /* Acceptance code register */ 131 | wire [7:0] acceptance_code_0; 132 | 133 | /* Acceptance mask register */ 134 | wire [7:0] acceptance_mask_0; 135 | /* End: This section is for BASIC and EXTENDED mode */ 136 | 137 | /* This section is for EXTENDED mode */ 138 | /* Acceptance code register */ 139 | wire [7:0] acceptance_code_1; 140 | wire [7:0] acceptance_code_2; 141 | wire [7:0] acceptance_code_3; 142 | 143 | /* Acceptance mask register */ 144 | wire [7:0] acceptance_mask_1; 145 | wire [7:0] acceptance_mask_2; 146 | wire [7:0] acceptance_mask_3; 147 | /* End: This section is for EXTENDED mode */ 148 | 149 | /* Tx data registers. Holding identifier (basic mode), tx frame information (extended mode) and data */ 150 | wire [7:0] tx_data_0; 151 | wire [7:0] tx_data_1; 152 | wire [7:0] tx_data_2; 153 | wire [7:0] tx_data_3; 154 | wire [7:0] tx_data_4; 155 | wire [7:0] tx_data_5; 156 | wire [7:0] tx_data_6; 157 | wire [7:0] tx_data_7; 158 | wire [7:0] tx_data_8; 159 | wire [7:0] tx_data_9; 160 | wire [7:0] tx_data_10; 161 | wire [7:0] tx_data_11; 162 | wire [7:0] tx_data_12; 163 | /* End: Tx data registers */ 164 | 165 | /* Output signals from can_btl module */ 166 | wire sample_point; 167 | wire sampled_bit; 168 | wire sampled_bit_q; 169 | wire tx_point; 170 | wire hard_sync; 171 | 172 | /* output from can_bsp module */ 173 | wire rx_idle; 174 | wire transmitting; 175 | wire transmitter; 176 | wire go_rx_inter; 177 | wire not_first_bit_of_inter; 178 | wire set_reset_mode; 179 | wire node_bus_off; 180 | wire error_status; 181 | wire [7:0] rx_err_cnt; 182 | wire [7:0] tx_err_cnt; 183 | wire rx_err_cnt_dummy; // The MSB is not displayed. It is just used for easier calculation (no counter overflow). 184 | wire tx_err_cnt_dummy; // The MSB is not displayed. It is just used for easier calculation (no counter overflow). 185 | wire transmit_status; 186 | wire receive_status; 187 | wire tx_successful; 188 | wire need_to_tx; 189 | wire overrun; 190 | wire info_empty; 191 | wire set_bus_error_irq; 192 | wire set_arbitration_lost_irq; 193 | wire [4:0] arbitration_lost_capture; 194 | wire node_error_passive; 195 | wire node_error_active; 196 | wire [6:0] rx_message_counter; 197 | wire tx_next; 198 | 199 | wire go_overload_frame; 200 | wire go_error_frame; 201 | wire go_tx; 202 | wire send_ack; 203 | 204 | reg rx_sync_tmp; 205 | reg rx_sync; 206 | 207 | /* Connecting can_registers module */ 208 | can_registers i_can_registers 209 | ( 210 | .clk(clk_i), 211 | .rst(rst_i), 212 | .cs(cs_i), 213 | .we(we_i), 214 | .addr(addr_i), 215 | .data_in(data_i), 216 | .data_out(data_out_regs), 217 | .irq_n(irq_n_o), 218 | 219 | .sample_point(sample_point), 220 | .transmitting(transmitting), 221 | .set_reset_mode(set_reset_mode), 222 | .node_bus_off(node_bus_off), 223 | .error_status(error_status), 224 | .rx_err_cnt(rx_err_cnt), 225 | .tx_err_cnt(tx_err_cnt), 226 | .transmit_status(transmit_status), 227 | .receive_status(receive_status), 228 | .tx_successful(tx_successful), 229 | .need_to_tx(need_to_tx), 230 | .overrun(overrun), 231 | .info_empty(info_empty), 232 | .set_bus_error_irq(set_bus_error_irq), 233 | .set_arbitration_lost_irq(set_arbitration_lost_irq), 234 | .arbitration_lost_capture(arbitration_lost_capture), 235 | .node_error_passive(node_error_passive), 236 | .node_error_active(node_error_active), 237 | .rx_message_counter(rx_message_counter), 238 | 239 | /* Mode register */ 240 | .reset_mode(reset_mode), 241 | .listen_only_mode(listen_only_mode), 242 | .acceptance_filter_mode(acceptance_filter_mode), 243 | .self_test_mode(self_test_mode), 244 | 245 | /* Command register */ 246 | .clear_data_overrun(), 247 | .release_buffer(release_buffer), 248 | .abort_tx(abort_tx), 249 | .tx_request(tx_request), 250 | .self_rx_request(self_rx_request), 251 | .single_shot_transmission(single_shot_transmission), 252 | .tx_state(tx_state), 253 | .tx_state_q(tx_state_q), 254 | .overload_request(overload_request), 255 | .overload_frame(overload_frame), 256 | 257 | /* Arbitration Lost Capture Register */ 258 | .read_arbitration_lost_capture_reg(read_arbitration_lost_capture_reg), 259 | 260 | /* Error Code Capture Register */ 261 | .read_error_code_capture_reg(read_error_code_capture_reg), 262 | .error_capture_code(error_capture_code), 263 | 264 | /* Bus Timing 0 register */ 265 | .baud_r_presc(baud_r_presc), 266 | .sync_jump_width(sync_jump_width), 267 | 268 | /* Bus Timing 1 register */ 269 | .time_segment1(time_segment1), 270 | .time_segment2(time_segment2), 271 | .triple_sampling(triple_sampling), 272 | 273 | /* Error Warning Limit register */ 274 | .error_warning_limit(error_warning_limit), 275 | 276 | /* Rx Error Counter register */ 277 | .we_rx_err_cnt(we_rx_err_cnt), 278 | 279 | /* Tx Error Counter register */ 280 | .we_tx_err_cnt(we_tx_err_cnt), 281 | 282 | /* Clock Divider register */ 283 | .extended_mode(extended_mode), 284 | .clkout(clkout_o), 285 | 286 | /* This section is for BASIC and EXTENDED mode */ 287 | /* Acceptance code register */ 288 | .acceptance_code_0(acceptance_code_0), 289 | 290 | /* Acceptance mask register */ 291 | .acceptance_mask_0(acceptance_mask_0), 292 | /* End: This section is for BASIC and EXTENDED mode */ 293 | 294 | /* This section is for EXTENDED mode */ 295 | /* Acceptance code register */ 296 | .acceptance_code_1(acceptance_code_1), 297 | .acceptance_code_2(acceptance_code_2), 298 | .acceptance_code_3(acceptance_code_3), 299 | 300 | /* Acceptance mask register */ 301 | .acceptance_mask_1(acceptance_mask_1), 302 | .acceptance_mask_2(acceptance_mask_2), 303 | .acceptance_mask_3(acceptance_mask_3), 304 | /* End: This section is for EXTENDED mode */ 305 | 306 | /* Tx data registers. Holding identifier (basic mode), tx frame information (extended mode) and data */ 307 | .tx_data_0(tx_data_0), 308 | .tx_data_1(tx_data_1), 309 | .tx_data_2(tx_data_2), 310 | .tx_data_3(tx_data_3), 311 | .tx_data_4(tx_data_4), 312 | .tx_data_5(tx_data_5), 313 | .tx_data_6(tx_data_6), 314 | .tx_data_7(tx_data_7), 315 | .tx_data_8(tx_data_8), 316 | .tx_data_9(tx_data_9), 317 | .tx_data_10(tx_data_10), 318 | .tx_data_11(tx_data_11), 319 | .tx_data_12(tx_data_12) 320 | /* End: Tx data registers */ 321 | ); 322 | 323 | /* some interconnect signal from BSP to BTL */ 324 | wire rx_inter; 325 | 326 | /* Connecting can_btl module */ 327 | can_btl i_can_btl 328 | ( 329 | .clk(clk_i), 330 | .rst(rst_i), 331 | .rx(rx_sync), 332 | .tx(tx_o), 333 | 334 | /* Bus Timing 0 register */ 335 | .baud_r_presc(baud_r_presc), 336 | .sync_jump_width(sync_jump_width), 337 | 338 | /* Bus Timing 1 register */ 339 | .time_segment1(time_segment1), 340 | .time_segment2(time_segment2), 341 | .triple_sampling(triple_sampling), 342 | 343 | /* Output signals from this module */ 344 | .sample_point(sample_point), 345 | .sampled_bit(sampled_bit), 346 | .sampled_bit_q(sampled_bit_q), 347 | .tx_point(tx_point), 348 | .hard_sync(hard_sync), 349 | 350 | 351 | /* output from can_bsp module */ 352 | .rx_idle(rx_idle), 353 | .rx_inter(rx_inter), 354 | .transmitting(transmitting), 355 | .transmitter(transmitter), 356 | .go_rx_inter(go_rx_inter), 357 | .tx_next(tx_next), 358 | 359 | .go_overload_frame(go_overload_frame), 360 | .go_error_frame(go_error_frame), 361 | .go_tx(go_tx), 362 | .send_ack(send_ack), 363 | .node_error_passive(node_error_passive) 364 | ); 365 | 366 | can_bsp i_can_bsp 367 | ( 368 | .clk(clk_i), 369 | .rst(rst_i), 370 | 371 | /* From btl module */ 372 | .sample_point(sample_point), 373 | .sampled_bit(sampled_bit), 374 | .sampled_bit_q(sampled_bit_q), 375 | .tx_point(tx_point), 376 | .hard_sync(hard_sync), 377 | 378 | .addr(addr_i), 379 | .data_in(data_i), 380 | .data_out(data_out_fifo), 381 | .fifo_selected(data_out_fifo_selected), 382 | 383 | /* Mode register */ 384 | .reset_mode(reset_mode), 385 | .listen_only_mode(listen_only_mode), 386 | .acceptance_filter_mode(acceptance_filter_mode), 387 | .self_test_mode(self_test_mode), 388 | 389 | /* Command register */ 390 | .release_buffer(release_buffer), 391 | .tx_request(tx_request), 392 | .abort_tx(abort_tx), 393 | .self_rx_request(self_rx_request), 394 | .single_shot_transmission(single_shot_transmission), 395 | .tx_state(tx_state), 396 | .tx_state_q(tx_state_q), 397 | .overload_request(overload_request), 398 | .overload_frame(overload_frame), 399 | 400 | /* Arbitration Lost Capture Register */ 401 | .read_arbitration_lost_capture_reg(read_arbitration_lost_capture_reg), 402 | 403 | /* Error Code Capture Register */ 404 | .read_error_code_capture_reg(read_error_code_capture_reg), 405 | .error_capture_code(error_capture_code), 406 | 407 | /* Error Warning Limit register */ 408 | .error_warning_limit(error_warning_limit), 409 | 410 | /* Rx Error Counter register */ 411 | .we_rx_err_cnt(we_rx_err_cnt), 412 | 413 | /* Tx Error Counter register */ 414 | .we_tx_err_cnt(we_tx_err_cnt), 415 | 416 | /* Clock Divider register */ 417 | .extended_mode(extended_mode), 418 | 419 | /* output from can_bsp module */ 420 | .rx_idle(rx_idle), 421 | .transmitting(transmitting), 422 | .transmitter(transmitter), 423 | .go_rx_inter(go_rx_inter), 424 | .not_first_bit_of_inter(not_first_bit_of_inter), 425 | .rx_inter(rx_inter), 426 | .set_reset_mode(set_reset_mode), 427 | .node_bus_off(node_bus_off), 428 | .error_status(error_status), 429 | .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). 430 | .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). 431 | .transmit_status(transmit_status), 432 | .receive_status(receive_status), 433 | .tx_successful(tx_successful), 434 | .need_to_tx(need_to_tx), 435 | .overrun(overrun), 436 | .info_empty(info_empty), 437 | .set_bus_error_irq(set_bus_error_irq), 438 | .set_arbitration_lost_irq(set_arbitration_lost_irq), 439 | .arbitration_lost_capture(arbitration_lost_capture), 440 | .node_error_passive(node_error_passive), 441 | .node_error_active(node_error_active), 442 | .rx_message_counter(rx_message_counter), 443 | 444 | /* This section is for BASIC and EXTENDED mode */ 445 | /* Acceptance code register */ 446 | .acceptance_code_0(acceptance_code_0), 447 | 448 | /* Acceptance mask register */ 449 | .acceptance_mask_0(acceptance_mask_0), 450 | /* End: This section is for BASIC and EXTENDED mode */ 451 | 452 | /* This section is for EXTENDED mode */ 453 | /* Acceptance code register */ 454 | .acceptance_code_1(acceptance_code_1), 455 | .acceptance_code_2(acceptance_code_2), 456 | .acceptance_code_3(acceptance_code_3), 457 | 458 | /* Acceptance mask register */ 459 | .acceptance_mask_1(acceptance_mask_1), 460 | .acceptance_mask_2(acceptance_mask_2), 461 | .acceptance_mask_3(acceptance_mask_3), 462 | /* End: This section is for EXTENDED mode */ 463 | 464 | /* Tx data registers. Holding identifier (basic mode), tx frame information (extended mode) and data */ 465 | .tx_data_0(tx_data_0), 466 | .tx_data_1(tx_data_1), 467 | .tx_data_2(tx_data_2), 468 | .tx_data_3(tx_data_3), 469 | .tx_data_4(tx_data_4), 470 | .tx_data_5(tx_data_5), 471 | .tx_data_6(tx_data_6), 472 | .tx_data_7(tx_data_7), 473 | .tx_data_8(tx_data_8), 474 | .tx_data_9(tx_data_9), 475 | .tx_data_10(tx_data_10), 476 | .tx_data_11(tx_data_11), 477 | .tx_data_12(tx_data_12), 478 | /* End: Tx data registers */ 479 | 480 | /* Tx signal */ 481 | .tx(tx_o), 482 | .tx_next(tx_next), 483 | .bus_off_on(bus_off_on_o), 484 | 485 | .go_overload_frame(go_overload_frame), 486 | .go_error_frame(go_error_frame), 487 | .go_tx(go_tx), 488 | .send_ack(send_ack) 489 | 490 | `ifdef CAN_BIST 491 | , 492 | .mbist_si_i(mbist_si_i), 493 | .mbist_so_o(mbist_so_o), 494 | .mbist_ctrl_i(mbist_ctrl_i) 495 | `endif 496 | ); 497 | 498 | // Multiplexing registers and rx fifo into data_o 499 | always @(extended_mode or addr_i or reset_mode) begin 500 | if(extended_mode & (~reset_mode) & ((addr_i >= 8'd16) && (addr_i <= 8'd28)) 501 | | (~extended_mode) & ((addr_i >= 8'd20) && (addr_i <= 8'd29))) begin 502 | 503 | data_out_fifo_selected = 1'b1; 504 | end else begin 505 | data_out_fifo_selected = 1'b0; 506 | end 507 | end 508 | 509 | always @(posedge clk_i) begin 510 | if(cs_i & (~we_i)) begin 511 | if(data_out_fifo_selected) begin 512 | data_o <=#Tp data_out_fifo; 513 | end else begin 514 | data_o <=#Tp data_out_regs; 515 | end 516 | end 517 | end 518 | 519 | always @(posedge clk_i or posedge rst_i) begin 520 | if(rst_i) begin 521 | rx_sync_tmp <= 1'b1; 522 | rx_sync <= 1'b1; 523 | end else begin 524 | rx_sync_tmp <=#Tp rx_i; 525 | rx_sync <=#Tp rx_sync_tmp; 526 | end 527 | end 528 | 529 | endmodule 530 | 531 | 532 | /* 533 | * CAN controller connected to a wishbone bus 534 | */ 535 | module can_wishbone_top( 536 | input wire wb_clk_i, 537 | input wire wb_rst_i, 538 | input wire [7:0] wb_dat_i, 539 | output wire [7:0] wb_dat_o, 540 | input wire wb_cyc_i, 541 | input wire wb_stb_i, 542 | input wire wb_we_i, 543 | input wire [7:0] wb_adr_i, 544 | output reg wb_ack_o, 545 | 546 | input wire clk_i, 547 | input wire rx_i, 548 | output wire tx_o, 549 | output wire bus_off_on_o, 550 | output wire irq_n_o, 551 | output wire clkout_o 552 | 553 | `ifdef CAN_BIST 554 | , 555 | input wire mbist_si_i, // bist scan serial in 556 | output wire mbist_so_o, // bist scan serial out 557 | input wire [`CAN_MBIST_CTRL_WIDTH - 1:0] mbist_ctrl_i // bist chain shift control 558 | `endif 559 | ); 560 | 561 | parameter Tp = 1; 562 | 563 | reg cs_sync1 = 0; 564 | reg cs_sync2 = 0; 565 | reg cs_sync3 = 0; 566 | 567 | reg cs_ack1 = 0; 568 | reg cs_ack2 = 0; 569 | reg cs_ack3 = 0; 570 | reg cs_sync_rst1 = 0; 571 | reg cs_sync_rst2 = 0; 572 | wire cs_can = cs_sync2 & (~cs_sync3); 573 | 574 | 575 | // Combine wb_cyc_i and wb_stb_i signals to cs signal, then sync to clk_i clock domain. 576 | always @(posedge clk_i or posedge wb_rst_i) begin 577 | if(wb_rst_i) begin 578 | cs_sync1 <= 0; 579 | cs_sync2 <= 0; 580 | cs_sync3 <= 0; 581 | cs_sync_rst1 <= 0; 582 | cs_sync_rst2 <= 0; 583 | end else begin 584 | cs_sync1 <=#Tp wb_cyc_i & wb_stb_i & (~cs_sync_rst2); 585 | cs_sync2 <=#Tp cs_sync1 & (~cs_sync_rst2); 586 | cs_sync3 <=#Tp cs_sync2 & (~cs_sync_rst2); 587 | cs_sync_rst1 <=#Tp cs_ack3; 588 | cs_sync_rst2 <=#Tp cs_sync_rst1; 589 | end 590 | end 591 | 592 | // Generate bus signals 593 | always @(posedge wb_clk_i) begin 594 | cs_ack1 <=#Tp cs_sync3; 595 | cs_ack2 <=#Tp cs_ack1; 596 | cs_ack3 <=#Tp cs_ack2; 597 | wb_ack_o <=#Tp (cs_ack2 & (~cs_ack3)); 598 | end 599 | 600 | can_controller #(.Tp(Tp)) can_controller( 601 | .rst_i(wb_rst_i), 602 | .cs_i(cs_can), 603 | .we_i(wb_we_i), 604 | .addr_i(wb_adr_i), 605 | .data_i(wb_dat_i), 606 | .data_o(wb_dat_o), 607 | 608 | .clk_i(clk_i), 609 | .rx_i(rx_i), 610 | .tx_o(tx_o), 611 | .bus_off_on_o(bus_off_on_o), 612 | .irq_n_o(irq_n_o), 613 | .clkout_o(clkout_o) 614 | 615 | `ifdef CAN_BIST 616 | , 617 | .mbist_si_i(mbist_si_i), 618 | .mbist_so_o(mbist_so_o), 619 | .mbist_ctrl_i(mbist_ctrl_i) 620 | `endif 621 | ); 622 | 623 | endmodule 624 | 625 | 626 | /* 627 | * CAN controller connected to an 8051 bus. 628 | * Output enable signal is provided for data bus output signals. 629 | */ 630 | module can_8051_top( 631 | input wire rst_i, 632 | input wire cs_can_i, 633 | input wire ale_i, 634 | input wire rd_i, 635 | input wire wr_i, 636 | input wire [7:0] port_0_i, 637 | output wire [7:0] port_0_o, 638 | output wire port_0_oe, 639 | 640 | input wire clk_i, 641 | input wire rx_i, 642 | output wire tx_o, 643 | output wire bus_off_on_o, 644 | output wire irq_n_o, 645 | output wire clkout_o 646 | 647 | `ifdef CAN_BIST 648 | , 649 | input wire mbist_si_i, // bist scan serial in 650 | output wire mbist_so_o, // bist scan serial out 651 | input wire [`CAN_MBIST_CTRL_WIDTH - 1:0] mbist_ctrl_i // bist chain shift control 652 | `endif 653 | ); 654 | 655 | parameter Tp = 1; 656 | 657 | reg [7:0] addr_latched; 658 | reg wr_i_q; 659 | reg rd_i_q; 660 | 661 | // Latching of bus signals 662 | always @(posedge clk_i or posedge rst_i) begin 663 | if(rst_i) begin 664 | addr_latched <= 8'h0; 665 | wr_i_q <= 1'b0; 666 | rd_i_q <= 1'b0; 667 | end else if(ale_i) begin 668 | addr_latched <=#Tp port_0_i; 669 | wr_i_q <=#Tp wr_i; 670 | rd_i_q <=#Tp rd_i; 671 | end 672 | end 673 | 674 | wire cs = ((wr_i & (~wr_i_q)) | (rd_i & (~rd_i_q))) & cs_can_i; 675 | 676 | assign port_0_oe = cs_can_i & rd_i; 677 | 678 | can_controller can_controller( 679 | .rst_i(rst_i), 680 | .cs_i(cs), 681 | .we_i(wr_i), 682 | .addr_i(addr_latched), 683 | .data_i(port_0_i), 684 | .data_o(port_0_o), 685 | 686 | .clk_i(clk_i), 687 | .rx_i(rx_i), 688 | .tx_o(tx_o), 689 | .bus_off_on_o(bus_off_on_o), 690 | .irq_n_o(irq_n_o), 691 | .clkout_o(clkout_o) 692 | 693 | `ifdef CAN_BIST 694 | , 695 | .mbist_si_i(mbist_si_i), 696 | .mbist_so_o(mbist_so_o), 697 | .mbist_ctrl_i(mbist_ctrl_i) 698 | `endif 699 | ); 700 | 701 | endmodule 702 | 703 | 704 | /* 705 | * CAN controller connected to an 8051 bus. 706 | * Data lines are shared between input and output; 707 | * outputs thus can be tri-stated. 708 | * 709 | * This is the original 8051 interface provided by earlier versions of this 710 | * core. 711 | */ 712 | module can_8051_tristate_top( 713 | input wire rst_i, 714 | input wire ale_i, 715 | input wire rd_i, 716 | input wire wr_i, 717 | inout wire [7:0] port_0_io, 718 | input wire cs_can_i, 719 | 720 | input wire clk_i, 721 | input wire rx_i, 722 | output wire tx_o, 723 | output wire bus_off_on_o, 724 | output wire irq_n_o, 725 | output wire clkout_o 726 | 727 | `ifdef CAN_BIST 728 | , 729 | input wire mbist_si_i, // bist scan serial in 730 | output wire mbist_so_o, // bist scan serial out 731 | input wire [`CAN_MBIST_CTRL_WIDTH - 1:0] mbist_ctrl_i // bist chain shift control 732 | `endif 733 | ); 734 | 735 | parameter Tp = 1; 736 | 737 | wire [7:0] port_0_o; 738 | wire port_0_oe; 739 | 740 | assign port_0_io = (port_0_oe) ? port_0_o : 8'hz; 741 | 742 | can_8051_top #(.Tp(Tp)) can_8051( 743 | .rst_i(rst_i), 744 | .ale_i(ale_i), 745 | .rd_i(rd_i), 746 | .wr_i(wr_i), 747 | .port_0_i(port_0_io), 748 | .port_0_o(port_0_o), 749 | .port_0_oe(port_0_oe), 750 | .cs_can_i(cs_can_i), 751 | 752 | .clk_i(clk_i), 753 | .rx_i(rx_i), 754 | .tx_o(tx_o), 755 | .bus_off_on_o(bus_off_on_o), 756 | .irq_n_o(irq_n_o), 757 | .clkout_o(clkout_o) 758 | 759 | `ifdef CAN_BIST 760 | , 761 | .mbist_si_i(mbist_si_i), 762 | .mbist_so_o(mbist_so_o), 763 | .mbist_ctrl_i(mbist_ctrl_i) 764 | `endif 765 | ); 766 | 767 | endmodule 768 | 769 | -------------------------------------------------------------------------------- /can_top_defines.v: -------------------------------------------------------------------------------- 1 | /* vim: colorcolumn=80 2 | * 3 | * This file is part of a verilog CAN controller that is SJA1000 compatible. 4 | * 5 | * Authors: 6 | * * Igor Mohor 7 | * Author of the original version at 8 | * http://www.opencores.org/projects/can/ 9 | * (which has been unmaintained since about 2009) 10 | * 11 | * * David Piegdon 12 | * Picked up project for cleanup and bugfixes in 2019 13 | * 14 | * Any additional information is available in the LICENSE file. 15 | * 16 | * Copyright (C) 2002, 2003, 2004, 2019 Authors 17 | * 18 | * This source file may be used and distributed without restriction provided 19 | * that this copyright statement is not removed from the file and that any 20 | * derivative work contains the original copyright notice and the associated 21 | * disclaimer. 22 | * 23 | * This source file is free software; you can redistribute it and/or modify it 24 | * under the terms of the GNU Lesser General Public License as published by the 25 | * Free Software Foundation; either version 2.1 of the License, or (at your 26 | * option) any later version. 27 | * 28 | * This source is distributed in the hope that it will be useful, but WITHOUT 29 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 30 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 31 | * details. 32 | * 33 | * You should have received a copy of the GNU Lesser General Public License 34 | * along with this source; if not, download it from 35 | * http://www.opencores.org/lgpl.shtml 36 | * 37 | * The CAN protocol is developed by Robert Bosch GmbH and protected by patents. 38 | * Anybody who wants to implement this CAN IP core on silicon has to obtain 39 | * a CAN protocol license from Bosch. 40 | */ 41 | 42 | `default_nettype none 43 | 44 | /* 45 | * Uncomment following line if you want to use CAN in Actel APA devices 46 | * (embedded memory used) 47 | */ 48 | //`define ACTEL_APA_RAM 49 | 50 | /* 51 | * Uncomment following line if you want to use CAN in Altera devices 52 | * (embedded memory used) 53 | */ 54 | //`define ALTERA_RAM 55 | 56 | /* 57 | * Uncomment following line if you want to use CAN in Xilinx devices 58 | * (embedded memory used) 59 | */ 60 | //`define XILINX_RAM 61 | 62 | /* 63 | * Uncomment the line for the ram used in ASIC implementation 64 | */ 65 | //`define VIRTUALSILICON_RAM 66 | //`define ARTISAN_RAM 67 | 68 | /* 69 | * Uncomment the following line when RAM BIST is needed 70 | * (for ASIC implementations) 71 | */ 72 | //`define CAN_BIST 73 | 74 | /* 75 | * width of MBIST control bus 76 | */ 77 | //`define CAN_MBIST_CTRL_WIDTH 3 78 | -------------------------------------------------------------------------------- /can_top_tb.v: -------------------------------------------------------------------------------- 1 | /* vim: colorcolumn=80 2 | * 3 | * This file is part of a verilog CAN controller that is SJA1000 compatible. 4 | * 5 | * Authors: 6 | * * David Piegdon 7 | * Picked up project for cleanup and bugfixes in 2019 8 | * 9 | * Any additional information is available in the LICENSE file. 10 | * 11 | * Copyright (C) 2019 Authors 12 | * 13 | * This source file may be used and distributed without restriction provided 14 | * that this copyright statement is not removed from the file and that any 15 | * derivative work contains the original copyright notice and the associated 16 | * disclaimer. 17 | * 18 | * This source file is free software; you can redistribute it and/or modify it 19 | * under the terms of the GNU Lesser General Public License as published by the 20 | * Free Software Foundation; either version 2.1 of the License, or (at your 21 | * option) any later version. 22 | * 23 | * This source is distributed in the hope that it will be useful, but WITHOUT 24 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 25 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 26 | * details. 27 | * 28 | * You should have received a copy of the GNU Lesser General Public License 29 | * along with this source; if not, download it from 30 | * http://www.opencores.org/lgpl.shtml 31 | * 32 | * The CAN protocol is developed by Robert Bosch GmbH and protected by patents. 33 | * Anybody who wants to implement this CAN IP core on silicon has to obtain 34 | * a CAN protocol license from Bosch. 35 | */ 36 | 37 | `default_nettype none 38 | 39 | `timescale 1ns/10ps 40 | 41 | `include "testbench/canbus.v" 42 | `include "testbench/test_rx_tx.v" 43 | `include "testbench/test_acceptance_filter.v" 44 | 45 | module can_top_tb(); 46 | 47 | initial begin 48 | $dumpfile("can_top_tb.vcd"); 49 | $dumpvars; 50 | end 51 | 52 | localparam TESTCOUNT=2; 53 | 54 | wire [TESTCOUNT-1:0] subtest_finished; 55 | wire [15:0] subtest_errors[TESTCOUNT-1:0]; 56 | 57 | // instantiate all sub-tests 58 | test_tx_rx test_tx_rx(subtest_finished[0], subtest_errors[0]); 59 | test_acceptance_filter test_acceptance_filter(subtest_finished[1], subtest_errors[1]); 60 | // to be ported: 61 | // test_synchronization 62 | // test_empty_fifo_ext 63 | // test_full_fifo_ext 64 | // send_frame_ext 65 | // test_empty_fifo 66 | // test_full_fifo 67 | // test_reset_mode 68 | // bus_off_test 69 | // forced_bus_off 70 | // send_frame_basic 71 | // send_frame_extended 72 | // self_reception_request 73 | // manual_frame_basic 74 | // manual_frame_ext 75 | // error_test 76 | // register_test 77 | // bus_off_recovery_test; 78 | // new: 79 | // test_baudrate 80 | // test_arbitration_loss 81 | 82 | 83 | // collect output 84 | wire finished = &(subtest_finished); 85 | integer errors; 86 | integer i; 87 | 88 | always begin 89 | #1; 90 | 91 | wait(finished); 92 | #500; 93 | 94 | errors = 0; 95 | for(i = 0; i < TESTCOUNT; i = i+1) begin 96 | errors = errors + subtest_errors[i]; 97 | end 98 | 99 | $display("%1d subtests completed.", TESTCOUNT); 100 | 101 | if(errors) begin 102 | $error("FAIL: collected %d errors", errors); 103 | $fatal(); 104 | end else begin 105 | $display("PASS: testsuite finished successfully"); 106 | $finish; 107 | end 108 | end 109 | 110 | endmodule 111 | 112 | -------------------------------------------------------------------------------- /testbench/canbus.v: -------------------------------------------------------------------------------- 1 | /* vim: colorcolumn=80 2 | * 3 | * This file is part of a verilog CAN controller that is SJA1000 compatible. 4 | * 5 | * Authors: 6 | * * David Piegdon 7 | * Picked up project for cleanup and bugfixes in 2019 8 | * 9 | * Any additional information is available in the LICENSE file. 10 | * 11 | * Copyright (C) 2019 Authors 12 | * 13 | * This source file may be used and distributed without restriction provided 14 | * that this copyright statement is not removed from the file and that any 15 | * derivative work contains the original copyright notice and the associated 16 | * disclaimer. 17 | * 18 | * This source file is free software; you can redistribute it and/or modify it 19 | * under the terms of the GNU Lesser General Public License as published by the 20 | * Free Software Foundation; either version 2.1 of the License, or (at your 21 | * option) any later version. 22 | * 23 | * This source is distributed in the hope that it will be useful, but WITHOUT 24 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 25 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 26 | * details. 27 | * 28 | * You should have received a copy of the GNU Lesser General Public License 29 | * along with this source; if not, download it from 30 | * http://www.opencores.org/lgpl.shtml 31 | * 32 | * The CAN protocol is developed by Robert Bosch GmbH and protected by patents. 33 | * Anybody who wants to implement this CAN IP core on silicon has to obtain 34 | * a CAN protocol license from Bosch. 35 | */ 36 | 37 | `default_nettype none 38 | 39 | module simulated_can_bus(input wire [N-1:0] tx, output wire [N-1:0] rx); 40 | /* 41 | * tx bit '1' equals to 0V = can_hi - can_low (recessive) 42 | * tx bit '0' equals to 5V = can_hi - can_low (dominant) 43 | * 44 | * this is a simple CAN bus simulator that merges N devices on a bus, 45 | * where each device has a transmission delay of #delay from to each 46 | * other device. 47 | */ 48 | 49 | parameter N=2; // number of devices on bus 50 | parameter delay=0; // delay from any one to another node 51 | 52 | wire [N-1:0] delayed_tx; 53 | wand [N-1:0] merged_tx; 54 | 55 | generate 56 | genvar rxn; 57 | genvar txn; 58 | for(rxn = 0; rxn < N; rxn=rxn+1) begin 59 | 60 | assign #delay delayed_tx[rxn] = tx[rxn]; 61 | 62 | for(txn = 0; txn < N; txn=txn+1) begin 63 | if(rxn == txn) begin 64 | assign merged_tx[rxn] = tx[txn]; 65 | end else begin 66 | assign merged_tx[rxn] = delayed_tx[txn]; 67 | end 68 | end 69 | 70 | assign rx[rxn] = merged_tx[rxn]; 71 | end 72 | endgenerate 73 | 74 | endmodule 75 | 76 | -------------------------------------------------------------------------------- /testbench/fixture.inc: -------------------------------------------------------------------------------- 1 | /* vim: colorcolumn=80 syntax=verilog 2 | * 3 | * This file is part of a verilog CAN controller that is SJA1000 compatible. 4 | * 5 | * Authors: 6 | * * David Piegdon 7 | * Picked up project for cleanup and bugfixes in 2019 8 | * 9 | * Any additional information is available in the LICENSE file. 10 | * 11 | * Copyright (C) 2019 Authors 12 | * 13 | * This source file may be used and distributed without restriction provided 14 | * that this copyright statement is not removed from the file and that any 15 | * derivative work contains the original copyright notice and the associated 16 | * disclaimer. 17 | * 18 | * This source file is free software; you can redistribute it and/or modify it 19 | * under the terms of the GNU Lesser General Public License as published by the 20 | * Free Software Foundation; either version 2.1 of the License, or (at your 21 | * option) any later version. 22 | * 23 | * This source is distributed in the hope that it will be useful, but WITHOUT 24 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 25 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 26 | * details. 27 | * 28 | * You should have received a copy of the GNU Lesser General Public License 29 | * along with this source; if not, download it from 30 | * http://www.opencores.org/lgpl.shtml 31 | * 32 | * The CAN protocol is developed by Robert Bosch GmbH and protected by patents. 33 | * Anybody who wants to implement this CAN IP core on silicon has to obtain 34 | * a CAN protocol license from Bosch. 35 | */ 36 | 37 | /* 38 | * This file contains a basic test fixture for the can controller. 39 | * Five devices are connected on a can bus: 40 | * two (1&2) partially share a wishbone bus, 41 | * and the other three (3&4&5) share a 8051 bus. 42 | * Tasks are provided to read and write registers of all of these. 43 | * 44 | * Just include this file *inside* your testbench module and add the test code 45 | * and wait(start_test) in your code so the fixture is initialized properly. 46 | * 47 | * Also make sure your testbench supplies the following: 48 | * 49 | * localparam bitclocks; // length of a bit on the can bus, in clocks ok clk. 50 | */ 51 | 52 | `include "testbench/tasks.inc" 53 | `include "testbench/timings.inc" 54 | 55 | // to enable logging of all register accesses 56 | //`define LOG_REGISTER_ACCESS 1 57 | 58 | // main clock at 16 MHz 59 | reg clk = 0; 60 | initial begin 61 | forever #31.25 clk = ~clk; 62 | end 63 | 64 | // countdown for timeouts. may be used by anybody to measure timeouts. 65 | integer countdown = 0; 66 | always @(posedge clk) begin 67 | if(countdown != 0) begin 68 | countdown = countdown - 1; 69 | end 70 | end 71 | 72 | // wishbone clock at 10 MHz 73 | reg wb_clk = 0; 74 | initial begin 75 | forever #50 wb_clk = ~wb_clk; 76 | end 77 | 78 | reg reset = 1; 79 | 80 | 81 | // wishbone bus 82 | reg [7:0] wb_di = 8'hx; 83 | wire [7:0] wb_do1; 84 | wire [7:0] wb_do2; 85 | reg wb_cyc1 = 0; 86 | reg wb_cyc2 = 0; 87 | reg wb_stb = 0; 88 | reg wb_we = 0; 89 | reg [7:0] wb_adr = 8'hx; 90 | wire wb_ack1; 91 | wire wb_ack2; 92 | reg wb_free = 1; // bus-free indicator for wishbone bus 93 | 94 | // can device 1 95 | wire dut1_rx; 96 | wire dut1_tx; 97 | wire dut1_irq; 98 | wire dut1_clkout; 99 | wire dut1_bus_off_on; 100 | can_wishbone_top dut1(wb_clk, reset, 101 | wb_di, wb_do1, wb_cyc1, wb_stb, wb_we, wb_adr, wb_ack1, 102 | clk, 103 | dut1_rx, dut1_tx, 104 | dut1_bus_off_on, dut1_irq, dut1_clkout); 105 | 106 | // can device 2 107 | wire dut2_rx; 108 | wire dut2_tx; 109 | wire dut2_irq; 110 | wire dut2_clkout; 111 | wire dut2_bus_off_on; 112 | can_wishbone_top dut2(wb_clk, reset, 113 | wb_di, wb_do2, wb_cyc2, wb_stb, wb_we, wb_adr, wb_ack2, 114 | clk, 115 | dut2_rx, dut2_tx, 116 | dut2_bus_off_on, dut2_irq, dut2_clkout); 117 | 118 | 119 | // tristatable 8051 bus 120 | reg t8b_cs3 = 0; 121 | reg t8b_cs4 = 0; 122 | reg t8b_cs5 = 0; 123 | reg t8b_ale = 0; 124 | reg t8b_rd = 0; 125 | reg t8b_wr = 0; 126 | wire [7:0] t8b_port; 127 | reg t8b_free = 1; // bus free indicator for 8051 bus 128 | reg t8b_port_inject_now = 0; // trigger to inject word onto data port 129 | reg [7:0] t8b_port_inject_value = 0; // word to inject onto data port 130 | assign t8b_port = t8b_port_inject_now ? t8b_port_inject_value : 8'hz; 131 | 132 | // can device 3 133 | wire dut3_rx; 134 | wire dut3_tx; 135 | wire dut3_irq; 136 | wire dut3_clkout; 137 | wire dut3_bus_off_on; 138 | can_8051_tristate_top dut3(reset, 139 | t8b_ale, t8b_rd, t8b_wr, t8b_port, t8b_cs3, 140 | clk, 141 | dut3_rx, dut3_tx, 142 | dut3_bus_off_on, dut3_irq, dut3_clkout); 143 | 144 | // can device 4 145 | wire dut4_rx; 146 | wire dut4_tx; 147 | wire dut4_irq; 148 | wire dut4_clkout; 149 | wire dut4_bus_off_on; 150 | can_8051_tristate_top dut4(reset, 151 | t8b_ale, t8b_rd, t8b_wr, t8b_port, t8b_cs4, 152 | clk, 153 | dut4_rx, dut4_tx, 154 | dut4_bus_off_on, dut4_irq, dut4_clkout); 155 | 156 | // can device 5 157 | wire dut5_rx; 158 | wire dut5_tx; 159 | wire dut5_irq; 160 | wire dut5_clkout; 161 | wire dut5_bus_off_on; 162 | can_8051_tristate_top dut5(reset, 163 | t8b_ale, t8b_rd, t8b_wr, t8b_port, t8b_cs5, 164 | clk, 165 | dut5_rx, dut5_tx, 166 | dut5_bus_off_on, dut5_irq, dut5_clkout); 167 | 168 | 169 | // bus helper tasks 170 | task automatic read_register_wb; 171 | input integer dut; 172 | input [7:0] reg_addr; 173 | output [7:0] reg_data; 174 | 175 | begin 176 | wait (wb_free); 177 | wb_free = 0; 178 | 179 | @(posedge wb_clk); 180 | #1; 181 | wb_adr = reg_addr; 182 | if(dut == 1) begin 183 | wb_cyc1 = 1; 184 | end else if(dut == 2) begin 185 | wb_cyc2 = 1; 186 | end 187 | wb_stb = 1; 188 | wb_we = 0; 189 | if(dut == 1) begin 190 | wait (wb_ack1); 191 | reg_data = wb_do1; 192 | end else if(dut == 2) begin 193 | wait (wb_ack2); 194 | reg_data = wb_do2; 195 | end 196 | @(posedge wb_clk); 197 | #1; 198 | wb_adr = 8'hz; 199 | if(dut == 1) begin 200 | wb_cyc1 = 0; 201 | end else if(dut == 2) begin 202 | wb_cyc2 = 0; 203 | end 204 | wb_stb = 0; 205 | wb_we = 0; 206 | 207 | wb_free = 1; 208 | end 209 | endtask 210 | 211 | task automatic write_register_wb; 212 | input integer dut; 213 | input [7:0] reg_addr; 214 | input [7:0] reg_data; 215 | 216 | begin 217 | wait (wb_free); 218 | wb_free = 0; 219 | 220 | @(posedge wb_clk); 221 | #1; 222 | wb_adr = reg_addr; 223 | wb_di = reg_data; 224 | if(dut == 1) begin 225 | wb_cyc1 = 1; 226 | end else if(dut == 2) begin 227 | wb_cyc2 = 1; 228 | end 229 | wb_stb = 1; 230 | wb_we = 1; 231 | if(dut == 1) begin 232 | wait (wb_ack1); 233 | end else if(dut == 2) begin 234 | wait (wb_ack2); 235 | end 236 | @(posedge wb_clk); 237 | #1; 238 | wb_adr = 8'hx; 239 | if(dut == 1) begin 240 | wb_cyc1 = 0; 241 | end else if(dut == 2) begin 242 | wb_cyc2 = 0; 243 | end 244 | wb_stb = 0; 245 | wb_we = 0; 246 | wb_di = 8'hx; 247 | 248 | wb_free = 1; 249 | end 250 | endtask 251 | 252 | task automatic read_register_t8b; 253 | input integer dut; 254 | input [7:0] reg_addr; 255 | output [7:0] reg_data; 256 | 257 | begin 258 | wait (t8b_free); 259 | t8b_free = 0; 260 | 261 | @(posedge clk); 262 | #1; 263 | if(dut == 3) begin 264 | t8b_cs3 = 1; 265 | end else if(dut == 4) begin 266 | t8b_cs4 = 1; 267 | end else if(dut == 5) begin 268 | t8b_cs5 = 1; 269 | end 270 | @(negedge clk); 271 | #1; 272 | t8b_ale = 1; 273 | t8b_port_inject_value = reg_addr; 274 | t8b_port_inject_now = 1; 275 | @(negedge clk); 276 | #1; 277 | t8b_ale = 0; 278 | @(negedge clk); 279 | #1; 280 | t8b_port_inject_now = 0; 281 | t8b_rd = 1; 282 | @(negedge clk); 283 | #1; 284 | reg_data = t8b_port; 285 | #1; 286 | t8b_rd = 0; 287 | if(dut == 3) begin 288 | t8b_cs3 = 0; 289 | end else if(dut == 4) begin 290 | t8b_cs4 = 0; 291 | end else if(dut == 5) begin 292 | t8b_cs5 = 0; 293 | end 294 | 295 | t8b_free = 1; 296 | end 297 | endtask 298 | 299 | task automatic write_register_t8b; 300 | input integer dut; 301 | input [7:0] reg_addr; 302 | input [7:0] reg_data; 303 | 304 | begin 305 | wait (t8b_free); 306 | t8b_free = 0; 307 | 308 | @(posedge clk); 309 | #1; 310 | if(dut == 3) begin 311 | t8b_cs3 = 1; 312 | end else if(dut == 4) begin 313 | t8b_cs4 = 1; 314 | end else if(dut == 5) begin 315 | t8b_cs5 = 1; 316 | end 317 | @(negedge clk); 318 | #1; 319 | t8b_ale = 1; 320 | t8b_port_inject_now = 1; 321 | t8b_port_inject_value = reg_addr; 322 | @(negedge clk); 323 | #1; 324 | t8b_ale = 0; 325 | @(negedge clk); 326 | #1; 327 | t8b_port_inject_value = reg_data; 328 | t8b_wr = 1; 329 | @(negedge clk); 330 | #1; 331 | t8b_wr = 0; 332 | t8b_port_inject_now = 0; 333 | if(dut == 3) begin 334 | t8b_cs3 = 0; 335 | end else if(dut == 4) begin 336 | t8b_cs4 = 0; 337 | end else if(dut == 5) begin 338 | t8b_cs5 = 0; 339 | end 340 | 341 | t8b_free = 1; 342 | end 343 | endtask 344 | 345 | 346 | /* 347 | * task to read a register via the connected bus. 348 | * @dut: which device to interface with 349 | * @reg_addr: address of register to read 350 | * @reg_data: output value 351 | */ 352 | task automatic read_register; 353 | input integer dut; 354 | input [7:0] reg_addr; 355 | output [7:0] reg_data; 356 | 357 | begin 358 | if((dut == 1) || (dut == 2)) begin 359 | read_register_wb(dut, reg_addr, reg_data); 360 | end else if((dut == 3) || (dut == 4) || (dut == 5)) begin 361 | read_register_t8b(dut, reg_addr, reg_data); 362 | end 363 | 364 | `ifdef LOG_REGISTER_ACCESS 365 | $display("(%012t) DUT%1d GET register %0d == 0x%0x", 366 | $time, dut, reg_addr, reg_data); 367 | `endif 368 | end 369 | endtask 370 | 371 | /* 372 | * task to write a register via the connected bus. 373 | * @dut: which device to interface with 374 | * @reg_addr: address of register to write 375 | * @reg_data: output value 376 | */ 377 | task automatic write_register; 378 | input integer dut; 379 | input [7:0] reg_addr; 380 | input [7:0] reg_data; 381 | 382 | begin 383 | `ifdef LOG_REGISTER_ACCESS 384 | $display("(%012t) DUT%1d SET register %0d := 0x%0x", 385 | $time, dut, reg_addr, reg_data); 386 | `endif 387 | 388 | if((dut == 1) || (dut == 2)) begin 389 | write_register_wb(dut, reg_addr, reg_data); 390 | end else if((dut == 3) || (dut == 4) || (dut == 5)) begin 391 | write_register_t8b(dut, reg_addr, reg_data); 392 | end 393 | end 394 | endtask 395 | 396 | 397 | // manual bus tap 398 | reg canbus_tap_tx = 1; 399 | wire canbus_tap_rx; 400 | 401 | 402 | // can bus 403 | simulated_can_bus #(.N(6), .delay(25)) bus( 404 | { canbus_tap_tx, dut1_tx, dut2_tx, dut3_tx, dut4_tx, dut5_tx }, 405 | { canbus_tap_rx, dut1_rx, dut2_rx, dut3_rx, dut4_rx, dut5_rx }); 406 | 407 | 408 | // test trigger 409 | reg start_test = 0; 410 | initial begin 411 | #250; 412 | reset = 0; 413 | #250; 414 | start_test = 1; 415 | end 416 | 417 | -------------------------------------------------------------------------------- /testbench/tasks.inc: -------------------------------------------------------------------------------- 1 | /* vim: colorcolumn=80 syntax=verilog 2 | * 3 | * This file is part of a verilog CAN controller that is SJA1000 compatible. 4 | * 5 | * Authors: 6 | * * David Piegdon 7 | * Picked up project for cleanup and bugfixes in 2019 8 | * 9 | * Any additional information is available in the LICENSE file. 10 | * 11 | * Copyright (C) 2019 Authors 12 | * 13 | * This source file may be used and distributed without restriction provided 14 | * that this copyright statement is not removed from the file and that any 15 | * derivative work contains the original copyright notice and the associated 16 | * disclaimer. 17 | * 18 | * This source file is free software; you can redistribute it and/or modify it 19 | * under the terms of the GNU Lesser General Public License as published by the 20 | * Free Software Foundation; either version 2.1 of the License, or (at your 21 | * option) any later version. 22 | * 23 | * This source is distributed in the hope that it will be useful, but WITHOUT 24 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 25 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 26 | * details. 27 | * 28 | * You should have received a copy of the GNU Lesser General Public License 29 | * along with this source; if not, download it from 30 | * http://www.opencores.org/lgpl.shtml 31 | * 32 | * The CAN protocol is developed by Robert Bosch GmbH and protected by patents. 33 | * Anybody who wants to implement this CAN IP core on silicon has to obtain 34 | * a CAN protocol license from Bosch. 35 | */ 36 | 37 | /* 38 | * This file defines helper tasks for the can controller. 39 | * 40 | * Just include this file *inside* your testbench module and add the test code. 41 | */ 42 | 43 | // Forcing bus-off by writinf to tx_err_cnt register 44 | task automatic forced_bus_off(input integer dut); 45 | begin 46 | // Switch-on reset mode 47 | write_register(dut, 8'd0, {7'h0, 1'h1}); 48 | // Set Clock Divider register 49 | write_register(dut, 8'd31, {1'b1, 7'h0}); // Setting the extended mode (not normal) 50 | // Write 255 to tx_err_cnt register - Forcing bus-off 51 | write_register(dut, 8'd15, 255); 52 | // Switch-off reset mode 53 | write_register(dut, 8'd0, {7'h0, ~(1'h1)}); 54 | 55 | // #1000000; 56 | #2500000; 57 | 58 | // Switch-on reset mode 59 | write_register(dut, 8'd0, {7'h0, 1'h1}); 60 | // Write 245 to tx_err_cnt register 61 | write_register(dut, 8'd15, 245); 62 | // Switch-off reset mode 63 | write_register(dut, 8'd0, {7'h0, ~(1'h1)}); 64 | 65 | #1000000; 66 | end 67 | endtask 68 | 69 | // Return number of bytes in RX fifo. 70 | // Not working when wr_info_pointer is smaller than rd_info_pointer. 71 | `define rx_fifo_bytes(dut_interna) \ 72 | (dut_interna.can_controller.i_can_bsp.i_can_fifo.fifo_cnt) 73 | 74 | // Return number of frames in RX fifo. 75 | // Not working when wr_info_pointer is smaller than rd_info_pointer. 76 | `define rx_fifo_frames(dut_interna) \ 77 | (dut_interna.can_controller.i_can_bsp.i_can_fifo.wr_info_pointer - \ 78 | dut_interna.can_controller.i_can_bsp.i_can_fifo.rd_info_pointer) 79 | 80 | function automatic integer get_rx_fifo_framecount(input integer dut); 81 | begin 82 | if(dut==1) begin 83 | get_rx_fifo_framecount = `rx_fifo_frames(dut1); 84 | end else if(dut==2) begin 85 | get_rx_fifo_framecount = `rx_fifo_frames(dut2); 86 | end else if(dut==3) begin 87 | get_rx_fifo_framecount = `rx_fifo_frames(dut3.can_8051); 88 | end else if(dut==4) begin 89 | get_rx_fifo_framecount = `rx_fifo_frames(dut4.can_8051); 90 | end else if(dut==5) begin 91 | get_rx_fifo_framecount = `rx_fifo_frames(dut5.can_8051); 92 | end 93 | end 94 | endfunction 95 | 96 | // Wait for interrupt on specified device. Returns immediately if IRQ active. 97 | task automatic wait4irq(input integer dut); 98 | begin 99 | if(dut==1) begin 100 | if(dut1_irq) begin 101 | @(negedge dut1_irq); 102 | end 103 | end else if(dut==2) begin 104 | if(dut2_irq) begin 105 | @(negedge dut2_irq); 106 | end 107 | end else if(dut==3) begin 108 | if(dut3_irq) begin 109 | @(negedge dut3_irq); 110 | end 111 | end else if(dut==4) begin 112 | if(dut4_irq) begin 113 | @(negedge dut4_irq); 114 | end 115 | end else if(dut==5) begin 116 | if(dut5_irq) begin 117 | @(negedge dut5_irq); 118 | end 119 | end 120 | end 121 | endtask 122 | 123 | // Return value of interrupt line of dut 124 | function automatic irqline(input integer dut); 125 | begin 126 | if(dut==1) begin 127 | irqline = dut1_irq; 128 | end else if(dut==2) begin 129 | irqline = dut2_irq; 130 | end else if(dut==3) begin 131 | irqline = dut3_irq; 132 | end else if(dut==4) begin 133 | irqline = dut4_irq; 134 | end else if(dut==5) begin 135 | irqline = dut5_irq; 136 | end 137 | end 138 | endfunction 139 | 140 | task automatic set_timing_registers(input integer dut, 141 | input [1:0] sync_jump_width, input [5:0] baudrate_prescaler, 142 | input triple_sampling, input [2:0] tseg2, input [3:0] tseg1); 143 | 144 | begin 145 | // BRT0 146 | write_register(dut, 8'd6, {sync_jump_width, baudrate_prescaler}); 147 | // BTR1 148 | write_register(dut, 8'd7, {triple_sampling, tseg2, tseg1}); 149 | end 150 | endtask 151 | 152 | task automatic set_clockdivider_register(input integer dut, 153 | input extended_mode, // (PeliCAN mode) 154 | // CBP is always 0 155 | // RXINTEN is always 0 156 | // BIT4 is always 0 157 | input clock_off, 158 | input [2:0] clock_div); 159 | 160 | begin 161 | write_register(dut, 8'd31, { 162 | extended_mode, 3'b000, 163 | clock_off, clock_div}); 164 | end 165 | endtask 166 | 167 | task automatic set_mode_register(input integer dut, 168 | input sleep, input acceptance_filter, input self_test, 169 | input listen_only, input reset); 170 | // (only sensible for extended mode / PeliCAN mode) 171 | 172 | begin 173 | write_register(dut, 8'd0, { 174 | 3'b000, sleep, 175 | acceptance_filter, self_test, 176 | listen_only, reset}); 177 | end 178 | endtask 179 | 180 | task automatic set_interrupt_enable_register(input integer dut, 181 | input bus_error, input arbitration_lost, input error_passive, 182 | input wake_up, input data_overrun, input error_warning, 183 | input transmitted, input received); 184 | 185 | begin 186 | write_register(dut, 8'd4, { 187 | bus_error, arbitration_lost, 188 | error_passive, wake_up, 189 | data_overrun, error_warning, 190 | transmitted, received}); 191 | end 192 | endtask 193 | 194 | task automatic get_interrupt_register(input integer dut, output [7:0] interrupts); 195 | begin 196 | read_register(dut, 8'd3, interrupts); 197 | end 198 | endtask 199 | 200 | task automatic set_command_register(input integer dut, input [7:0] commands); 201 | begin 202 | write_register(dut, 8'd1, commands); 203 | end 204 | endtask 205 | 206 | task automatic setup_device_with_filters( 207 | input integer dut, 208 | input [1:0] sync_jump_width, 209 | input [5:0] baudrate_prescaler, 210 | input triple_sampling, 211 | input [2:0] tseg2, 212 | input [3:0] tseg1, 213 | input extended_mode, 214 | input acceptance_filter_mode, 215 | input [7:0] acode0, acode1, acode2, acode3, 216 | input [7:0] amask0, amask1, amask2, amask3); 217 | 218 | reg [7:0] tmp; 219 | begin 220 | // force into reset mode 221 | set_mode_register(dut, 0, acceptance_filter_mode, 0, 0, 1); 222 | 223 | set_clockdivider_register(dut, extended_mode, 0, 0); 224 | 225 | set_timing_registers(dut, sync_jump_width, baudrate_prescaler, 226 | triple_sampling, tseg2, tseg1); 227 | 228 | // send all interrupts 229 | set_interrupt_enable_register(dut, 1,1,1,1,1,1,1,1); 230 | 231 | // set acceptance filter to accept anything 232 | if(extended_mode) begin 233 | write_register(dut, 8'd16, acode0); 234 | write_register(dut, 8'd17, acode1); 235 | write_register(dut, 8'd18, acode2); 236 | write_register(dut, 8'd19, acode3); 237 | write_register(dut, 8'd20, amask0); 238 | write_register(dut, 8'd21, amask1); 239 | write_register(dut, 8'd22, amask2); 240 | write_register(dut, 8'd23, amask3); 241 | end else begin 242 | write_register(dut, 8'd04, acode0); 243 | write_register(dut, 8'd05, amask0); 244 | end 245 | 246 | // clear error counter 247 | write_register(dut, 8'd14, 8'h00); // RX error counter 248 | write_register(dut, 8'd15, 8'h00); // TX error counter 249 | 250 | // clear error code capture register 251 | read_register(dut, 8'd12, tmp); 252 | 253 | // clear any interrupts 254 | get_interrupt_register(dut, tmp); 255 | 256 | // leave reset mode 257 | set_mode_register(dut, 0, acceptance_filter_mode, 0, 0, 0); 258 | end 259 | endtask 260 | 261 | task automatic setup_device( 262 | input integer dut, 263 | input [1:0] sync_jump_width, 264 | input [5:0] baudrate_prescaler, 265 | input triple_sampling, 266 | input [2:0] tseg2, 267 | input [3:0] tseg1, 268 | input extended_mode); 269 | begin 270 | setup_device_with_filters(dut, sync_jump_width, baudrate_prescaler, 271 | triple_sampling, tseg2, tseg1, extended_mode, 272 | 0, 273 | 8'h00, 8'h00, 8'h00, 8'h00, 274 | 8'hff, 8'hff, 8'hff, 8'hff); 275 | end 276 | endtask 277 | 278 | task automatic send_frame(input integer dut, 279 | input remote_transmission_request, 280 | input extended_format, 281 | input [3:0] data_length, 282 | input [28:0] id, 283 | input [63:0] data); 284 | 285 | reg [63:0] data_dlc; 286 | 287 | begin 288 | write_register(dut, 8'd16, { 289 | extended_format, remote_transmission_request, 290 | 2'b00, 291 | data_length}); 292 | 293 | data_dlc = data << (8-data_length); 294 | 295 | if(extended_format) begin 296 | write_register(dut, 8'd17, id[28:21]); 297 | write_register(dut, 8'd18, id[20:13]); 298 | write_register(dut, 8'd19, id[12:5]); 299 | write_register(dut, 8'd20, {id[4:0], 3'b000}); 300 | write_register(dut, 8'd21, data_dlc[63:56]); 301 | write_register(dut, 8'd22, data_dlc[55:48]); 302 | write_register(dut, 8'd23, data_dlc[47:40]); 303 | write_register(dut, 8'd24, data_dlc[39:32]); 304 | write_register(dut, 8'd25, data_dlc[31:24]); 305 | write_register(dut, 8'd26, data_dlc[23:16]); 306 | write_register(dut, 8'd27, data_dlc[15:8]); 307 | write_register(dut, 8'd28, data_dlc[7:0]); 308 | end else begin 309 | write_register(dut, 8'd17, id[10:3]); 310 | write_register(dut, 8'd18, {id[2:0], 5'b00000}); 311 | write_register(dut, 8'd19, data_dlc[63:56]); 312 | write_register(dut, 8'd20, data_dlc[55:48]); 313 | write_register(dut, 8'd21, data_dlc[47:40]); 314 | write_register(dut, 8'd22, data_dlc[39:32]); 315 | write_register(dut, 8'd23, data_dlc[31:24]); 316 | write_register(dut, 8'd24, data_dlc[23:16]); 317 | write_register(dut, 8'd25, data_dlc[15:8]); 318 | write_register(dut, 8'd26, data_dlc[7:0]); 319 | end 320 | 321 | set_command_register(dut, 8'h01); // start transmit 322 | end 323 | endtask 324 | 325 | // verify that transmission on CAN bus has started 326 | // uses upstream `countdown` `bitclocks` `canbus_tap_rx` 327 | task automatic verify_transmit_started(input integer dut); 328 | begin 329 | // check device actually starts a transmit 330 | countdown = 2 * bitclocks; 331 | while((countdown!=0) && (canbus_tap_rx!=0)) begin 332 | @(posedge clk); 333 | end 334 | if(0==countdown) begin 335 | errors += 1; 336 | $error("DUT%d did not send data on can bus.", dut); 337 | end else begin 338 | countdown = 0; 339 | end 340 | end 341 | endtask 342 | 343 | // verify that transmission starts on CANbus, device triggers an interrupt, 344 | // and only the tx-complete interrupt is set. 345 | task automatic verify_transmit_finished(input integer dut); 346 | begin 347 | verify_transmit_started(dut); 348 | 349 | // check tx-complete interrupt 350 | countdown = (maximum_bits_between_ack_and_interrupt + maximum_bits_per_stuffed_extended_frame) * bitclocks; 351 | while((countdown != 0) && (irqline(dut_sender) != 0)) begin 352 | @(posedge clk); 353 | end 354 | if(0 == countdown) begin 355 | $error("DUT%d TX timeout", dut_sender); 356 | end else begin 357 | countdown = 0; 358 | get_interrupt_register(dut_sender, value); 359 | expect = 8'h02; 360 | if(value != expect) begin 361 | errors += 1; 362 | $error("DUT%d interrupt should be 'TX complete' (0x%02X) but is 0x%02X", 363 | dut_sender, expect, value); 364 | end 365 | end 366 | end 367 | endtask 368 | 369 | 370 | task automatic release_receive_buffer(input integer dut); 371 | begin 372 | set_command_register(dut, 8'h04); 373 | end 374 | endtask 375 | 376 | 377 | task automatic receive_frame(input integer dut, 378 | output remote_transmission_request, 379 | output received_extended_id, 380 | output [28:0] received_id, 381 | output [3:0] received_data_length, 382 | output [63:0] received_data); 383 | 384 | // NOTE this does not check if there actually is a frame queued in the buffer. 385 | // you need to do that before calling. 386 | 387 | reg [7:0] value; 388 | integer datareg_off; 389 | integer i; 390 | integer databyte; 391 | 392 | begin 393 | read_register(dut, 8'd16, value); 394 | received_extended_id = value[7]; 395 | received_data_length = value[3:0]; 396 | if(received_data_length[3] & |(received_data_length[2:0])) begin 397 | $error("insane DLC while receiving frame: %d. truncating to 8.\n", received_data_length); 398 | //received_data_length = 8; 399 | end 400 | 401 | received_id = 0; 402 | if(received_extended_id) begin 403 | read_register(dut, 8'd17, value); 404 | received_id[28:21] = value; 405 | read_register(dut, 8'd18, value); 406 | received_id[20:13] = value; 407 | read_register(dut, 8'd19, value); 408 | received_id[12:5] = value; 409 | read_register(dut, 8'd20, value); 410 | received_id[4:0] = value[7:3]; 411 | datareg_off = 21; 412 | end else begin 413 | read_register(dut, 8'd17, value); 414 | received_id[10:3] = value; 415 | read_register(dut, 8'd18, value); 416 | received_id[2:0] = value[7:5]; 417 | datareg_off = 19; 418 | end 419 | 420 | received_data = 0; 421 | for(i = 0; i < received_data_length; i=i+1) begin 422 | read_register(dut, datareg_off + i, value); 423 | // circumvent use of variable array index... 424 | databyte = received_data_length - i - 1; 425 | if(7 == databyte) begin 426 | received_data[63:56] = value; 427 | end else if(6 == databyte) begin 428 | received_data[55:48] = value; 429 | end else if(5 == databyte) begin 430 | received_data[47:40] = value; 431 | end else if(4 == databyte) begin 432 | received_data[39:32] = value; 433 | end else if(3 == databyte) begin 434 | received_data[31:24] = value; 435 | end else if(2 == databyte) begin 436 | received_data[23:16] = value; 437 | end else if(1 == databyte) begin 438 | received_data[15:8] = value; 439 | end else if(0 == databyte) begin 440 | received_data[7:0] = value; 441 | end 442 | end 443 | 444 | release_receive_buffer(dut); 445 | end 446 | endtask 447 | 448 | task automatic receive_and_verify_frame(input integer dut, 449 | input expected_remote_transmission_request, 450 | input expected_extended_id, 451 | input [28:0] expected_id, 452 | input [3:0] expected_data_length, 453 | input [63:0] expected_data, 454 | output [1:0] errors); 455 | 456 | reg received_remote_transmission_request; 457 | reg received_extended_id; 458 | reg [28:0] received_id; 459 | reg [3:0] received_data_length; 460 | reg [63:0] received_data; 461 | 462 | begin 463 | errors = 2'h0; 464 | 465 | receive_frame(dut, received_remote_transmission_request, received_extended_id, received_id, received_data_length, received_data); 466 | 467 | if(received_remote_transmission_request != expected_remote_transmission_request) begin 468 | $error("DUT%d RTR flag: got %d should be %d", 469 | dut, received_remote_transmission_request, expected_remote_transmission_request); 470 | errors = errors + 1; 471 | end 472 | 473 | if(received_extended_id != expected_extended_id) begin 474 | $error("DUT%d extended ID flag: got %d should be %d", 475 | dut, received_extended_id, expected_extended_id); 476 | errors = errors + 1; 477 | end 478 | 479 | if(received_id != expected_id) begin 480 | $error("DUT%d ID: got 0x%08x should be 0x%08x\n", 481 | dut, received_id, expected_id); 482 | errors = errors + 1; 483 | end 484 | 485 | if(received_data_length != expected_data_length) begin 486 | $error("DUT%d DLC: got %d should be %d\n", 487 | dut, received_data_length, expected_data_length); 488 | errors = errors + 1; 489 | end 490 | 491 | if(received_data != expected_data) begin 492 | $error("DUT%d data: got 0x%016x should be 0x%016x\n", 493 | dut, received_data, expected_data); 494 | errors = errors + 1; 495 | end 496 | end 497 | endtask 498 | -------------------------------------------------------------------------------- /testbench/test_acceptance_filter.v: -------------------------------------------------------------------------------- 1 | /* vim: colorcolumn=80 2 | * 3 | * This file is part of a verilog CAN controller that is SJA1000 compatible. 4 | * 5 | * Authors: 6 | * * David Piegdon 7 | * Picked up project for cleanup and bugfixes in 2019 8 | * 9 | * Any additional information is available in the LICENSE file. 10 | * 11 | * Copyright (C) 2019 Authors 12 | * 13 | * This source file may be used and distributed without restriction provided 14 | * that this copyright statement is not removed from the file and that any 15 | * derivative work contains the original copyright notice and the associated 16 | * disclaimer. 17 | * 18 | * This source file is free software; you can redistribute it and/or modify it 19 | * under the terms of the GNU Lesser General Public License as published by the 20 | * Free Software Foundation; either version 2.1 of the License, or (at your 21 | * option) any later version. 22 | * 23 | * This source is distributed in the hope that it will be useful, but WITHOUT 24 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 25 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 26 | * details. 27 | * 28 | * You should have received a copy of the GNU Lesser General Public License 29 | * along with this source; if not, download it from 30 | * http://www.opencores.org/lgpl.shtml 31 | * 32 | * The CAN protocol is developed by Robert Bosch GmbH and protected by patents. 33 | * Anybody who wants to implement this CAN IP core on silicon has to obtain 34 | * a CAN protocol license from Bosch. 35 | */ 36 | 37 | `default_nettype none 38 | 39 | module test_acceptance_filter(output reg finished, output reg [15:0] errors); 40 | /* 41 | * primary goals: 42 | * test acceptance filter when receiving frames. 43 | * secondary goals: 44 | * test basic frame transmission and receiption, 45 | * test controller in basic mode (dut 2), 46 | * test transmit/receive of different frames length. 47 | */ 48 | 49 | `include "testbench/fixture.inc" 50 | 51 | task automatic setup_devices(input reg [31:0] filter_id, input reg [31:0] filter_mask); 52 | begin 53 | // transmitting device 54 | setup_device(1, sync_jump_width, baudrate_prescaler, 55 | triple_sampling, tseg2, tseg1, 1); 56 | 57 | // basic mode, single short filter: 58 | // filter checks against id[10:3] 59 | setup_device_with_filters(2, sync_jump_width, baudrate_prescaler, 60 | triple_sampling, tseg2, tseg1, 0, 61 | 0, 62 | filter_id[10:3], 8'h00, 8'h00, 8'h00, 63 | filter_mask[10:3], 8'h00, 8'h00, 8'h00 64 | ); 65 | 66 | // extended mode, single long filter 67 | setup_device_with_filters(3, sync_jump_width, baudrate_prescaler, 68 | triple_sampling, tseg2, tseg1, 1, 69 | 1, 70 | filter_id[31:24], filter_id[23:16], filter_id[15:8], filter_id[7:0], 71 | filter_mask[31:24], filter_mask[23:16], filter_mask[15:8], filter_mask[7:0] 72 | ); 73 | 74 | // extended mode, double short filter, first slot 75 | setup_device_with_filters(4, sync_jump_width, baudrate_prescaler, 76 | triple_sampling, tseg2, tseg1, 1, 77 | 0, 78 | filter_id[31:24], filter_id[23:16], 8'h00, 8'h00, 79 | filter_mask[31:24], filter_mask[23:16], 8'h00, 8'h00 80 | ); 81 | 82 | // extended mode, double short filter, second slot 83 | setup_device_with_filters(5, sync_jump_width, baudrate_prescaler, 84 | triple_sampling, tseg2, tseg1, 1, 85 | 0, 86 | 8'h00, 8'h00, filter_id[31:24], filter_id[23:16], 87 | 8'h00, 8'h00, filter_mask[31:24], filter_mask[23:16] 88 | ); 89 | 90 | // BRP clocks are needed before we can do work with the bus. 91 | repeat (8 * bitclocks) @(posedge clk); 92 | end 93 | endtask 94 | 95 | task automatic receiption_ok(input integer dut_receiver); 96 | begin 97 | if(irqline(dut_receiver) != 0) begin 98 | errors += 1; 99 | $error("DUT%d did not trigger interrupt line", dut_receiver); 100 | end 101 | 102 | get_interrupt_register(dut_receiver, value); 103 | if(dut_receiver == 2) begin 104 | expect = 8'he1; // basic mode controller has always 0xe0 set. 105 | end else begin 106 | expect = 8'h01; 107 | end 108 | if(value != expect) begin 109 | errors += 1; 110 | $error("DUT%d interrupt should be 'RX complete' (0x%02X) but is 0x%02X", 111 | dut_receiver, expect, value); 112 | end 113 | 114 | value = get_rx_fifo_framecount(dut_receiver); 115 | expect = 1; 116 | if(value == expect) begin 117 | release_receive_buffer(dut_receiver); 118 | end else begin 119 | errors += 1; 120 | $error("DUT%d has %d frames in fifo, but there should be %d.", 121 | dut_receiver, value, expect); 122 | end 123 | 124 | repeat (5) @(posedge clk); 125 | 126 | expect = 0; 127 | value = get_rx_fifo_framecount(dut_receiver); 128 | if(value != 0) begin 129 | errors += 1; 130 | $error("DUT%d did not properly release buffer. Has %d in queue, should be %d", 131 | dut_receiver, value, expect); 132 | end 133 | end 134 | endtask 135 | 136 | localparam baudrate_prescaler = 6'h0; 137 | localparam sync_jump_width = 2'h1; 138 | localparam tseg1 = 4'h1; 139 | localparam tseg2 = 3'h0; 140 | localparam bitclocks = clocks_per_bit(baudrate_prescaler, tseg2, tseg1); 141 | 142 | localparam triple_sampling = 0; 143 | localparam extended_mode = 1; 144 | localparam remote_transmission_request = 0; 145 | 146 | integer dut_sender = 1; 147 | integer dut_receiver; 148 | integer value = 0; 149 | integer expect = 0; 150 | 151 | reg [31:0] filter_id; 152 | reg [31:0] bad_id; 153 | reg [31:0] filter_mask; 154 | reg [63:0] payload; 155 | reg [3:0] dlc; 156 | 157 | initial begin 158 | errors = 0; 159 | finished = 0; 160 | wait(start_test); 161 | 162 | filter_id = 32'h00000123; 163 | filter_mask = 32'h00000000; 164 | payload = 64'h0000_0000_0000_0000; 165 | dlc = 0; 166 | setup_devices(filter_id, filter_mask); 167 | send_frame(dut_sender, 0, 0, dlc, filter_id[28:0], payload); 168 | verify_transmit_finished(dut_sender); 169 | 170 | // check reception on other devices 171 | repeat (20) @(posedge clk); 172 | for(dut_receiver=2; dut_receiver<=5; dut_receiver=dut_receiver+1) begin 173 | receiption_ok(dut_receiver); 174 | end 175 | 176 | 177 | 178 | // FIXME 179 | finished = 1; 180 | end 181 | endmodule 182 | 183 | -------------------------------------------------------------------------------- /testbench/test_rx_tx.v: -------------------------------------------------------------------------------- 1 | /* vim: colorcolumn=80 2 | * 3 | * This file is part of a verilog CAN controller that is SJA1000 compatible. 4 | * 5 | * Authors: 6 | * * David Piegdon 7 | * Picked up project for cleanup and bugfixes in 2019 8 | * 9 | * Any additional information is available in the LICENSE file. 10 | * 11 | * Copyright (C) 2019 Authors 12 | * 13 | * This source file may be used and distributed without restriction provided 14 | * that this copyright statement is not removed from the file and that any 15 | * derivative work contains the original copyright notice and the associated 16 | * disclaimer. 17 | * 18 | * This source file is free software; you can redistribute it and/or modify it 19 | * under the terms of the GNU Lesser General Public License as published by the 20 | * Free Software Foundation; either version 2.1 of the License, or (at your 21 | * option) any later version. 22 | * 23 | * This source is distributed in the hope that it will be useful, but WITHOUT 24 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 25 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 26 | * details. 27 | * 28 | * You should have received a copy of the GNU Lesser General Public License 29 | * along with this source; if not, download it from 30 | * http://www.opencores.org/lgpl.shtml 31 | * 32 | * The CAN protocol is developed by Robert Bosch GmbH and protected by patents. 33 | * Anybody who wants to implement this CAN IP core on silicon has to obtain 34 | * a CAN protocol license from Bosch. 35 | */ 36 | 37 | `default_nettype none 38 | 39 | module test_tx_rx(output reg finished, output reg [15:0] errors); 40 | /* 41 | * primary goals: 42 | * test transmit and receive of extended-id CAN frames on a bus. 43 | * secondary goals: 44 | * test basic data bus connectivity for 8051 and wishbone bus. 45 | */ 46 | 47 | `include "testbench/fixture.inc" 48 | 49 | localparam baudrate_prescaler = 6'h0; 50 | localparam sync_jump_width = 2'h1; 51 | localparam tseg1 = 4'hf; 52 | localparam tseg2 = 3'h2; 53 | localparam bitclocks = clocks_per_bit(baudrate_prescaler, tseg2, tseg1); 54 | 55 | localparam triple_sampling = 0; 56 | localparam extended_mode = 1; 57 | localparam remote_transmission_request = 0; 58 | 59 | integer i = 0; 60 | integer dut_sender = 0; 61 | integer dut_receiver = 0; 62 | 63 | integer value = 0; 64 | integer expect = 0; 65 | 66 | reg [28:0] tx_id; 67 | reg [3:0] tx_data_length; 68 | reg [63:0] tx_data; 69 | reg [1:0] rx_errors; 70 | 71 | initial begin 72 | finished = 0; 73 | errors = 0; 74 | wait(start_test); 75 | 76 | for(i=1; i<=5; i=i+1) begin 77 | setup_device(i, 78 | sync_jump_width, baudrate_prescaler, 79 | triple_sampling, tseg2, tseg1, extended_mode); 80 | end 81 | 82 | // BRP clocks are needed before we can do work with the bus. 83 | repeat (8 * bitclocks) @(posedge clk); 84 | 85 | // send from all DUTs and check that all other DUTs received. 86 | for(dut_sender=1; dut_sender<=5; dut_sender=dut_sender+1) begin 87 | // make sure bus is idle 88 | if(1!=canbus_tap_rx) begin 89 | errors += 1; 90 | $error("CAN bus should be idle but is not."); 91 | end 92 | 93 | // transmit frame from one device 94 | tx_id = 28'h0123456+dut_sender; 95 | tx_data_length = 8; 96 | tx_data = 64'hdead_beef_badc_0ffe+dut_sender; 97 | send_frame(dut_sender, remote_transmission_request, extended_mode, tx_data_length, tx_id, tx_data); 98 | verify_transmit_finished(dut_sender); 99 | 100 | // check reception on other devices 101 | repeat (20) @(posedge clk); 102 | for(dut_receiver=1; dut_receiver<=5; dut_receiver=dut_receiver+1) begin 103 | if(dut_receiver != dut_sender) begin 104 | get_interrupt_register(dut_receiver, value); 105 | expect = 8'h01; 106 | if(value != expect) begin 107 | errors += 1; 108 | $error("DUT%d interrupt should be 'RX complete' (0x%02X) but is 0x%02X", 109 | dut_receiver, expect, value); 110 | end 111 | 112 | value = get_rx_fifo_framecount(dut_receiver); 113 | expect = 1; 114 | if(value == expect) begin 115 | receive_and_verify_frame(dut_receiver, remote_transmission_request, extended_mode, tx_id, tx_data_length, tx_data, rx_errors); 116 | errors = errors + rx_errors; 117 | end else begin 118 | errors += 1; 119 | $error("DUT%d has %d frames in fifo, but there should be %d.", 120 | dut_receiver, value, expect); 121 | end 122 | end 123 | end 124 | 125 | // check that interrupts have not reappeared. 126 | for(i = 1; i <= 5; i=i+1) begin 127 | get_interrupt_register(i, value); 128 | expect = 8'h0; 129 | if(value != expect) begin 130 | errors += 1; 131 | $error("DUT%d interrupt should be 'NONE' (0x%02X) but is 0x%02X", 132 | i, expect, value); 133 | end 134 | end 135 | repeat (20) @(posedge clk); 136 | 137 | end 138 | 139 | finished = 1; 140 | end 141 | 142 | endmodule 143 | 144 | -------------------------------------------------------------------------------- /testbench/timings.inc: -------------------------------------------------------------------------------- 1 | /* vim: colorcolumn=80 syntax=verilog 2 | * 3 | * This file is part of a verilog CAN controller that is SJA1000 compatible. 4 | * 5 | * Authors: 6 | * * David Piegdon 7 | * Picked up project for cleanup and bugfixes in 2019 8 | * 9 | * Any additional information is available in the LICENSE file. 10 | * 11 | * Copyright (C) 2019 Authors 12 | * 13 | * This source file may be used and distributed without restriction provided 14 | * that this copyright statement is not removed from the file and that any 15 | * derivative work contains the original copyright notice and the associated 16 | * disclaimer. 17 | * 18 | * This source file is free software; you can redistribute it and/or modify it 19 | * under the terms of the GNU Lesser General Public License as published by the 20 | * Free Software Foundation; either version 2.1 of the License, or (at your 21 | * option) any later version. 22 | * 23 | * This source is distributed in the hope that it will be useful, but WITHOUT 24 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 25 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 26 | * details. 27 | * 28 | * You should have received a copy of the GNU Lesser General Public License 29 | * along with this source; if not, download it from 30 | * http://www.opencores.org/lgpl.shtml 31 | * 32 | * The CAN protocol is developed by Robert Bosch GmbH and protected by patents. 33 | * Anybody who wants to implement this CAN IP core on silicon has to obtain 34 | * a CAN protocol license from Bosch. 35 | */ 36 | 37 | /* 38 | * This file defines timing constants. 39 | * 40 | * Just include this file *inside* your testbench module and add the test code. 41 | */ 42 | 43 | // maximum frame lengths 44 | localparam maximum_bits_per_basic_frame = 1+11+1+2+4+8*8+15+1+2+7; 45 | localparam maximum_bits_per_extended_frame = 1+29+1+2+4+8*8+15+1+2+7; 46 | localparam maximum_bits_per_stuffed_basic_frame = maximum_bits_per_basic_frame + maximum_bits_per_basic_frame/5; 47 | localparam maximum_bits_per_stuffed_extended_frame = maximum_bits_per_extended_frame + maximum_bits_per_extended_frame/5; 48 | 49 | // maximum time (in bits) between an acknowledge and the corresponding interrupt being triggered 50 | localparam maximum_bits_between_ack_and_interrupt = 9; 51 | 52 | // this yields the length of a single bit on the CAN bus, as 53 | // configured by the given parameters, in terms of a single master clocks 54 | function automatic [15:0] clocks_per_bit(input [5:0] baudrate_prescaler, input [2:0] tseg2, input [3:0] tseg1); 55 | begin 56 | clocks_per_bit = 2 * (baudrate_prescaler+1) * (1 + tseg1+1 + tseg2+1); 57 | end 58 | endfunction 59 | 60 | --------------------------------------------------------------------------------