├── .gitignore ├── README.md ├── cocotb ├── README.md ├── makefile ├── model │ ├── __init__.py │ ├── adders.py │ └── alu_nzvc.py └── tests │ ├── test_adder4.py │ ├── test_addsub4.py │ ├── test_alu8.py │ ├── test_alu_nzvc.py │ ├── test_full_adder.py │ ├── test_half_adder.py │ └── test_master.py ├── impl └── pipeline.xdc ├── makefile ├── rtl ├── adder4.vhd ├── addsub4.vhd ├── alu1.vhd ├── alu8.vhd ├── alu_nzvc.vhd ├── barrel_shifter.vhd ├── bram.vhd ├── cla.vhd ├── counter.vhd ├── decoder2.vhd ├── demux4.vhd ├── dff.vhd ├── dlatch.vhd ├── dram.vhd ├── dualram.vhd ├── fifo_async.vhd ├── fifo_sync.vhd ├── fsm.vhd ├── fsm_counter.vhd ├── fsm_serializer.vhd ├── fsm_serializer_mc.vhd ├── full_adder.vhd ├── half_adder.vhd ├── hamming.vhd ├── mux2.vhd ├── mux4.vhd ├── parity.vhd ├── pipeline.vhd ├── priority.vhd ├── pulse_generator.vhd ├── rca.vhd ├── read_only_mem.vhd ├── rgb2grey.vhd ├── rgb2yuv.vhd └── shift_register.vhd ├── tb ├── tb_adder4.vhd ├── tb_addsub4.vhd ├── tb_counter.vhd ├── tb_dualram.vhd ├── tb_fifo.vhd ├── tb_fsm.vhd ├── tb_fsm_counter.vhd ├── tb_fsm_serializer.vhd ├── tb_full_adder.vhd ├── tb_half_adder.vhd ├── tb_hamming.vhd ├── tb_parity.vhd ├── tb_pipeline.vhd ├── tb_priority.vhd ├── tb_rgb2grey.vhd └── tb_rgb2yuv.vhd └── tools ├── ram_content.data └── rgb2yuv.py /.gitignore: -------------------------------------------------------------------------------- 1 | debug/ 2 | build/ 3 | sim_build/ 4 | __pycache__ 5 | _* -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vhdl-digital-design 2 | 3 | VHDL circuit examples for digital design course. 4 | 5 | Some of the designs might have multiple architecture implementations to show design options and variations. Watch out when you instantiate/synthesize the circuits. Basic testbench examples are also given for some of the circuits. Not all the designs are tested and verified, so feel free to send any fixes if you see any mistakes. 6 | 7 | ## Folders 8 | 9 | ``` 10 | rtl/ - circuits 11 | tb/ - testbenches for some of the circuits 12 | cocotb/ - cocotb examples for simulation 13 | ``` 14 | 15 | ## Usage 16 | 17 | - All the files under `rtl/` and `tb/` can be imported in your synthesis tool (e.g Vivado). 18 | - Optionally, you can use [GHDL](http://ghdl.free.fr), which is a cross-platform open-source simulator for VHDL language, to simulate the circuits. 19 | - Simulated results can be viewed using [GTKWave](http://gtkwave.sourceforge.net/) which is an open source waveform viewer. 20 | - Install *GHDL* and *GTKWave* and add them to your `PATH` 21 | - run `make` on the root folder to check syntax and analyze all designs 22 | 23 | example: 24 | 25 | ```bash 26 | $ make 27 | >>> check syntax on all designs... 28 | >>> analyzing designs... 29 | >>> completed... 30 | ``` 31 | 32 | - run `make simulate ARCHNAME=tbname` to run the given testbench and display waveform using *GTKWave* where `tbname` is any of the testbench names inside the [tb](tb/) directory. 33 | 34 | example: 35 | 36 | ```bash 37 | $ make simulate ARCHNAME=tb_counter 38 | >>> cleaning design... 39 | >>> done... 40 | >>> analyzing designs... 41 | >>> simulating design: tb/tb_counter.vhd 42 | tb/tb_counter.vhd:43:9:@510ns:(assertion note): completed 43 | >>> showing waveform for: tb/tb_counter.vhd 44 | 45 | GTKWave Analyzer v3.3.94 (w)1999-2018 BSI 46 | ... 47 | ``` 48 | 49 | - `100us` stop time is given for simulation by default. Optional `STOPTIME=` arg can be passed to makefile to change this value. 50 | 51 | example: 52 | 53 | ```bash 54 | make simulate ARCHNAME=tb_counter STOPTIME=1ms 55 | ``` 56 | 57 | ## Cocotb Support 58 | 59 | - [Cocotb](https://github.com/cocotb/cocotb) is a *co-simulation library* for writing VHDL and Verilog testbenches in Python. 60 | - Github page gives information about installation. 61 | - `cocotb/` directory has a couple models and examples along with a *makefile* to run tests. 62 | -------------------------------------------------------------------------------- /cocotb/README.md: -------------------------------------------------------------------------------- 1 | # Cocotb examples 2 | 3 | [Cocotb](https://github.com/potentialventures/cocotb) is a Python based cosimulation testbench environment for verifying VHDL/Verilog that uses GHDL/iverilog as backends. 4 | 5 | - install cocotb and set COCOTB environmental variable 6 | - run `make` from `cocotb/` directory 7 | - all models are under `cocotb/model/` directory 8 | - all tests are under `cocotb/tests/` directory 9 | 10 | additionally 11 | 12 | - `make COCOTB_REDUCED_LOG_FMT=1` for reduced log lines. (added in makefile by default) 13 | - `make TOPLEVEL=design_name MODULE=test_design_name` for changing tests 14 | 15 | example: 16 | 17 | - `make TOPLEVEL=full_adder MODULE=test_full_adder` 18 | - `make TOPLEVEL=alu_nzvc MODULE=test_alu_nzvc` 19 | -------------------------------------------------------------------------------- /cocotb/makefile: -------------------------------------------------------------------------------- 1 | # install cocotb and set COCOTB environmental variable 2 | # eg. COCOTB=../../tools/cocotb 3 | 4 | TOPLEVEL_LANG = vhdl 5 | SIM = ghdl 6 | 7 | # reduce logs 8 | export COCOTB_REDUCED_LOG_FMT=1 9 | 10 | include $(COCOTB)/makefiles/Makefile.inc 11 | include $(COCOTB)/makefiles/Makefile.sim 12 | 13 | ifeq ($(OS),Msys) 14 | export USER_DIR:=$(shell sh -c 'pwd -W') 15 | WPWD=$(shell sh -c 'pwd -W') 16 | PYTHONPATH := $(WPWD)/model;$(WPWD)/tests;$(PYTHONPATH) 17 | else 18 | export USER_DIR:=$(shell pwd) 19 | WPWD=$(shell pwd) 20 | PYTHONPATH := $(WPWD)/model:$(WPWD)/tests:$(PYTHONPATH) 21 | endif 22 | 23 | # add sources here. order is important 24 | VHDL_SOURCES += $(WPWD)/../rtl/half_adder.vhd 25 | VHDL_SOURCES += $(WPWD)/../rtl/full_adder.vhd 26 | VHDL_SOURCES += $(WPWD)/../rtl/adder4.vhd 27 | VHDL_SOURCES += $(WPWD)/../rtl/addsub4.vhd 28 | VHDL_SOURCES += $(WPWD)/../rtl/alu1.vhd 29 | VHDL_SOURCES += $(WPWD)/../rtl/alu8.vhd 30 | VHDL_SOURCES += $(WPWD)/../rtl/alu_nzvc.vhd 31 | 32 | TOPLEVEL := addsub4 33 | MODULE := test_addsub4 34 | -------------------------------------------------------------------------------- /cocotb/model/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcayci/vhdl-digital-design/0bc765787b5963a7215f5e4b6db08bc9281e538a/cocotb/model/__init__.py -------------------------------------------------------------------------------- /cocotb/model/adders.py: -------------------------------------------------------------------------------- 1 | # all the adder models 2 | 3 | def xor(a, b): 4 | return (a & (~b)) | ((~a) & b) 5 | 6 | def half_adder_model(a, b): 7 | """ 8 | half adder model 9 | """ 10 | s = xor(a, b) 11 | c = a and b 12 | return s, c 13 | 14 | 15 | def full_adder_model(a, b, cin): 16 | """ 17 | full adder model 18 | """ 19 | 20 | m = xor(a, b) 21 | s = xor(m, cin) 22 | cout = (a and b) or (cin and m) 23 | 24 | return s, cout 25 | 26 | 27 | def adder4_model(a, b, cin): 28 | """ 29 | 4-bit adder model 30 | """ 31 | 32 | s = a + b + cin 33 | if s > 15: 34 | cout = 1 35 | s = s % 16 36 | else: 37 | cout = 0 38 | 39 | # overflow calculation 40 | # two negatives give positive or 41 | # two positives give negative 42 | if a > 7 and b > 7 and s < 8: 43 | v = 1 44 | elif a < 8 and b < 8 and s > 7: 45 | v = 1 46 | else: 47 | v = 0 48 | 49 | return s, cout, v 50 | 51 | 52 | def addsub4_model(a, b, m): 53 | """ 54 | 4-bit adder/subtractor model 55 | """ 56 | 57 | # add 58 | if m == 0: 59 | s = a + b + m 60 | if s > 15: 61 | cout = 1 62 | s = s % 16 63 | else: 64 | cout = 0 65 | 66 | # sub 67 | elif m == 1: 68 | s = a - b 69 | if s < 0: 70 | cout = 0 71 | s = 16 + s 72 | else: 73 | cout = 1 74 | 75 | # overflow calculation 76 | # two negatives give positive or 77 | # two positives give negative 78 | if a > 7 and b > 7 and s < 8: 79 | v = 1 80 | elif a < 8 and b < 8 and s > 7: 81 | v = 1 82 | else: 83 | v = 0 84 | 85 | return s, cout, v 86 | -------------------------------------------------------------------------------- /cocotb/model/alu_nzvc.py: -------------------------------------------------------------------------------- 1 | # alu_nzvc model 2 | 3 | # 0 a + b 4 | # 1 a - b 5 | # 2 a and b 6 | # 3 a or b 7 | # 4 a nor b 8 | # 5 a xor b 9 | # 6 a < b 10 | # 7 not a 11 | 12 | # constants 13 | INT_MAX = 2**31-1 14 | INT_MIN = -2**31 15 | UINT_MAX = 2**32-1 16 | 17 | def xor(a, b): 18 | return (a & (~b)) | ((~a) & b) 19 | 20 | 21 | def alu_add_model(a, b, op): 22 | '''alu ADD model''' 23 | 24 | # opcode for ADD is 0 25 | assert(0 == op) 26 | 27 | # sum a and b 28 | r = a + b 29 | 30 | # check if r is bigger than 32 bits, if so trim it 31 | # and set carry flag 32 | if r > UINT_MAX: 33 | r = r % (UINT_MAX + 1) 34 | c = 1 35 | else: 36 | c = 0 37 | 38 | # check for overflow, + + > - or - - > + 39 | if a <= INT_MAX and b <= INT_MAX: 40 | if r > INT_MAX: 41 | v = 1 42 | else: 43 | v = 0 44 | elif a > INT_MAX and b > INT_MAX: 45 | if r <= INT_MAX: 46 | v = 1 47 | else: 48 | v = 0 49 | else: 50 | v = 0 51 | 52 | # zero flag 53 | z = 1 if r == 0 else 0 54 | 55 | # negative flag 56 | n = 1 if r > INT_MAX else 0 57 | 58 | return r, n, z, v, c 59 | 60 | 61 | def alu_sub_model(a, b, op): 62 | '''alu SUB model''' 63 | 64 | # opcode for SUB is 1 65 | assert(1 == op) 66 | 67 | # a - b 68 | r = a - b 69 | 70 | # check if r is smaller than 0, if so trim it 71 | # and set carry flag 72 | if r < 0: 73 | r = int(format(r % (1 << 32), '032b'), base=2) 74 | c = 0 75 | else: 76 | c = 1 77 | 78 | # check for overflow, + + > - or - - > + 79 | if a <= INT_MAX and b <= INT_MAX: 80 | if r > INT_MAX: 81 | v = 1 82 | else: 83 | v = 0 84 | elif a > INT_MAX and b > INT_MAX: 85 | if r <= INT_MAX: 86 | v = 1 87 | else: 88 | v = 0 89 | else: 90 | v = 0 91 | 92 | # zero flag 93 | z = 1 if r == 0 else 0 94 | 95 | # negative flag 96 | n = 1 if r > INT_MAX else 0 97 | 98 | return r, n, z, v, c 99 | 100 | 101 | 102 | def alu_and_model(a, b, op): 103 | '''alu AND model''' 104 | 105 | # opcode for AND is 2 106 | assert(2 == op) 107 | 108 | # and a and b 109 | r = a & b 110 | 111 | # carry flag : should always be zero 112 | c = 0 113 | 114 | # check for overflow, + + > - or - - > + 115 | if a <= INT_MAX and b <= INT_MAX: 116 | if r > INT_MAX: 117 | v = 1 118 | else: 119 | v = 0 120 | elif a > INT_MAX and b > INT_MAX: 121 | if r <= INT_MAX: 122 | v = 1 123 | else: 124 | v = 0 125 | else: 126 | v = 0 127 | 128 | # zero flag 129 | z = 1 if r == 0 else 0 130 | 131 | # negative flag 132 | n = 1 if r > INT_MAX else 0 133 | 134 | return r, n, z, v, c 135 | 136 | 137 | def alu_or_model(a, b, op): 138 | '''alu OR model''' 139 | 140 | # opcode for OR is 3 141 | assert(3 == op) 142 | 143 | # a or b 144 | r = a | b 145 | 146 | # carry flag : should always be zero 147 | c = 0 148 | 149 | # check for overflow, + + > - or - - > + 150 | if a <= INT_MAX and b <= INT_MAX: 151 | if r > INT_MAX: 152 | v = 1 153 | else: 154 | v = 0 155 | elif a > INT_MAX and b > INT_MAX: 156 | if r <= INT_MAX: 157 | v = 1 158 | else: 159 | v = 0 160 | else: 161 | v = 0 162 | 163 | # zero flag 164 | z = 1 if r == 0 else 0 165 | 166 | # negative flag 167 | n = 1 if r > INT_MAX else 0 168 | 169 | return r, n, z, v, c 170 | 171 | 172 | def alu_nor_model(a, b, op): 173 | '''alu NOR model''' 174 | 175 | # opcode for NOR is 3 176 | assert(4 == op) 177 | 178 | # not (a or b) 179 | r = UINT_MAX - (a | b) 180 | #r = int(format(r % (1 << 32), '032b'), base=2) 181 | 182 | # carry flag : should always be zero 183 | c = 0 184 | 185 | # check for overflow, + + > - or - - > + 186 | if a <= INT_MAX and b <= INT_MAX: 187 | if r > INT_MAX: 188 | v = 1 189 | else: 190 | v = 0 191 | elif a > INT_MAX and b > INT_MAX: 192 | if r <= INT_MAX: 193 | v = 1 194 | else: 195 | v = 0 196 | else: 197 | v = 0 198 | 199 | # zero flag 200 | z = 1 if r == 0 else 0 201 | 202 | # negative flag 203 | n = 1 if r > INT_MAX else 0 204 | 205 | return r, n, z, v, c 206 | 207 | 208 | def alu_xor_model(a, b, op): 209 | '''alu XOR model''' 210 | 211 | # opcode for XOR is 5 212 | assert(5 == op) 213 | 214 | # a xor b 215 | r = xor(a, b) 216 | 217 | # carry flag : should always be zero 218 | c = 0 219 | 220 | # check for overflow, + + > - or - - > + 221 | if a <= INT_MAX and b <= INT_MAX: 222 | if r > INT_MAX: 223 | v = 1 224 | else: 225 | v = 0 226 | elif a > INT_MAX and b > INT_MAX: 227 | if r <= INT_MAX: 228 | v = 1 229 | else: 230 | v = 0 231 | else: 232 | v = 0 233 | 234 | # zero flag 235 | z = 1 if r == 0 else 0 236 | 237 | # negative flag 238 | n = 1 if r > INT_MAX else 0 239 | 240 | return r, n, z, v, c 241 | 242 | 243 | def alu_slt_model(a, b, op): 244 | '''alu SLT model''' 245 | 246 | # opcode for SLT is 6 247 | assert(6 == op) 248 | 249 | # a < b 250 | r = 1 if a < b else 0 251 | 252 | # carry flag : should always be zero 253 | c = 0 254 | 255 | # check for overflow, + + > - or - - > + 256 | if a <= INT_MAX and b <= INT_MAX: 257 | if r > INT_MAX: 258 | v = 1 259 | else: 260 | v = 0 261 | elif a > INT_MAX and b > INT_MAX: 262 | if r <= INT_MAX: 263 | v = 1 264 | else: 265 | v = 0 266 | else: 267 | v = 0 268 | 269 | # zero flag 270 | z = 1 if r == 0 else 0 271 | 272 | # negative flag 273 | n = 0 274 | 275 | return r, n, z, v, c 276 | 277 | 278 | def alu_not_model(a, b, op): 279 | '''alu NOT model''' 280 | 281 | # opcode for NOT is 7 282 | assert(7 == op) 283 | 284 | r = ~a 285 | r = int(format(r % (1 << 32), '032b'), base=2) 286 | 287 | # carry flag : should always be zero 288 | c = 0 289 | 290 | # check for overflow, + + > - or - - > + 291 | if a <= INT_MAX and b <= INT_MAX: 292 | if r > INT_MAX: 293 | v = 1 294 | else: 295 | v = 0 296 | elif a > INT_MAX and b > INT_MAX: 297 | if r <= INT_MAX: 298 | v = 1 299 | else: 300 | v = 0 301 | else: 302 | v = 0 303 | 304 | # zero flag 305 | z = 1 if r == 0 else 0 306 | 307 | # negative flag 308 | n = 1 if r > INT_MAX else 0 309 | 310 | return r, n, z, v, c 311 | 312 | -------------------------------------------------------------------------------- /cocotb/tests/test_adder4.py: -------------------------------------------------------------------------------- 1 | # Test for adder4 module 2 | import cocotb 3 | from cocotb.triggers import Timer 4 | from cocotb.result import TestFailure 5 | from adders import adder4_model 6 | import random 7 | 8 | @cocotb.test() 9 | def adder4_simple(dut): 10 | """ 11 | adder4 simple test 12 | calculates 13 + 4 + 1 13 | """ 14 | 15 | a = 13 16 | b = 4 17 | cin = 1 18 | dut.a = a 19 | dut.b = b 20 | dut.cin = cin 21 | yield Timer(1, units='ns') 22 | 23 | # run model and get the results 24 | s, cout, v = adder4_model(a, b, cin) 25 | 26 | if dut.s != s: 27 | x = 'SUM ERROR!\n' 28 | x += 'added 0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, s) 29 | x += 'rtl resulted in s: 0x{:x}'.format(int(dut.s)) 30 | raise TestFailure(x) 31 | elif dut.cout != cout: 32 | x = 'CARRY ERROR!\n' 33 | x += 'added 0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, s) 34 | x += 'carry flag should be : 0b{:b}\n'.format(cout) 35 | x += 'rtl resulted in c: 0b{:b}'.format(int(dut.cout)) 36 | raise TestFailure(x) 37 | elif dut.v != v: 38 | x = 'OVERFLOW ERROR!\n' 39 | x += 'added 0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, s) 40 | x+= 'overflow flag should be : 0b{:b}\n'.format(v) 41 | x += 'rtl resulted in v: 0b{:b}'.format(int(dut.v)) 42 | #raise TestFailure(x) 43 | 44 | else: 45 | dut._log.info("passed!") 46 | 47 | 48 | @cocotb.test() 49 | def adder4_randomized(dut): 50 | """ 51 | adder4 randomized test 52 | test for 100 random inputs for a/b/cin 53 | """ 54 | 55 | for _ in range(100): 56 | a = random.randint(0, 15) 57 | b = random.randint(0, 15) 58 | cin = random.randint(0, 1) 59 | dut.a = a 60 | dut.b = b 61 | dut.cin = cin 62 | yield Timer(1, units='ns') 63 | 64 | # run model and get the results 65 | s, cout, v = adder4_model(a, b, cin) 66 | 67 | if dut.s != s: 68 | x = 'SUM ERROR!\n' 69 | x += 'added 0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, s) 70 | x += 'rtl resulted in s: 0x{:x}'.format(int(dut.s)) 71 | raise TestFailure(x) 72 | elif dut.cout != cout: 73 | x = 'CARRY ERROR!\n' 74 | x += 'added 0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, s) 75 | x += 'carry flag should be : 0b{:b}\n'.format(cout) 76 | x += 'rtl resulted in c: 0b{:b}'.format(int(dut.cout)) 77 | raise TestFailure(x) 78 | elif dut.v != v: 79 | x = 'OVERFLOW ERROR!\n' 80 | x += 'added 0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, s) 81 | x+= 'overflow flag should be : 0b{:b}\n'.format(v) 82 | x += 'rtl resulted in v: 0b{:b}'.format(int(dut.v)) 83 | raise TestFailure(x) 84 | 85 | -------------------------------------------------------------------------------- /cocotb/tests/test_addsub4.py: -------------------------------------------------------------------------------- 1 | # Test for addsub4 module 2 | import cocotb 3 | from cocotb.triggers import Timer 4 | from cocotb.result import TestFailure 5 | from adders import addsub4_model 6 | 7 | @cocotb.test() 8 | def addsub4_simple(dut): 9 | ''' 10 | addsub4 simple subtract test 11 | calculates 13 - 4 = 9 12 | ''' 13 | 14 | dut._log.info("OVERFLOW CHECK IS NOT IMPLEMENTED!") 15 | 16 | a = 13 17 | b = 4 18 | m = 1 19 | dut.a = a 20 | dut.b = b 21 | dut.m = m 22 | yield Timer(1, units='ns') 23 | 24 | # run model and get the results 25 | s, cout, v = addsub4_model(a, b, m) 26 | 27 | if dut.s != s: 28 | x = 'SUM ERROR!\n' 29 | x += 'added 0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, s) 30 | x += 'rtl resulted in s: 0x{:x}'.format(int(dut.s)) 31 | raise TestFailure(x) 32 | elif dut.cout != cout: 33 | x = 'CARRY ERROR!\n' 34 | x += 'added 0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, s) 35 | x += 'carry flag should be : 0b{:b}\n'.format(cout) 36 | x += 'rtl resulted in c: 0b{:b}'.format(int(dut.cout)) 37 | raise TestFailure(x) 38 | elif dut.v != v: 39 | x = 'OVERFLOW ERROR!\n' 40 | x += 'added 0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, s) 41 | x+= 'overflow flag should be : 0b{:b}\n'.format(v) 42 | x += 'rtl resulted in v: 0b{:b}'.format(int(dut.v)) 43 | #raise TestFailure(x) 44 | 45 | else: 46 | dut._log.info("passed!") 47 | 48 | 49 | @cocotb.test() 50 | def addsub4_randomized(dut): 51 | """ 52 | addsub4 randomized test 53 | test for 100 random inputs for a/b/m 54 | """ 55 | import random 56 | 57 | dut._log.info("OVERFLOW CHECK IS NOT IMPLEMENTED!") 58 | 59 | for _ in range(100): 60 | a = random.randint(0, 15) 61 | b = random.randint(0, 15) 62 | m = random.randint(0, 1) 63 | dut.a = a 64 | dut.b = b 65 | dut.m = m 66 | yield Timer(1, units='ns') 67 | 68 | # run model and get the results 69 | s, cout, v = addsub4_model(a, b, m) 70 | 71 | if dut.s != s: 72 | x = 'SUM ERROR!\n' 73 | x += 'added 0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, s) 74 | x += 'rtl resulted in s: 0x{:x}'.format(int(dut.s)) 75 | raise TestFailure(x) 76 | elif dut.cout != cout: 77 | x = 'CARRY ERROR!\n' 78 | x += 'added 0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, s) 79 | x += 'carry flag should be : 0b{:b}\n'.format(cout) 80 | x += 'rtl resulted in c: 0b{:b}'.format(int(dut.cout)) 81 | raise TestFailure(x) 82 | elif dut.v != v: 83 | x = 'OVERFLOW ERROR!\n' 84 | x += 'added 0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, s) 85 | x+= 'overflow flag should be : 0b{:b}\n'.format(v) 86 | x += 'rtl resulted in v: 0b{:b}'.format(int(dut.v)) 87 | #raise TestFailure(x) 88 | 89 | dut._log.info("all tests passed!") 90 | 91 | -------------------------------------------------------------------------------- /cocotb/tests/test_alu8.py: -------------------------------------------------------------------------------- 1 | # tests for alu8 unit 2 | 3 | # 0 a + b 4 | # 1 a - b 5 | # 2 a and b 6 | # 3 a or b 7 | # 4 a nor b 8 | # 5 a xor b 9 | # 6 a < b 10 | # 7 not a 11 | 12 | import cocotb 13 | from cocotb.triggers import Timer 14 | from cocotb.result import TestFailure 15 | from alu_nzvc import * 16 | 17 | @cocotb.test() 18 | def alu_add_single(dut): 19 | ''' 20 | alu ADD tests: 21 | - simple and operation: 22 | 13 add 1 = 14 23 | ''' 24 | 25 | a = 13 26 | b = 1 27 | op = 0 28 | dut.a = a 29 | dut.b = b 30 | dut.cin = 0 31 | dut.opcode = op 32 | yield Timer(1, units='ns') 33 | 34 | # run model and get the results 35 | r, n, z, v, c = alu_add_model(a, b, op) 36 | 37 | if dut.r != r: 38 | x = '0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, r) 39 | x += 'rtl resulted in r : 0x{:x}'.format(int(dut.r)) 40 | raise TestFailure(x) 41 | elif dut.cout != c: 42 | x = '0x{:x} and 0x{:x}, result is 0x{:x}\n'.format(a, b, r) 43 | x += 'carry out should be : c:{}\n'.format(c) 44 | x += 'rtl result in carry o: c:{}'.format(dut.cout) 45 | raise TestFailure(x) 46 | else: 47 | dut._log.info("all passed!") 48 | 49 | 50 | @cocotb.test() 51 | def alu_add_random(dut): 52 | ''' 53 | alu ADD tests: 54 | - random numbers 55 | ''' 56 | from random import randrange 57 | 58 | op = 0 59 | 60 | for _ in range(1000): 61 | a = randrange(0, UINT_MAX) 62 | b = randrange(0, UINT_MAX) 63 | dut.a = a 64 | dut.b = b 65 | dut.cin = 0 66 | dut.opcode = op 67 | yield Timer(1, units='ns') 68 | 69 | # run model and get the results 70 | r, n, z, v, c = alu_add_model(a, b, op) 71 | 72 | if dut.r != r: 73 | x = '0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, r) 74 | x += 'rtl resulted in r : 0x{:x}'.format(int(dut.r)) 75 | raise TestFailure(x) 76 | elif dut.cout != c: 77 | x = '0x{:x} and 0x{:x}, result is 0x{:x}\n'.format(a, b, r) 78 | x += 'carry out should be : c:{}\n'.format(c) 79 | x += 'rtl result in carry o: c:{}'.format(dut.cout) 80 | raise TestFailure(x) 81 | 82 | dut._log.info("all passed!") 83 | 84 | 85 | @cocotb.test() 86 | def alu_sub_single(dut): 87 | ''' 88 | alu SUB tests: 89 | - simple subtraction operation: 90 | 1 - 13 91 | ''' 92 | 93 | a = 1 94 | b = 13 95 | op = 1 96 | dut.a = a 97 | dut.b = b 98 | dut.cin = 0 99 | dut.opcode = op 100 | yield Timer(1, units='ns') 101 | 102 | # run model and get the results 103 | r, n, z, v, c = alu_sub_model(a, b, op) 104 | 105 | if dut.r != r: 106 | x = '0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, r) 107 | x += 'rtl resulted in r : 0x{:x}'.format(int(dut.r)) 108 | raise TestFailure(x) 109 | elif dut.cout != c: 110 | x = '0x{:x} and 0x{:x}, result is 0x{:x}\n'.format(a, b, r) 111 | x += 'carry out should be : c:{}\n'.format(c) 112 | x += 'rtl result in carry o: c:{}'.format(dut.cout) 113 | raise TestFailure(x) 114 | else: 115 | dut._log.info("all passed!") 116 | 117 | 118 | @cocotb.test() 119 | def alu_sub_random(dut): 120 | ''' 121 | alu SUB tests: 122 | - random numbers 123 | ''' 124 | from random import randrange 125 | 126 | op = 1 127 | 128 | for _ in range(1000): 129 | a = randrange(0, UINT_MAX) 130 | b = randrange(0, UINT_MAX) 131 | dut.a = a 132 | dut.b = b 133 | dut.cin = 0 134 | dut.opcode = op 135 | yield Timer(1, units='ns') 136 | 137 | # run model and get the results 138 | r, n, z, v, c = alu_sub_model(a, b, op) 139 | 140 | if dut.r != r: 141 | x = '0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, r) 142 | x += 'rtl resulted in r : 0x{:x}'.format(int(dut.r)) 143 | raise TestFailure(x) 144 | elif dut.cout != c: 145 | x = '0x{:x} and 0x{:x}, result is 0x{:x}\n'.format(a, b, r) 146 | x += 'carry out should be : c:{}\n'.format(c) 147 | x += 'rtl result in carry o: c:{}'.format(dut.cout) 148 | raise TestFailure(x) 149 | 150 | dut._log.info("all passed!") 151 | 152 | 153 | @cocotb.test() 154 | def alu_and_single(dut): 155 | ''' 156 | alu AND tests: 157 | - simple and operation: 158 | 13 and 1 = 1 159 | ''' 160 | 161 | a = 13 162 | b = 1 163 | op = 2 164 | dut.a = a 165 | dut.b = b 166 | dut.cin = 0 167 | dut.opcode = op 168 | yield Timer(1, units='ns') 169 | 170 | # run model and get the results 171 | r, n, z, v, c = alu_and_model(a, b, op) 172 | 173 | if dut.r != r: 174 | x = '0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, r) 175 | x += 'rtl resulted in r : 0x{:x}'.format(int(dut.r)) 176 | raise TestFailure(x) 177 | elif dut.cout != c: 178 | x = '0x{:x} and 0x{:x}, result is 0x{:x}\n'.format(a, b, r) 179 | x += 'carry out should be : c:{}\n'.format(c) 180 | x += 'rtl result in carry o: c:{}'.format(dut.cout) 181 | raise TestFailure(x) 182 | else: 183 | dut._log.info("all passed!") 184 | 185 | 186 | @cocotb.test() 187 | def alu_and_random(dut): 188 | ''' 189 | alu AND tests: 190 | - random numbers 191 | ''' 192 | from random import randrange 193 | 194 | op = 2 195 | 196 | for _ in range(1000): 197 | a = randrange(0, UINT_MAX) 198 | b = randrange(0, UINT_MAX) 199 | dut.a = a 200 | dut.b = b 201 | dut.cin = 0 202 | dut.opcode = op 203 | yield Timer(1, units='ns') 204 | 205 | # run model and get the results 206 | r, n, z, v, c = alu_and_model(a, b, op) 207 | 208 | if dut.r != r: 209 | x = '0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, r) 210 | x += 'rtl resulted in r : 0x{:x}'.format(int(dut.r)) 211 | raise TestFailure(x) 212 | elif dut.cout != c: 213 | x = '0x{:x} and 0x{:x}, result is 0x{:x}\n'.format(a, b, r) 214 | x += 'carry out should be : c:{}\n'.format(c) 215 | x += 'rtl result in carry o: c:{}'.format(dut.cout) 216 | raise TestFailure(x) 217 | 218 | dut._log.info("all passed!") 219 | 220 | 221 | @cocotb.test() 222 | def alu_or_single(dut): 223 | ''' 224 | alu OR tests: 225 | - simple or operation: 226 | 12 or 1 = 13 227 | ''' 228 | 229 | a = 12 230 | b = 1 231 | op = 3 232 | dut.a = a 233 | dut.b = b 234 | dut.cin = 0 235 | dut.opcode = op 236 | yield Timer(1, units='ns') 237 | 238 | # run model and get the results 239 | r, n, z, v, c = alu_or_model(a, b, op) 240 | 241 | if dut.r != r: 242 | x = '0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, r) 243 | x += 'rtl resulted in r : 0x{:x}'.format(int(dut.r)) 244 | raise TestFailure(x) 245 | elif dut.cout != c: 246 | x = '0x{:x} and 0x{:x}, result is 0x{:x}\n'.format(a, b, r) 247 | x += 'carry out should be : c:{}\n'.format(c) 248 | x += 'rtl result in carry o: c:{}'.format(dut.cout) 249 | raise TestFailure(x) 250 | else: 251 | dut._log.info("all passed!") 252 | 253 | 254 | @cocotb.test() 255 | def alu_or_random(dut): 256 | ''' 257 | alu OR tests: 258 | - random numbers 259 | ''' 260 | from random import randrange 261 | 262 | op = 3 263 | 264 | for _ in range(1000): 265 | a = randrange(0, UINT_MAX) 266 | b = randrange(0, UINT_MAX) 267 | dut.a = a 268 | dut.b = b 269 | dut.cin = 0 270 | dut.opcode = op 271 | yield Timer(1, units='ns') 272 | 273 | # run model and get the results 274 | r, n, z, v, c = alu_or_model(a, b, op) 275 | 276 | if dut.r != r: 277 | x = '0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, r) 278 | x += 'rtl resulted in r : 0x{:x}'.format(int(dut.r)) 279 | raise TestFailure(x) 280 | elif dut.cout != c: 281 | x = '0x{:x} and 0x{:x}, result is 0x{:x}\n'.format(a, b, r) 282 | x += 'carry out should be : c:{}\n'.format(c) 283 | x += 'rtl result in carry o: c:{}'.format(dut.cout) 284 | raise TestFailure(x) 285 | 286 | dut._log.info("all passed!") 287 | 288 | 289 | @cocotb.test() 290 | def alu_nor_single(dut): 291 | ''' 292 | alu NOR tests: 293 | - simple NOR operation: 294 | 12 nor 1 295 | ''' 296 | 297 | a = 12 298 | b = 1 299 | op = 4 300 | dut.a = a 301 | dut.b = b 302 | dut.cin = 0 303 | dut.opcode = op 304 | yield Timer(1, units='ns') 305 | 306 | # run model and get the results 307 | r, n, z, v, c = alu_nor_model(a, b, op) 308 | 309 | if dut.r != r: 310 | x = '0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, r) 311 | x += 'rtl resulted in r : 0x{:x}'.format(int(dut.r)) 312 | raise TestFailure(x) 313 | elif dut.cout != c: 314 | x = '0x{:x} and 0x{:x}, result is 0x{:x}\n'.format(a, b, r) 315 | x += 'carry out should be : c:{}\n'.format(c) 316 | x += 'rtl result in carry o: c:{}'.format(dut.cout) 317 | raise TestFailure(x) 318 | else: 319 | dut._log.info("all passed!") 320 | 321 | 322 | @cocotb.test() 323 | def alu_nor_random(dut): 324 | ''' 325 | alu NOR tests: 326 | - random numbers 327 | ''' 328 | from random import randrange 329 | 330 | op = 4 331 | 332 | for _ in range(1000): 333 | a = randrange(0, UINT_MAX) 334 | b = randrange(0, UINT_MAX) 335 | dut.a = a 336 | dut.b = b 337 | dut.cin = 0 338 | dut.opcode = op 339 | yield Timer(1, units='ns') 340 | 341 | # run model and get the results 342 | r, n, z, v, c = alu_nor_model(a, b, op) 343 | 344 | if dut.r != r: 345 | x = '0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, r) 346 | x += 'rtl resulted in r : 0x{:x}'.format(int(dut.r)) 347 | raise TestFailure(x) 348 | elif dut.cout != c: 349 | x = '0x{:x} and 0x{:x}, result is 0x{:x}\n'.format(a, b, r) 350 | x += 'carry out should be : c:{}\n'.format(c) 351 | x += 'rtl result in carry o: c:{}'.format(dut.cout) 352 | raise TestFailure(x) 353 | 354 | dut._log.info("all passed!") 355 | 356 | 357 | @cocotb.test() 358 | def alu_xor_single(dut): 359 | ''' 360 | alu XOR tests: 361 | - simple Xor operation: 362 | 12 xor 1 = 13 363 | ''' 364 | 365 | a = 12 366 | b = 1 367 | op = 5 368 | dut.a = a 369 | dut.b = b 370 | dut.cin = 0 371 | dut.opcode = op 372 | yield Timer(1, units='ns') 373 | 374 | # run model and get the results 375 | r, n, z, v, c = alu_xor_model(a, b, op) 376 | 377 | if dut.r != r: 378 | x = '0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, r) 379 | x += 'rtl resulted in r : 0x{:x}'.format(int(dut.r)) 380 | raise TestFailure(x) 381 | elif dut.cout != c: 382 | x = '0x{:x} and 0x{:x}, result is 0x{:x}\n'.format(a, b, r) 383 | x += 'carry out should be : c:{}\n'.format(c) 384 | x += 'rtl result in carry o: c:{}'.format(dut.cout) 385 | raise TestFailure(x) 386 | else: 387 | dut._log.info("all passed!") 388 | 389 | 390 | @cocotb.test() 391 | def alu_xor_random(dut): 392 | ''' 393 | alu XOR tests: 394 | - random numbers 395 | ''' 396 | from random import randrange 397 | 398 | op = 5 399 | 400 | for _ in range(1000): 401 | a = randrange(0, UINT_MAX) 402 | b = randrange(0, UINT_MAX) 403 | dut.a = a 404 | dut.b = b 405 | dut.cin = 0 406 | dut.opcode = op 407 | yield Timer(1, units='ns') 408 | 409 | # run model and get the results 410 | r, n, z, v, c = alu_xor_model(a, b, op) 411 | 412 | if dut.r != r: 413 | x = '0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, r) 414 | x += 'rtl resulted in r : 0x{:x}'.format(int(dut.r)) 415 | raise TestFailure(x) 416 | elif dut.cout != c: 417 | x = '0x{:x} and 0x{:x}, result is 0x{:x}\n'.format(a, b, r) 418 | x += 'carry out should be : c:{}\n'.format(c) 419 | x += 'rtl result in carry o: c:{}'.format(dut.cout) 420 | raise TestFailure(x) 421 | 422 | dut._log.info("all passed!") 423 | 424 | 425 | @cocotb.test() 426 | def alu_slt_single(dut): 427 | ''' 428 | alu SLT tests: 429 | - simple set less than operation: 430 | 12 slt 1 = 0 431 | ''' 432 | 433 | a = 12 434 | b = 1 435 | op = 6 436 | dut.a = a 437 | dut.b = b 438 | dut.cin = 0 439 | dut.opcode = op 440 | yield Timer(1, units='ns') 441 | 442 | # run model and get the results 443 | r, n, z, v, c = alu_slt_model(a, b, op) 444 | 445 | if dut.r != r: 446 | x = '0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, r) 447 | x += 'rtl resulted in r : 0x{:x}'.format(int(dut.r)) 448 | raise TestFailure(x) 449 | elif dut.cout != c: 450 | x = '0x{:x} and 0x{:x}, result is 0x{:x}\n'.format(a, b, r) 451 | x += 'carry out should be : c:{}\n'.format(c) 452 | x += 'rtl result in carry o: c:{}'.format(dut.cout) 453 | raise TestFailure(x) 454 | else: 455 | dut._log.info("all passed!") 456 | 457 | 458 | @cocotb.test() 459 | def alu_slt_random(dut): 460 | ''' 461 | alu SLT tests: 462 | - random numbers 463 | ''' 464 | from random import randrange 465 | 466 | op = 6 467 | 468 | for _ in range(1000): 469 | a = randrange(0, UINT_MAX) 470 | b = randrange(0, UINT_MAX) 471 | dut.a = a 472 | dut.b = b 473 | dut.cin = 0 474 | dut.opcode = op 475 | yield Timer(1, units='ns') 476 | 477 | # run model and get the results 478 | r, n, z, v, c = alu_slt_model(a, b, op) 479 | 480 | if dut.r != r: 481 | x = '0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, r) 482 | x += 'rtl resulted in r : 0x{:x}'.format(int(dut.r)) 483 | raise TestFailure(x) 484 | elif dut.cout != c: 485 | x = '0x{:x} and 0x{:x}, result is 0x{:x}\n'.format(a, b, r) 486 | x += 'carry out should be : c:{}\n'.format(c) 487 | x += 'rtl result in carry o: c:{}'.format(dut.cout) 488 | raise TestFailure(x) 489 | 490 | dut._log.info("all passed!") 491 | 492 | 493 | 494 | @cocotb.test() 495 | def alu_not_single(dut): 496 | ''' 497 | alu NOT tests: 498 | - simple NOT operation: 499 | not 12 500 | ''' 501 | 502 | a = 12 503 | b = 1 504 | op = 7 505 | dut.a = a 506 | dut.b = b 507 | dut.cin = 0 508 | dut.opcode = op 509 | yield Timer(1, units='ns') 510 | 511 | # run model and get the results 512 | r, n, z, v, c = alu_not_model(a, b, op) 513 | 514 | if dut.r != r: 515 | x = '0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, r) 516 | x += 'rtl resulted in r : 0x{:x}'.format(int(dut.r)) 517 | raise TestFailure(x) 518 | elif dut.cout != c: 519 | x = '0x{:x} and 0x{:x}, result is 0x{:x}\n'.format(a, b, r) 520 | x += 'carry out should be : c:{}\n'.format(c) 521 | x += 'rtl result in carry o: c:{}'.format(dut.cout) 522 | raise TestFailure(x) 523 | else: 524 | dut._log.info("all passed!") 525 | 526 | 527 | @cocotb.test() 528 | def alu_not_random(dut): 529 | ''' 530 | alu NOT tests: 531 | - random numbers 532 | ''' 533 | from random import randrange 534 | 535 | op = 7 536 | 537 | for _ in range(1000): 538 | a = randrange(0, UINT_MAX) 539 | b = randrange(0, UINT_MAX) 540 | dut.a = a 541 | dut.b = b 542 | dut.cin = 0 543 | dut.opcode = op 544 | yield Timer(1, units='ns') 545 | 546 | # run model and get the results 547 | r, n, z, v, c = alu_not_model(a, b, op) 548 | 549 | if dut.r != r: 550 | x = '0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, r) 551 | x += 'rtl resulted in r : 0x{:x}'.format(int(dut.r)) 552 | raise TestFailure(x) 553 | elif dut.cout != c: 554 | x = '0x{:x} and 0x{:x}, result is 0x{:x}\n'.format(a, b, r) 555 | x += 'carry out should be : c:{}\n'.format(c) 556 | x += 'rtl result in carry out : c:{}'.format(dut.cout) 557 | raise TestFailure(x) 558 | 559 | dut._log.info("all passed!") 560 | 561 | -------------------------------------------------------------------------------- /cocotb/tests/test_alu_nzvc.py: -------------------------------------------------------------------------------- 1 | # tests for alu_nzvc unit 2 | 3 | # 0 a + b 4 | # 1 a - b 5 | # 2 a and b 6 | # 3 a or b 7 | # 4 a nor b 8 | # 5 a xor b 9 | # 6 a < b 10 | # 7 not a 11 | 12 | import cocotb 13 | from cocotb.triggers import Timer 14 | from cocotb.result import TestFailure 15 | from alu_nzvc import * 16 | 17 | @cocotb.test() 18 | def alu_add_single(dut): 19 | ''' 20 | alu ADD tests: 21 | - simple and operation: 22 | 13 add 1 = 14 23 | ''' 24 | 25 | a = 13 26 | b = 1 27 | op = 0 28 | dut.a = a 29 | dut.b = b 30 | dut.opcode = op 31 | yield Timer(1, units='ns') 32 | 33 | # run model and get the results 34 | r, n, z, v, c = alu_add_model(a, b, op) 35 | 36 | if dut.r != r: 37 | x = '0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, r) 38 | x += 'rtl resulted in r : 0x{:x}'.format(int(dut.r)) 39 | raise TestFailure(x) 40 | elif dut.n != n or dut.z != z or dut.v != v or dut.c != c: 41 | x = '0x{:x} and 0x{:x}, result is 0x{:x}\n'.format(a, b, r) 42 | x += 'flags should be : n:{} z:{} v:{} c:{}\n'.format(n, z, v, c) 43 | x += 'rtl result in o_flags: n:{} z:{} v:{} c:{}'.format(dut.n, dut.z, dut.v, dut.c) 44 | raise TestFailure(x) 45 | else: 46 | dut._log.info("all passed!") 47 | 48 | 49 | @cocotb.test() 50 | def alu_add_random(dut): 51 | ''' 52 | alu ADD tests: 53 | - random numbers 54 | ''' 55 | from random import randrange 56 | 57 | op = 0 58 | 59 | for _ in range(1000): 60 | a = randrange(0, UINT_MAX) 61 | b = randrange(0, UINT_MAX) 62 | dut.a = a 63 | dut.b = b 64 | dut.opcode = op 65 | yield Timer(1, units='ns') 66 | 67 | # run model and get the results 68 | r, n, z, v, c = alu_add_model(a, b, op) 69 | 70 | if dut.r != r: 71 | x = '0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, r) 72 | x += 'rtl resulted in r : 0x{:x}'.format(int(dut.r)) 73 | raise TestFailure(x) 74 | elif dut.n != n or dut.z != z or dut.v != v or dut.c != c: 75 | x = '0x{:x} and 0x{:x}, result is 0x{:x}\n'.format(a, b, r) 76 | x += 'flags should be : n:{} z:{} v:{} c:{}\n'.format(n, z, v, c) 77 | x += 'rtl result in o_flags: n:{} z:{} v:{} c:{}'.format(dut.n, dut.z, dut.v, dut.c) 78 | raise TestFailure(x) 79 | 80 | dut._log.info("all passed!") 81 | 82 | 83 | @cocotb.test() 84 | def alu_sub_single(dut): 85 | ''' 86 | alu SUB tests: 87 | - simple subtraction operation: 88 | 1 - 13 89 | ''' 90 | 91 | a = 1 92 | b = 13 93 | op = 1 94 | dut.a = a 95 | dut.b = b 96 | dut.opcode = op 97 | yield Timer(1, units='ns') 98 | 99 | # run model and get the results 100 | r, n, z, v, c = alu_sub_model(a, b, op) 101 | 102 | if dut.r != r: 103 | x = '0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, r) 104 | x += 'rtl resulted in r : 0x{:x}'.format(int(dut.r)) 105 | raise TestFailure(x) 106 | elif dut.n != n or dut.z != z or dut.v != v or dut.c != c: 107 | x = '0x{:x} and 0x{:x}, result is 0x{:x}\n'.format(a, b, r) 108 | x += 'flags should be : n:{} z:{} v:{} c:{}\n'.format(n, z, v, c) 109 | x += 'rtl result in o_flags: n:{} z:{} v:{} c:{}'.format(dut.n, dut.z, dut.v, dut.c) 110 | raise TestFailure(x) 111 | else: 112 | dut._log.info("all passed!") 113 | 114 | 115 | @cocotb.test() 116 | def alu_sub_random(dut): 117 | ''' 118 | alu SUB tests: 119 | - random numbers 120 | ''' 121 | from random import randrange 122 | 123 | op = 1 124 | 125 | for _ in range(1000): 126 | a = randrange(0, UINT_MAX) 127 | b = randrange(0, UINT_MAX) 128 | dut.a = a 129 | dut.b = b 130 | dut.opcode = op 131 | yield Timer(1, units='ns') 132 | 133 | # run model and get the results 134 | r, n, z, v, c = alu_sub_model(a, b, op) 135 | 136 | if dut.r != r: 137 | x = '0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, r) 138 | x += 'rtl resulted in r : 0x{:x}'.format(int(dut.r)) 139 | raise TestFailure(x) 140 | elif dut.n != n or dut.z != z or dut.v != v or dut.c != c: 141 | x = '0x{:x} and 0x{:x}, result is 0x{:x}\n'.format(a, b, r) 142 | x += 'flags should be : n:{} z:{} v:{} c:{}\n'.format(n, z, v, c) 143 | x += 'rtl result in o_flags: n:{} z:{} v:{} c:{}'.format(dut.n, dut.z, dut.v, dut.c) 144 | raise TestFailure(x) 145 | 146 | dut._log.info("all passed!") 147 | 148 | 149 | @cocotb.test() 150 | def alu_and_single(dut): 151 | ''' 152 | alu AND tests: 153 | - simple and operation: 154 | 13 and 1 = 1 155 | ''' 156 | 157 | a = 13 158 | b = 1 159 | op = 2 160 | dut.a = a 161 | dut.b = b 162 | dut.opcode = op 163 | yield Timer(1, units='ns') 164 | 165 | # run model and get the results 166 | r, n, z, v, c = alu_and_model(a, b, op) 167 | 168 | if dut.r != r: 169 | x = '0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, r) 170 | x += 'rtl resulted in r : 0x{:x}'.format(int(dut.r)) 171 | raise TestFailure(x) 172 | elif dut.n != n or dut.z != z or dut.v != v or dut.c != c: 173 | x = '0x{:x} and 0x{:x}, result is 0x{:x}\n'.format(a, b, r) 174 | x += 'flags should be : n:{} z:{} v:{} c:{}\n'.format(n, z, v, c) 175 | x += 'rtl result in o_flags: n:{} z:{} v:{} c:{}'.format(dut.n, dut.z, dut.v, dut.c) 176 | raise TestFailure(x) 177 | else: 178 | dut._log.info("all passed!") 179 | 180 | 181 | @cocotb.test() 182 | def alu_and_random(dut): 183 | ''' 184 | alu AND tests: 185 | - random numbers 186 | ''' 187 | from random import randrange 188 | 189 | op = 2 190 | 191 | for _ in range(1000): 192 | a = randrange(0, UINT_MAX) 193 | b = randrange(0, UINT_MAX) 194 | dut.a = a 195 | dut.b = b 196 | dut.opcode = op 197 | yield Timer(1, units='ns') 198 | 199 | # run model and get the results 200 | r, n, z, v, c = alu_and_model(a, b, op) 201 | 202 | if dut.r != r: 203 | x = '0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, r) 204 | x += 'rtl resulted in r : 0x{:x}'.format(int(dut.r)) 205 | raise TestFailure(x) 206 | elif dut.n != n or dut.z != z or dut.v != v or dut.c != c: 207 | x = '0x{:x} and 0x{:x}, result is 0x{:x}\n'.format(a, b, r) 208 | x += 'flags should be : n:{} z:{} v:{} c:{}\n'.format(n, z, v, c) 209 | x += 'rtl result in o_flags: n:{} z:{} v:{} c:{}'.format(dut.n, dut.z, dut.v, dut.c) 210 | raise TestFailure(x) 211 | 212 | dut._log.info("all passed!") 213 | 214 | 215 | @cocotb.test() 216 | def alu_or_single(dut): 217 | ''' 218 | alu OR tests: 219 | - simple or operation: 220 | 12 or 1 = 13 221 | ''' 222 | 223 | a = 12 224 | b = 1 225 | op = 3 226 | dut.a = a 227 | dut.b = b 228 | dut.opcode = op 229 | yield Timer(1, units='ns') 230 | 231 | # run model and get the results 232 | r, n, z, v, c = alu_or_model(a, b, op) 233 | 234 | if dut.r != r: 235 | x = '0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, r) 236 | x += 'rtl resulted in r : 0x{:x}'.format(int(dut.r)) 237 | raise TestFailure(x) 238 | elif dut.n != n or dut.z != z or dut.v != v or dut.c != c: 239 | x = '0x{:x} and 0x{:x}, result is 0x{:x}\n'.format(a, b, r) 240 | x += 'flags should be : n:{} z:{} v:{} c:{}\n'.format(n, z, v, c) 241 | x += 'rtl result in o_flags: n:{} z:{} v:{} c:{}'.format(dut.n, dut.z, dut.v, dut.c) 242 | raise TestFailure(x) 243 | else: 244 | dut._log.info("all passed!") 245 | 246 | 247 | @cocotb.test() 248 | def alu_or_random(dut): 249 | ''' 250 | alu OR tests: 251 | - random numbers 252 | ''' 253 | from random import randrange 254 | 255 | op = 3 256 | 257 | for _ in range(1000): 258 | a = randrange(0, UINT_MAX) 259 | b = randrange(0, UINT_MAX) 260 | dut.a = a 261 | dut.b = b 262 | dut.opcode = op 263 | yield Timer(1, units='ns') 264 | 265 | # run model and get the results 266 | r, n, z, v, c = alu_or_model(a, b, op) 267 | 268 | if dut.r != r: 269 | x = '0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, r) 270 | x += 'rtl resulted in r : 0x{:x}'.format(int(dut.r)) 271 | raise TestFailure(x) 272 | elif dut.n != n or dut.z != z or dut.v != v or dut.c != c: 273 | x = '0x{:x} and 0x{:x}, result is 0x{:x}\n'.format(a, b, r) 274 | x += 'flags should be : n:{} z:{} v:{} c:{}\n'.format(n, z, v, c) 275 | x += 'rtl result in o_flags: n:{} z:{} v:{} c:{}'.format(dut.n, dut.z, dut.v, dut.c) 276 | raise TestFailure(x) 277 | 278 | dut._log.info("all passed!") 279 | 280 | 281 | @cocotb.test() 282 | def alu_nor_single(dut): 283 | ''' 284 | alu NOR tests: 285 | - simple NOR operation: 286 | 12 nor 1 287 | ''' 288 | 289 | a = 12 290 | b = 1 291 | op = 4 292 | dut.a = a 293 | dut.b = b 294 | dut.opcode = op 295 | yield Timer(1, units='ns') 296 | 297 | # run model and get the results 298 | r, n, z, v, c = alu_nor_model(a, b, op) 299 | 300 | if dut.r != r: 301 | x = '0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, r) 302 | x += 'rtl resulted in r : 0x{:x}'.format(int(dut.r)) 303 | raise TestFailure(x) 304 | elif dut.n != n or dut.z != z or dut.v != v or dut.c != c: 305 | x = '0x{:x} and 0x{:x}, result is 0x{:x}\n'.format(a, b, r) 306 | x += 'flags should be : n:{} z:{} v:{} c:{}\n'.format(n, z, v, c) 307 | x += 'rtl result in o_flags: n:{} z:{} v:{} c:{}'.format(dut.n, dut.z, dut.v, dut.c) 308 | raise TestFailure(x) 309 | else: 310 | dut._log.info("all passed!") 311 | 312 | 313 | @cocotb.test() 314 | def alu_nor_random(dut): 315 | ''' 316 | alu NOR tests: 317 | - random numbers 318 | ''' 319 | from random import randrange 320 | 321 | op = 4 322 | 323 | for _ in range(1000): 324 | a = randrange(0, UINT_MAX) 325 | b = randrange(0, UINT_MAX) 326 | dut.a = a 327 | dut.b = b 328 | dut.opcode = op 329 | yield Timer(1, units='ns') 330 | 331 | # run model and get the results 332 | r, n, z, v, c = alu_nor_model(a, b, op) 333 | 334 | if dut.r != r: 335 | x = '0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, r) 336 | x += 'rtl resulted in r : 0x{:x}'.format(int(dut.r)) 337 | raise TestFailure(x) 338 | elif dut.n != n or dut.z != z or dut.v != v or dut.c != c: 339 | x = '0x{:x} and 0x{:x}, result is 0x{:x}\n'.format(a, b, r) 340 | x += 'flags should be : n:{} z:{} v:{} c:{}\n'.format(n, z, v, c) 341 | x += 'rtl result in o_flags: n:{} z:{} v:{} c:{}'.format(dut.n, dut.z, dut.v, dut.c) 342 | raise TestFailure(x) 343 | 344 | dut._log.info("all passed!") 345 | 346 | 347 | @cocotb.test() 348 | def alu_xor_single(dut): 349 | ''' 350 | alu XOR tests: 351 | - simple Xor operation: 352 | 12 xor 1 = 13 353 | ''' 354 | 355 | a = 12 356 | b = 1 357 | op = 5 358 | dut.a = a 359 | dut.b = b 360 | dut.opcode = op 361 | yield Timer(1, units='ns') 362 | 363 | # run model and get the results 364 | r, n, z, v, c = alu_xor_model(a, b, op) 365 | 366 | if dut.r != r: 367 | x = '0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, r) 368 | x += 'rtl resulted in r : 0x{:x}'.format(int(dut.r)) 369 | raise TestFailure(x) 370 | elif dut.n != n or dut.z != z or dut.v != v or dut.c != c: 371 | x = '0x{:x} and 0x{:x}, result is 0x{:x}\n'.format(a, b, r) 372 | x += 'flags should be : n:{} z:{} v:{} c:{}\n'.format(n, z, v, c) 373 | x += 'rtl result in o_flags: n:{} z:{} v:{} c:{}'.format(dut.n, dut.z, dut.v, dut.c) 374 | raise TestFailure(x) 375 | else: 376 | dut._log.info("all passed!") 377 | 378 | 379 | @cocotb.test() 380 | def alu_xor_random(dut): 381 | ''' 382 | alu XOR tests: 383 | - random numbers 384 | ''' 385 | from random import randrange 386 | 387 | op = 5 388 | 389 | for _ in range(1000): 390 | a = randrange(0, UINT_MAX) 391 | b = randrange(0, UINT_MAX) 392 | dut.a = a 393 | dut.b = b 394 | dut.opcode = op 395 | yield Timer(1, units='ns') 396 | 397 | # run model and get the results 398 | r, n, z, v, c = alu_xor_model(a, b, op) 399 | 400 | if dut.r != r: 401 | x = '0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, r) 402 | x += 'rtl resulted in r : 0x{:x}'.format(int(dut.r)) 403 | raise TestFailure(x) 404 | elif dut.n != n or dut.z != z or dut.v != v or dut.c != c: 405 | x = '0x{:x} and 0x{:x}, result is 0x{:x}\n'.format(a, b, r) 406 | x += 'flags should be : n:{} z:{} v:{} c:{}\n'.format(n, z, v, c) 407 | x += 'rtl result in o_flags: n:{} z:{} v:{} c:{}'.format(dut.n, dut.z, dut.v, dut.c) 408 | raise TestFailure(x) 409 | 410 | dut._log.info("all passed!") 411 | 412 | 413 | @cocotb.test() 414 | def alu_slt_single(dut): 415 | ''' 416 | alu SLT tests: 417 | - simple set less than operation: 418 | 12 slt 1 = 0 419 | ''' 420 | 421 | a = 12 422 | b = 1 423 | op = 6 424 | dut.a = a 425 | dut.b = b 426 | dut.opcode = op 427 | yield Timer(1, units='ns') 428 | 429 | # run model and get the results 430 | r, n, z, v, c = alu_slt_model(a, b, op) 431 | 432 | if dut.r != r: 433 | x = '0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, r) 434 | x += 'rtl resulted in r : 0x{:x}'.format(int(dut.r)) 435 | raise TestFailure(x) 436 | elif dut.n != n or dut.z != z or dut.v != v or dut.c != c: 437 | x = '0x{:x} and 0x{:x}, result is 0x{:x}\n'.format(a, b, r) 438 | x += 'flags should be : n:{} z:{} v:{} c:{}\n'.format(n, z, v, c) 439 | x += 'rtl result in o_flags: n:{} z:{} v:{} c:{}'.format(dut.n, dut.z, dut.v, dut.c) 440 | raise TestFailure(x) 441 | else: 442 | dut._log.info("all passed!") 443 | 444 | 445 | @cocotb.test() 446 | def alu_slt_random(dut): 447 | ''' 448 | alu SLT tests: 449 | - random numbers 450 | ''' 451 | from random import randrange 452 | 453 | op = 6 454 | 455 | for _ in range(1000): 456 | a = randrange(0, UINT_MAX) 457 | b = randrange(0, UINT_MAX) 458 | dut.a = a 459 | dut.b = b 460 | dut.opcode = op 461 | yield Timer(1, units='ns') 462 | 463 | # run model and get the results 464 | r, n, z, v, c = alu_slt_model(a, b, op) 465 | 466 | if dut.r != r: 467 | x = '0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, r) 468 | x += 'rtl resulted in r : 0x{:x}'.format(int(dut.r)) 469 | raise TestFailure(x) 470 | elif dut.n != n or dut.z != z or dut.v != v or dut.c != c: 471 | x = '0x{:x} and 0x{:x}, result is 0x{:x}\n'.format(a, b, r) 472 | x += 'flags should be : n:{} z:{} v:{} c:{}\n'.format(n, z, v, c) 473 | x += 'rtl result in o_flags: n:{} z:{} v:{} c:{}'.format(dut.n, dut.z, dut.v, dut.c) 474 | raise TestFailure(x) 475 | 476 | dut._log.info("all passed!") 477 | 478 | 479 | 480 | @cocotb.test() 481 | def alu_not_single(dut): 482 | ''' 483 | alu NOT tests: 484 | - simple NOT operation: 485 | not 12 486 | ''' 487 | 488 | a = 12 489 | b = 1 490 | op = 7 491 | dut.a = a 492 | dut.b = b 493 | dut.opcode = op 494 | yield Timer(1, units='ns') 495 | 496 | # run model and get the results 497 | r, n, z, v, c = alu_not_model(a, b, op) 498 | 499 | if dut.r != r: 500 | x = '0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, r) 501 | x += 'rtl resulted in r : 0x{:x}'.format(int(dut.r)) 502 | raise TestFailure(x) 503 | elif dut.n != n or dut.z != z or dut.v != v or dut.c != c: 504 | x = '0x{:x} and 0x{:x}, result is 0x{:x}\n'.format(a, b, r) 505 | x += 'flags should be : n:{} z:{} v:{} c:{}\n'.format(n, z, v, c) 506 | x += 'rtl result in o_flags: n:{} z:{} v:{} c:{}'.format(dut.n, dut.z, dut.v, dut.c) 507 | raise TestFailure(x) 508 | else: 509 | dut._log.info("all passed!") 510 | 511 | 512 | @cocotb.test() 513 | def alu_not_random(dut): 514 | ''' 515 | alu NOT tests: 516 | - random numbers 517 | ''' 518 | from random import randrange 519 | 520 | op = 7 521 | 522 | for _ in range(1000): 523 | a = randrange(0, UINT_MAX) 524 | b = randrange(0, UINT_MAX) 525 | dut.a = a 526 | dut.b = b 527 | dut.opcode = op 528 | yield Timer(1, units='ns') 529 | 530 | # run model and get the results 531 | r, n, z, v, c = alu_not_model(a, b, op) 532 | 533 | if dut.r != r: 534 | x = '0x{:x} and 0x{:x}, result is: 0x{:x}\n'.format(a, b, r) 535 | x += 'rtl resulted in r : 0x{:x}'.format(int(dut.r)) 536 | raise TestFailure(x) 537 | elif dut.n != n or dut.z != z or dut.v != v or dut.c != c: 538 | x = '0x{:x} and 0x{:x}, result is 0x{:x}\n'.format(a, b, r) 539 | x += 'flags should be : n:{} z:{} v:{} c:{}\n'.format(n, z, v, c) 540 | x += 'rtl result in o_flags: n:{} z:{} v:{} c:{}'.format(dut.n, dut.z, dut.v, dut.c) 541 | raise TestFailure(x) 542 | 543 | dut._log.info("all passed!") 544 | 545 | -------------------------------------------------------------------------------- /cocotb/tests/test_full_adder.py: -------------------------------------------------------------------------------- 1 | # Test for full adder module 2 | import cocotb 3 | from cocotb.triggers import Timer 4 | from cocotb.result import TestFailure 5 | from adders import full_adder_model 6 | import random 7 | 8 | @cocotb.test() 9 | def full_adder_simple(dut): 10 | """ 11 | full adder simple test 12 | calculates 1 + 0 + 1 13 | """ 14 | yield Timer(2) 15 | a = 1 16 | b = 0 17 | cin = 1 18 | dut.a = a 19 | dut.b = b 20 | dut.cin = cin 21 | yield Timer(2) 22 | 23 | # run model and get the results 24 | s, cout = full_adder_model(a, b, cin) 25 | 26 | if dut.s != s: 27 | x = "incorrect result for sum: {} != {}".format(dut.s, int(s)) 28 | raise TestFailure(x) 29 | elif dut.cout != cout: 30 | x = "incorrect result for carry: {} != {}".format(dut.cout, int(cout)) 31 | raise TestFailure(x) 32 | else: 33 | dut._log.info("passed!") 34 | 35 | 36 | @cocotb.test() 37 | def full_adder_randomized(dut): 38 | """ 39 | full adder randomized test 40 | test for 10 random inputs for x/y 41 | """ 42 | yield Timer(2) 43 | 44 | for _ in range(10): 45 | a = random.randint(0, 1) 46 | b = random.randint(0, 1) 47 | cin = random.randint(0, 1) 48 | dut.a = a 49 | dut.b = b 50 | dut.cin = cin 51 | yield Timer(2) 52 | 53 | # run model and get the results 54 | s, cout = full_adder_model(a, b, cin) 55 | 56 | if dut.s != s: 57 | x = "incorrect result for sum: {} != {}".format(dut.s, int(s)) 58 | raise TestFailure(x) 59 | elif dut.cout != cout: 60 | x = "incorrect result for carry: {} != {}".format(dut.cout, int(cout)) 61 | raise TestFailure(x) 62 | else: 63 | dut._log.info("passed!") 64 | -------------------------------------------------------------------------------- /cocotb/tests/test_half_adder.py: -------------------------------------------------------------------------------- 1 | # Test for half adder module 2 | import cocotb 3 | from cocotb.triggers import Timer 4 | from cocotb.result import TestFailure 5 | from adders import half_adder_model 6 | import random 7 | 8 | @cocotb.test() 9 | def half_adder_simple(dut): 10 | """ 11 | half adder simple test 12 | calculates 1 + 0 13 | """ 14 | yield Timer(2) 15 | x = 1 16 | y = 0 17 | dut.x = x 18 | dut.y = y 19 | yield Timer(2) 20 | 21 | # run model and get the results 22 | s, c = half_adder_model(x, y) 23 | 24 | if dut.s != s: 25 | x = "incorrect result for sum: {} != {}".format(dut.s, int(s)) 26 | raise TestFailure(x) 27 | elif dut.c != c: 28 | x = "incorrect result for carry: {} != {}".format(dut.c, int(c)) 29 | raise TestFailure(x) 30 | else: 31 | dut._log.info("passed!") 32 | 33 | 34 | @cocotb.test() 35 | def half_adder_randomized(dut): 36 | """ 37 | half adder randomized test 38 | test for 10 random inputs for x/y 39 | """ 40 | yield Timer(2) 41 | 42 | for _ in range(10): 43 | x = random.randint(0, 1) 44 | y = random.randint(0, 1) 45 | dut.x = x 46 | dut.y = y 47 | yield Timer(2) 48 | 49 | # run model and get the results 50 | s, c = half_adder_model(x, y) 51 | 52 | if dut.s != s: 53 | x = "incorrect result for sum: {} != {}".format(dut.s, int(s)) 54 | raise TestFailure(x) 55 | elif dut.c != c: 56 | x = "incorrect result for carry: {} != {}".format(dut.c, int(c)) 57 | raise TestFailure(x) 58 | else: 59 | dut._log.info("passed!") 60 | -------------------------------------------------------------------------------- /cocotb/tests/test_master.py: -------------------------------------------------------------------------------- 1 | # this is an example master file with all the tests imported 2 | # they need to share the same top module 3 | 4 | import cocotb 5 | from test_half_adder import * 6 | from test_full_adder import * 7 | from test_adder4 import * 8 | from test_addsub4 import * 9 | 10 | -------------------------------------------------------------------------------- /impl/pipeline.xdc: -------------------------------------------------------------------------------- 1 | # actual clk source 2 | create_clock -period 30.000 -name clk -waveform {0.000 15.000} [get_ports clk] 3 | 4 | #create_clock -period 30.000 -name clk 5 | set_input_delay -clock [get_clocks clk] -min -add_delay 0.100 [get_ports {a[*]}] 6 | set_input_delay -clock [get_clocks clk] -max -add_delay 0.100 [get_ports {a[*]}] 7 | set_input_delay -clock [get_clocks clk] -min -add_delay 0.100 [get_ports {b[*]}] 8 | set_input_delay -clock [get_clocks clk] -max -add_delay 0.100 [get_ports {b[*]}] 9 | set_input_delay -clock [get_clocks clk] -min -add_delay 0.100 [get_ports {c[*]}] 10 | set_input_delay -clock [get_clocks clk] -max -add_delay 0.100 [get_ports {c[*]}] 11 | set_input_delay -clock [get_clocks clk] -min -add_delay 0.100 [get_ports {d[*]}] 12 | set_input_delay -clock [get_clocks clk] -max -add_delay 0.100 [get_ports {d[*]}] 13 | 14 | set_output_delay -clock [get_clocks clk] -min -add_delay 0.100 [get_ports {x[*]}] 15 | set_output_delay -clock [get_clocks clk] -max -add_delay 0.100 [get_ports {x[*]}] 16 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | # author: Furkan Cayci, 2019 2 | # description: 3 | # add ghdl to your PATH for simulation 4 | # add gtkwave to your PATH for displaying waveform 5 | # run with make simulate ARCHNAME=tb_xxx STOPTIME=1us 6 | 7 | CC = ghdl 8 | SIM = gtkwave 9 | WORKDIR = debug 10 | QUIET = @ 11 | 12 | ARCHNAME?= tb_half_adder 13 | STOPTIME?= 100us 14 | 15 | # analyze these two first since some other circuits depend on these 16 | VHDL_SOURCES += rtl/half_adder.vhd 17 | VHDL_SOURCES += rtl/full_adder.vhd 18 | VHDL_SOURCES += rtl/adder4.vhd 19 | # add rest of the files in rtl directory for analyzing 20 | VHDL_SOURCES += $(wildcard rtl/*.vhd) 21 | #SRCS += $(wildcard impl/*.vhd) 22 | 23 | TBS = $(wildcard tb/tb_*.vhd) 24 | TB = tb/$(ARCHNAME).vhd 25 | 26 | CFLAGS += --std=08 # enable ieee 2008 standard 27 | CFLAGS += --warn-binding 28 | CFLAGS += --warn-no-library # turn off warning on design replace with same name 29 | 30 | .PHONY: all 31 | all: check analyze 32 | @echo ">>> completed..." 33 | 34 | .PHONY: check 35 | check: 36 | @echo ">>> check syntax on all designs..." 37 | $(QUIET)$(CC) -s $(CFLAGS) $(VHDL_SOURCES) $(TBS) 38 | 39 | .PHONY: analyze 40 | analyze: 41 | @echo ">>> analyzing designs..." 42 | $(QUIET)mkdir -p $(WORKDIR) 43 | $(QUIET)$(CC) -a $(CFLAGS) --workdir=$(WORKDIR) $(VHDL_SOURCES) $(TBS) 44 | 45 | .PHONY: simulate 46 | simulate: clean analyze 47 | @echo ">>> simulating design:" $(TB) 48 | $(QUIET)$(CC) --elab-run $(CFLAGS) --workdir=$(WORKDIR) \ 49 | -o $(WORKDIR)/$(ARCHNAME).bin $(ARCHNAME) \ 50 | --vcd=$(WORKDIR)/$(ARCHNAME).vcd --stop-time=$(STOPTIME) 51 | @echo ">>> showing waveform for:" $(TB) 52 | $(QUIET)$(SIM) $(WORKDIR)/$(ARCHNAME).vcd 53 | 54 | .PHONY: clean 55 | clean: 56 | @echo ">>> cleaning design..." 57 | $(QUIET)ghdl --remove --workdir=$(WORKDIR) 58 | $(QUIET)rm -f $(WORKDIR)/* 59 | $(QUIET)rm -rf $(WORKDIR) 60 | @echo ">>> done..." 61 | -------------------------------------------------------------------------------- /rtl/adder4.vhd: -------------------------------------------------------------------------------- 1 | -- 4-bit ripple-carry adder (RCA) 2 | library ieee; 3 | use ieee.std_logic_1164.all; 4 | 5 | entity adder4 is 6 | -- a, b are 4-bit inputs of the adder4 7 | -- cin is the carry-in input 8 | -- s is the 4-bit sum output, 9 | -- cout is the carry out 10 | -- v is the overflow output 11 | port ( 12 | a, b : in std_logic_vector(3 downto 0); 13 | cin : in std_logic; 14 | s : out std_logic_vector(3 downto 0); 15 | v, cout : out std_logic 16 | ); 17 | end adder4; 18 | 19 | architecture rtl of adder4 is 20 | -- intermediate signals 21 | -- set each bit to 0 initially 22 | signal c : std_logic_vector(3 downto 0) := (others => '0'); 23 | begin 24 | 25 | f0 : entity work.full_adder(bhv) 26 | port map ( a => a(0), b => b(0), cin => cin, s => s(0), cout => c(0) ); 27 | f1 : entity work.full_adder(bhv) 28 | port map ( a => a(1), b => b(1), cin => c(0), s => s(1), cout => c(1) ); 29 | f2 : entity work.full_adder(str) 30 | port map ( a => a(2), b => b(2), cin => c(1), s => s(2), cout => c(2) ); 31 | f3 : entity work.full_adder(str) 32 | port map ( a => a(3), b => b(3), cin => c(2), s => s(3), cout => c(3) ); 33 | 34 | -- carry out 35 | cout <= c(3); 36 | -- overflow 37 | v <= c(2) xor c(3); 38 | 39 | end rtl; 40 | -------------------------------------------------------------------------------- /rtl/addsub4.vhd: -------------------------------------------------------------------------------- 1 | -- 4-bit adder / subtractor 2 | -- subtractor calculates a - b 3 | library ieee; 4 | use ieee.std_logic_1164.all; 5 | 6 | entity addsub4 is 7 | -- a, b are 4-bit inputs of the addsub4 8 | -- m is the adder / subtractor selector input 9 | -- ('0' - adder, '1' - subtractor) 10 | -- s is the 4-bit sum output, 11 | -- cout is the carry out 12 | -- v is the overflow 13 | port ( 14 | a, b : in std_logic_vector(3 downto 0); 15 | m : in std_logic; 16 | s : out std_logic_vector(3 downto 0); 17 | v, cout : out std_logic 18 | ); 19 | end addsub4; 20 | 21 | architecture rtl of addsub4 is 22 | -- intermediate signals 23 | signal bt : std_logic_vector(3 downto 0) := (others => '0'); 24 | begin 25 | -- xor each b input with the value of m to use it as is 26 | -- or take 1's complement 27 | sub: for i in 0 to 3 generate 28 | begin 29 | bt(i) <= b(i) xor m; 30 | end generate; 31 | 32 | a4 : entity work.adder4(rtl) 33 | port map ( a => a, b => bt, cin => m, s => s, v => v, cout => cout ); 34 | 35 | end rtl; 36 | -------------------------------------------------------------------------------- /rtl/alu1.vhd: -------------------------------------------------------------------------------- 1 | -- 1-bit alu circuit (with process) 2 | -- functions implemented 3 | -- opcode function 4 | -- 000 a + b 5 | -- 001 a - b 6 | -- 010 a and b 7 | -- 011 a or b 8 | -- 100 a nor b 9 | -- 101 a xor b 10 | -- 110 a < b 11 | -- 111 not a 12 | 13 | library ieee; 14 | use ieee.std_logic_1164.all; 15 | 16 | entity alu1 is 17 | port ( 18 | a, b : in std_logic; 19 | ci : in std_logic; 20 | opcode : in std_logic_vector(2 downto 0); 21 | r : out std_logic; 22 | co : out std_logic 23 | ); 24 | end alu1; 25 | 26 | architecture rtl of alu1 is 27 | begin 28 | 29 | process(a, b, ci, opcode) is 30 | begin 31 | co <= '0'; 32 | case opcode is 33 | when "000" => 34 | r <= a xor b xor ci; 35 | co <= (a and b) or (a and ci) or (b and ci); 36 | when "001" => 37 | r <= a xor b xor ci; 38 | co <= ((not a) and b) or ((not (a xor b)) and ci); 39 | when "010" => 40 | r <= a and b; 41 | when "011" => 42 | r <= a or b; 43 | when "100" => 44 | r <= a nor b; 45 | when "101" => 46 | r <= a xor b; 47 | when "110" => 48 | if a = '0' and b = '1' then 49 | r <= '1'; 50 | else 51 | r <= '0'; 52 | end if; 53 | when "111" => 54 | r <= not a; 55 | when others => 56 | r <= '0'; 57 | end case; 58 | end process; 59 | 60 | end rtl; 61 | -------------------------------------------------------------------------------- /rtl/alu8.vhd: -------------------------------------------------------------------------------- 1 | -- M-bit alu using 1-bit alus 2 | -- smaller than options needs rework to get correct result 3 | library ieee; 4 | use ieee.std_logic_1164.all; 5 | use ieee.numeric_std.all; 6 | 7 | entity alu8 is 8 | generic(M: integer := 32); 9 | port ( 10 | a, b : in std_logic_vector(M-1 downto 0); 11 | cin : in std_logic; 12 | opcode : in std_logic_vector(2 downto 0); 13 | r : out std_logic_vector(M-1 downto 0); 14 | cout : out std_logic 15 | ); 16 | end alu8; 17 | 18 | architecture rtl of alu8 is 19 | component alu1 is 20 | port ( 21 | a, b : in std_logic; 22 | ci : in std_logic; 23 | opcode : in std_logic_vector(2 downto 0); 24 | r : out std_logic; 25 | co : out std_logic 26 | ); 27 | end component; 28 | 29 | signal c : std_logic_vector(M downto 0) := (others=>'0'); 30 | signal rtmp : std_logic_vector(M-1 downto 0) := (others=>'0'); 31 | begin 32 | 33 | c(0) <= cin; 34 | gen: for i in 0 to M-1 generate 35 | alu_g: alu1 port map ( a=>a(i), b=>b(i), ci=>c(i), opcode=>opcode, r=>rtmp(i), co=>c(i+1)); 36 | end generate; 37 | -- subtract is inverted cout 38 | cout <= not c(M) when opcode = "001" else c(M); 39 | 40 | -- only for a < b stage 41 | -- get correct result 42 | process(a, b, opcode, rtmp) is 43 | begin 44 | case opcode is 45 | when "110" => 46 | if a < b then 47 | r <= (0=>'1', others=>'0'); 48 | else 49 | r <= (others=>'0'); 50 | end if; 51 | when others => 52 | r <= rtmp; 53 | end case; 54 | end process; 55 | end rtl; 56 | -------------------------------------------------------------------------------- /rtl/alu_nzvc.vhd: -------------------------------------------------------------------------------- 1 | -- generic alu unit supporting nzvc flags 2 | -- not yet tested, expect bugs 3 | library ieee; 4 | use ieee.std_logic_1164.all; 5 | use ieee.numeric_std.all; 6 | 7 | entity alu_nzvc is 8 | generic ( M :integer := 32); 9 | port ( 10 | a, b : in std_logic_vector(M-1 downto 0); 11 | opcode : in std_logic_vector(2 downto 0); 12 | r : out std_logic_vector(M-1 downto 0); 13 | n,z,v,c : out std_logic 14 | ); 15 | end alu_nzvc; 16 | 17 | architecture rtl of alu_nzvc is 18 | signal a_u, b_u, r_u : unsigned(M downto 0) := (others=>'0'); 19 | signal c_sub : std_logic := '0'; 20 | begin 21 | 22 | -- make type castings for easy operations 23 | a_u <= unsigned('0' & a); 24 | b_u <= unsigned('0' & b); 25 | r <= std_logic_vector(r_u(M-1 downto 0)); 26 | 27 | -- alu, can also be tied to clock 28 | process(a_u, b_u, opcode) is 29 | begin 30 | c_sub <= '0'; 31 | 32 | case opcode is 33 | when "000" => -- add 34 | r_u <= a_u + b_u; 35 | when "001" => -- sub 36 | r_u <= a_u - b_u; 37 | c_sub <= '1'; 38 | when "010" => -- and 39 | r_u <= a_u and b_u; 40 | when "011" => -- or 41 | r_u <= a_u or b_u; 42 | when "100" => -- nor 43 | -- don't update carry bit 44 | r_u <= '0' & (a_u(M-1 downto 0) nor b_u(M-1 downto 0)); 45 | when "101" => -- xor 46 | r_u <= a_u xor b_u; 47 | when "110" => -- a < b unsigned 48 | if a_u < b_u then 49 | r_u <= (0=>'1', others=>'0'); 50 | else 51 | r_u <= (others=>'0'); 52 | end if; 53 | when "111" => -- not a 54 | -- don't update carry bit 55 | r_u <= '0' & (not a_u(M-1 downto 0)); 56 | when others => 57 | r_u <= (others=>'0'); 58 | end case; 59 | end process; 60 | 61 | -- carry flag 62 | c <= r_u(M) when c_sub = '0' else not r_u(M); 63 | 64 | -- negative flag 65 | n <= r_u(M-1); 66 | 67 | -- zero flag 68 | z <= '1' when r_u(M-1 downto 0) = 0 else '0'; 69 | 70 | -- overflow flag 71 | v <= '1' when (a_u(M-1) = '1' and b_u(M-1) = '1' and r_u(M-1) = '0') or 72 | (a_u(M-1) = '0' and b_u(M-1) = '0' and r_u(M-1) = '1') else 73 | '0'; 74 | 75 | end rtl; 76 | -------------------------------------------------------------------------------- /rtl/barrel_shifter.vhd: -------------------------------------------------------------------------------- 1 | -- 32-bit barrel shifter 2 | -- not yet tested 3 | library ieee; 4 | use ieee.std_logic_1164.all; 5 | use ieee.numeric_std.all; 6 | 7 | entity barrel_shifter is 8 | port ( 9 | a : in std_logic_vector(31 downto 0); 10 | sel : in std_logic_vector(4 downto 0); 11 | ori : in std_logic; 12 | b : out std_logic_vector(31 downto 0) 13 | ); 14 | end barrel_shifter; 15 | 16 | architecture rtl of barrel_shifter is 17 | begin 18 | 19 | process(a, sel, ori) is 20 | variable s : integer range 0 to 31 := 0; 21 | begin 22 | s := to_integer(unsigned(sel)); 23 | if s /= 0 then 24 | if ori = '1' then 25 | -- right rotate 26 | --b <= a ror s; 27 | b <= a(s-1 downto 0) & a(31 downto s); 28 | else 29 | -- left rotate 30 | --b <= a rol s; 31 | b <= a(31-s downto 0) & a(31 downto 31-s+1); 32 | end if; 33 | else 34 | b <= a; 35 | end if; 36 | end process; 37 | 38 | end rtl; 39 | -------------------------------------------------------------------------------- /rtl/bram.vhd: -------------------------------------------------------------------------------- 1 | -- single port M-bit x N-bit RAM 2 | -- read first / write first 3 | -- block RAM (sync read) 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | use ieee.numeric_std.all; 7 | 8 | entity bram is 9 | generic( 10 | M : integer := 10; 11 | N : integer := 32 12 | ); 13 | port( 14 | clk : in std_logic; 15 | we : in std_logic; 16 | addr : in std_logic_vector(M - 1 downto 0); 17 | din : in std_logic_vector(N - 1 downto 0); 18 | dout : out std_logic_vector(N - 1 downto 0) 19 | ); 20 | end bram; 21 | 22 | architecture rtl of bram is 23 | type ram_type is array(0 to 2**M - 1) of std_logic_vector(N - 1 downto 0); 24 | signal RAM : ram_type := (others => (others => '0')); 25 | begin 26 | 27 | process(clk) is 28 | begin 29 | if rising_edge(clk) then 30 | if we = '1' then 31 | RAM(to_integer(unsigned(addr))) <= din; 32 | -- dout <= din; -- optional, write first 33 | end if; 34 | dout <= RAM(to_integer(unsigned(addr))); 35 | end if; 36 | end process; 37 | 38 | end rtl; -------------------------------------------------------------------------------- /rtl/cla.vhd: -------------------------------------------------------------------------------- 1 | -- carry lookahead adder 2 | -- though synthesis will create like a ripple carry 3 | library ieee; 4 | use ieee.std_logic_1164.all; 5 | 6 | entity cla is 7 | generic (M : integer := 32); 8 | port ( 9 | a, b : in std_logic_vector(M-1 downto 0); 10 | cin : in std_logic; 11 | s : out std_logic_vector(M-1 downto 0); 12 | cout : out std_logic 13 | ); 14 | end cla; 15 | 16 | architecture rtl of cla is 17 | signal c : std_logic_vector(M downto 0) := (others =>'0'); 18 | signal p, g : std_logic_vector(M-1 downto 0) := (others =>'0'); 19 | begin 20 | 21 | -- common assignments for all routes 22 | p <= a xor b; 23 | g <= a and b; 24 | s <= p xor c(M-1 downto 0); 25 | cout <= c(M); 26 | 27 | -- 1. using for generate 28 | c(0) <= cin; 29 | gen: for i in 0 to M-1 generate 30 | c(i+1) <= g(i) or (p(i) and c(i)); 31 | end generate; 32 | 33 | -- 2. using for loop 34 | -- process(g, p, c) is 35 | -- begin 36 | -- c(0) <= cin; 37 | -- for i in 0 to M-1 loop 38 | -- c(i+1) <= g(i) or (p(i) and c(i)); 39 | -- end loop; 40 | -- end process; 41 | 42 | -- 3. manually assigning each signal 43 | -- c(0) <= cin; 44 | -- c(1) <= g(0) or ( p(0) and ( c(0) )); 45 | -- c(2) <= g(1) or ( p(1) and ( g(0) or ( p(0) and ( c(0) )) )); 46 | -- c(3) <= g(2) or ( p(2) and ( g(1) or ( p(1) and ( g(0) or ( p(0) and ( c(0) )) )) )); 47 | -- c(4) <= g(3) or ( p(3) and ( g(2) or ( p(2) and ( g(1) or ( p(1) and ( g(0) or ( p(0) and ( c(0) )) )) )) )); 48 | -- c(5) <= g(4) or ( p(4) and ( g(3) or ( p(3) and ( g(2) or ( p(2) and ( g(1) or ( p(1) and ( g(0) or ( p(0) and ( c(0) )) )) )) )) )); 49 | -- c(6) <= g(5) or ( p(5) and ( g(4) or ( p(4) and ( g(3) or ( p(3) and ( g(2) or ( p(2) and ( g(1) or ( p(1) and ( g(0) or ( p(0) and ( c(0) )) )) )) )) )) )); 50 | -- c(7) <= g(6) or ( p(6) and ( g(5) or ( p(5) and ( g(4) or ( p(4) and ( g(3) or ( p(3) and ( g(2) or ( p(2) and ( g(1) or ( p(1) and ( g(0) or ( p(0) and ( c(0) )) )) )) )) )) )) )); 51 | -- c(8) <= g(7) or ( p(7) and ( g(6) or ( p(6) and ( g(5) or ( p(5) and ( g(4) or ( p(4) and ( g(3) or ( p(3) and ( g(2) or ( p(2) and ( g(1) or ( p(1) and ( g(0) or ( p(0) and ( c(0) )) )) )) )) )) )) )) )); 52 | 53 | end rtl; 54 | -------------------------------------------------------------------------------- /rtl/counter.vhd: -------------------------------------------------------------------------------- 1 | -- 4-bit (mod16) counter using d flip flops 2 | -- connected as t flip flops 3 | library ieee; 4 | use ieee.std_logic_1164.all; 5 | use ieee.numeric_std.all; 6 | 7 | entity counter is 8 | port ( 9 | en, clk : in std_logic; 10 | cout : out std_logic_vector(3 downto 0) 11 | ); 12 | end counter; 13 | 14 | architecture bhv of counter is 15 | signal a, b, c, d : std_logic := '0'; 16 | begin 17 | 18 | process(clk) is 19 | begin 20 | if rising_edge(clk) then 21 | -- each rising edge, update the flip flops 22 | if en = '1' then 23 | -- reset when counter hits 12 24 | if a = '0' and b = '0' and c = '1' and d = '1' then 25 | a <= '0'; 26 | b <= '0'; 27 | c <= '0'; 28 | d <= '0'; 29 | else 30 | a <= a xor '1'; 31 | b <= b xor a; 32 | c <= c xor (a and b); 33 | d <= d xor (a and b and c); 34 | end if; 35 | end if; 36 | end if; 37 | end process; 38 | 39 | -- assign the outputs outside of process 40 | cout <= d & c & b & a; 41 | 42 | end bhv; 43 | 44 | 45 | architecture rtl of counter is 46 | -- initialize counter signal to all 0s 47 | signal cnt : unsigned(3 downto 0) := (others => '0'); 48 | begin 49 | 50 | process(clk) is 51 | begin 52 | -- Check for rising edge on the registers. 53 | if rising_edge(clk) then 54 | if en = '1' then 55 | -- reset when counter hits 12 56 | if cnt = 12 then 57 | cnt <= (others => '0'); 58 | else 59 | cnt <= cnt + 1; 60 | end if; 61 | end if; 62 | end if; 63 | end process; 64 | 65 | -- Assign the output outside of process. 66 | cout <= std_logic_vector(cnt); 67 | 68 | end rtl; 69 | -------------------------------------------------------------------------------- /rtl/decoder2.vhd: -------------------------------------------------------------------------------- 1 | -- 2-bit line decoder (2 to 4) 2 | library ieee; 3 | use ieee.std_logic_1164.all; 4 | 5 | entity decoder2 is 6 | port ( 7 | a : in std_logic_vector(1 downto 0); 8 | b : out std_logic_vector(3 downto 0) 9 | ); 10 | end decoder2; 11 | 12 | architecture rtl of decoder2 is 13 | begin 14 | 15 | with a select 16 | b <= "0001" when "00", 17 | "0010" when "01", 18 | "0100" when "10", 19 | "1000" when others; 20 | 21 | end rtl; -------------------------------------------------------------------------------- /rtl/demux4.vhd: -------------------------------------------------------------------------------- 1 | -- 1-to-4 demux 2 | library ieee; 3 | use ieee.std_logic_1164.all; 4 | 5 | entity demux4 is 6 | port ( 7 | a : in std_logic; 8 | sel : in std_logic_vector(1 downto 0); 9 | y : out std_logic_vector(3 downto 0) 10 | ); 11 | end demux4; 12 | 13 | architecture rtl of demux4 is 14 | -- signal to hold sel + a values 15 | signal s_sela : std_logic_vector(2 downto 0); 16 | begin 17 | 18 | -- concatenate two values together 19 | -- & is concatenation operation 20 | s_sela <= sel & a; 21 | 22 | with s_sela select 23 | y <= "0001" when "001", 24 | "0010" when "011", 25 | "0100" when "101", 26 | "1000" when "111", 27 | "0000" when others; 28 | end rtl; -------------------------------------------------------------------------------- /rtl/dff.vhd: -------------------------------------------------------------------------------- 1 | -- 1-bit d flip-flop examples with various configurations 2 | library ieee; 3 | use ieee.std_logic_1164.all; 4 | 5 | entity dff is 6 | port ( 7 | d : in std_logic; 8 | clk : in std_logic; 9 | en : in std_logic; 10 | set : in std_logic; 11 | rst : in std_logic; 12 | q1, q2, q3, q4 : out std_logic; 13 | q5, q6, q7, q8 : out std_logic 14 | ); 15 | end dff; 16 | 17 | architecture rtl of dff is 18 | begin 19 | 20 | -- rising-edge triggered dff 21 | process(clk) is 22 | begin 23 | -- clk'event and clk ='1' then 24 | if rising_edge(clk) then 25 | q1 <= d; 26 | end if; 27 | end process; 28 | 29 | -- falling-edge triggered dff 30 | process(clk) is 31 | begin 32 | --if clk'event and clk = '0' then 33 | if falling_edge(clk) then 34 | q2 <= d; 35 | end if; 36 | end process; 37 | 38 | -- dff with async reset (clear) 39 | process(rst, clk) is 40 | begin 41 | if rst = '1' then 42 | q3 <= '0'; 43 | elsif rising_edge(clk) then 44 | q3 <= d; 45 | end if; 46 | end process; 47 | 48 | -- dff with sync reset 49 | process(rst, clk) is 50 | begin 51 | if rising_edge(clk) then 52 | if rst = '1' then 53 | q4 <= '0'; 54 | else 55 | q4 <= d; 56 | end if; 57 | end if; 58 | end process; 59 | 60 | -- dff with async reset and enable 61 | process(rst, clk) is 62 | begin 63 | if rst = '1' then 64 | q5 <= '0'; 65 | elsif rising_edge(clk) then 66 | if en = '1' then 67 | q5 <= d; 68 | end if; 69 | end if; 70 | end process; 71 | 72 | 73 | -- dff with sync reset and enable 74 | process(clk) is 75 | begin 76 | if rising_edge(clk) then 77 | if rst = '1' then 78 | q6 <= '0'; 79 | elsif en = '1' then 80 | q6 <= d; 81 | end if; 82 | end if; 83 | end process; 84 | 85 | -- dff with async set (preset) and enable 86 | process(set, clk) is 87 | begin 88 | if set = '1' then 89 | q7 <= '1'; 90 | elsif rising_edge(clk) then 91 | if en = '1' then 92 | q7 <= d; 93 | end if; 94 | end if; 95 | end process; 96 | 97 | 98 | -- dff with sync set and enable 99 | process(clk) is 100 | begin 101 | if rising_edge(clk) then 102 | if set = '1' then 103 | q8 <= '1'; 104 | elsif en = '1' then 105 | q8 <= d; 106 | end if; 107 | end if; 108 | end process; 109 | 110 | end rtl; 111 | -------------------------------------------------------------------------------- /rtl/dlatch.vhd: -------------------------------------------------------------------------------- 1 | -- 1-bit d latch 2 | library ieee; 3 | use ieee.std_logic_1164.all; 4 | 5 | entity dlatch is 6 | port ( 7 | d : in std_logic; 8 | en : in std_logic; 9 | q1, q2 : out std_logic 10 | ); 11 | end dlatch; 12 | 13 | architecture rtl of dlatch is 14 | signal d_next : std_logic := '0'; 15 | begin 16 | 17 | -- 1st way with / select method 18 | 19 | -- implement 1-bit latch 20 | with en select 21 | d_next <= 22 | d when '1', 23 | d_next when others; 24 | 25 | -- Assign the output 26 | q1 <= d_next; 27 | 28 | -- 2nd way: if method 29 | -- en and d input signals are placed 30 | -- inside the sensitivity list 31 | process(en, d) is 32 | begin 33 | if en = '1' then 34 | q2 <= d; 35 | end if; 36 | end process; 37 | 38 | end rtl; 39 | -------------------------------------------------------------------------------- /rtl/dram.vhd: -------------------------------------------------------------------------------- 1 | -- single port M-bit x N-bit RAM 2 | -- distributed RAM (async read) 3 | library ieee; 4 | use ieee.std_logic_1164.all; 5 | use ieee.numeric_std.all; 6 | 7 | entity dram is 8 | generic( 9 | M : integer := 10; 10 | N : integer := 32 11 | ); 12 | port( 13 | clk : in std_logic; 14 | we : in std_logic; 15 | addr : in std_logic_vector(M - 1 downto 0); 16 | din : in std_logic_vector(N - 1 downto 0); 17 | dout : out std_logic_vector(N - 1 downto 0) 18 | ); 19 | end dram; 20 | 21 | architecture rtl of dram is 22 | type ram_type is array(0 to 2**M - 1) of std_logic_vector(N - 1 downto 0); 23 | signal RAM : ram_type := (others => (others => '0')); 24 | begin 25 | 26 | process(clk) is 27 | begin 28 | if rising_edge(clk) then 29 | if we = '1' then 30 | RAM(to_integer(unsigned(addr))) <= din; 31 | end if; 32 | end if; 33 | end process; 34 | 35 | dout <= RAM(to_integer(unsigned(addr))); 36 | 37 | end rtl; -------------------------------------------------------------------------------- /rtl/dualram.vhd: -------------------------------------------------------------------------------- 1 | -- simple dual-clock dual-port M-bit x N-bit RAM 2 | library ieee; 3 | use ieee.std_logic_1164.all; 4 | use ieee.numeric_std.all; 5 | use std.textio.all; 6 | 7 | entity dualram is 8 | generic( 9 | RAMFILENAME: string := "../impl/ram_content.data"; 10 | M : integer := 5; 11 | N : integer := 32 12 | ); 13 | port( 14 | clka, clkb : in std_logic; 15 | ena, enb : in std_logic; 16 | wea : in std_logic; 17 | addra, addrb : in std_logic_vector(M - 1 downto 0); 18 | dina : in std_logic_vector(N - 1 downto 0); 19 | doutb : out std_logic_vector(N - 1 downto 0) 20 | ); 21 | end dualram; 22 | 23 | architecture rtl of dualram is 24 | type ram_type is array(0 to 2**M - 1) of std_logic_vector(N - 1 downto 0); 25 | 26 | impure function init_ram_from_file (fname : in string) return ram_type is 27 | file f : text is fname; 28 | variable fline : line; 29 | variable ramm : ram_type; 30 | variable rl : bit_vector(N-1 downto 0); 31 | begin 32 | for i in ram_type'range loop 33 | readline (f, fline); 34 | read (fline, rl); 35 | ramm(i) := to_stdlogicvector(rl); 36 | end loop; 37 | return ramm; 38 | end function; 39 | 40 | signal RAM : ram_type := init_ram_from_file(RAMFILENAME); 41 | 42 | begin 43 | 44 | -- a port process - write only 45 | process(clka) is 46 | begin 47 | if rising_edge(clka) then 48 | if ena = '1' then 49 | if wea = '1' then 50 | RAM(to_integer(unsigned(addra))) <= dina; 51 | end if; 52 | end if; 53 | end if; 54 | end process; 55 | 56 | -- b port process - read only 57 | process(clkb) is 58 | begin 59 | if rising_edge(clkb) then 60 | if enb = '1' then 61 | doutb <= RAM(to_integer(unsigned(addrb))); 62 | end if; 63 | end if; 64 | end process; 65 | 66 | end rtl; -------------------------------------------------------------------------------- /rtl/fifo_async.vhd: -------------------------------------------------------------------------------- 1 | -- asyncronous fifo example with empty / full flags 2 | -- separate read / write clock 3 | library ieee; 4 | use ieee.std_logic_1164.all; 5 | use ieee.numeric_std.all; 6 | 7 | entity fifo_async is 8 | generic( 9 | M : integer := 10; -- depth 2**M 10 | N : integer := 18 -- width N-bits 11 | ); 12 | port( 13 | i_rst : in std_logic; 14 | -- write interface 15 | i_clk_wr : in std_logic; 16 | i_wr_en : in std_logic; 17 | i_din : in std_logic_vector(N -1 downto 0); 18 | -- read interface 19 | i_clk_rd : in std_logic; 20 | i_rd_en : in std_logic; 21 | o_dout : out std_logic_vector(N - 1 downto 0); 22 | -- flow control 23 | o_empty, o_full : out std_logic 24 | ); 25 | end fifo_async; 26 | 27 | architecture rtl of fifo_async is 28 | type fifo_type is array(0 to 2**M - 1) of std_logic_vector(N - 1 downto 0); 29 | signal FIFO : fifo_type := (others => (others => '0')); 30 | 31 | signal wr_ptr, rd_ptr : integer range 0 to 2**M - 1 := 0; 32 | signal empty, full : std_logic := '0'; 33 | 34 | -- do not optimize away empty / full signals 35 | attribute keep : string; 36 | attribute keep of empty : signal is "true"; 37 | attribute keep of full : signal is "true"; 38 | begin 39 | 40 | write: process(i_clk_wr) is 41 | begin 42 | if rising_edge(i_clk_wr) then 43 | if i_rst = '1' then 44 | wr_ptr <= 0; 45 | elsif i_wr_en = '1' then 46 | if full = '0' then 47 | FIFO(wr_ptr) <= i_din; 48 | if wr_ptr = 2**M - 1 then 49 | wr_ptr <= 0; 50 | else 51 | wr_ptr <= wr_ptr + 1; 52 | end if; 53 | end if; 54 | end if; 55 | end if; 56 | end process; 57 | 58 | read: process(i_clk_rd) is 59 | begin 60 | if rising_edge(i_clk_rd) then 61 | if i_rst = '1' then 62 | rd_ptr <= 0; 63 | elsif i_rd_en = '1' then 64 | if empty = '0' then 65 | if rd_ptr = 2**M - 1 then 66 | rd_ptr <= 0; 67 | else 68 | rd_ptr <= rd_ptr + 1; 69 | end if; 70 | end if; 71 | end if; 72 | end if; 73 | end process; 74 | 75 | empty <= '1' when wr_ptr - rd_ptr = 0 else '0'; 76 | full <= '1' when rd_ptr - wr_ptr = 1 or (rd_ptr = 0 and wr_ptr = 2**M - 1) else '0'; 77 | 78 | o_empty <= empty; 79 | o_full <= full; 80 | 81 | o_dout <= FIFO(rd_ptr); 82 | end rtl; -------------------------------------------------------------------------------- /rtl/fifo_sync.vhd: -------------------------------------------------------------------------------- 1 | -- syncronous fifo example with empty / full flags 2 | -- common read / write clock 3 | library ieee; 4 | use ieee.std_logic_1164.all; 5 | use ieee.numeric_std.all; 6 | 7 | entity fifo_sync is 8 | generic( 9 | M : integer := 10; -- depth 2**M 10 | N : integer := 18 -- width N-bits 11 | ); 12 | port( 13 | i_rst : in std_logic; 14 | i_clk : in std_logic; 15 | -- write interface 16 | i_wr_en : in std_logic; 17 | i_din : in std_logic_vector(N -1 downto 0); 18 | -- read interface 19 | i_rd_en : in std_logic; 20 | o_dout : out std_logic_vector(N - 1 downto 0); 21 | -- flow control 22 | o_empty, o_full : out std_logic 23 | ); 24 | end fifo_sync; 25 | 26 | architecture rtl of fifo_sync is 27 | type fifo_type is array(0 to 2**M - 1) of std_logic_vector(N - 1 downto 0); 28 | signal FIFO : fifo_type := (others => (others => '0')); 29 | 30 | signal wr_ptr, rd_ptr : integer range 0 to 2**M - 1 := 0; 31 | signal count : integer range 0 to 2**M := 0; 32 | signal empty, full : std_logic := '0'; 33 | 34 | -- do not optimize away empty / full signals 35 | attribute keep : string; 36 | attribute keep of empty : signal is "true"; 37 | attribute keep of full : signal is "true"; 38 | begin 39 | 40 | write: process(i_clk) is 41 | begin 42 | if rising_edge(i_clk) then 43 | if i_rst = '1' then 44 | wr_ptr <= 0; 45 | else 46 | if i_wr_en = '1' then 47 | if full = '0' then 48 | FIFO(wr_ptr) <= i_din; 49 | if wr_ptr = 2**M - 1 then 50 | wr_ptr <= 0; 51 | else 52 | wr_ptr <= wr_ptr + 1; 53 | end if; 54 | end if; 55 | end if; 56 | end if; 57 | end if; 58 | end process; 59 | 60 | read: process(i_clk) is 61 | begin 62 | if rising_edge(i_clk) then 63 | if i_rst = '1' then 64 | rd_ptr <= 0; 65 | else 66 | if i_rd_en = '1' then 67 | if empty = '0' then 68 | if rd_ptr = 2**M - 1 then 69 | rd_ptr <= 0; 70 | else 71 | rd_ptr <= rd_ptr + 1; 72 | end if; 73 | end if; 74 | end if; 75 | end if; 76 | end if; 77 | end process; 78 | 79 | 80 | counter: process(i_clk) is 81 | begin 82 | if rising_edge(i_clk) then 83 | if i_rst = '1' then 84 | count <= 0; 85 | else 86 | if i_rd_en = '1' and i_wr_en = '1' then 87 | if full = '0' then 88 | count <= count + 1; 89 | elsif empty = '0' then 90 | count <= count - 1; 91 | end if; 92 | elsif i_rd_en = '1' then 93 | if empty = '0' then 94 | count <= count - 1; 95 | end if; 96 | elsif i_wr_en = '1' then 97 | if full = '0' then 98 | count <= count + 1; 99 | end if; 100 | end if; 101 | end if; 102 | end if; 103 | end process; 104 | 105 | 106 | empty <= '1' when count = 0 else '0'; 107 | full <= '1' when count = 2**M else '0'; 108 | 109 | o_empty <= empty; 110 | o_full <= full; 111 | 112 | o_dout <= FIFO(rd_ptr); 113 | end rtl; 114 | -------------------------------------------------------------------------------- /rtl/fsm.vhd: -------------------------------------------------------------------------------- 1 | -- finite state machine implementations 2 | library ieee; 3 | use ieee.std_logic_1164.all; 4 | 5 | entity fsm is 6 | port( 7 | clk : in std_logic; 8 | a, b : in std_logic; 9 | mealy, moore : out std_logic 10 | ); 11 | end fsm; 12 | 13 | -- implementation #1 14 | -- separate next-state logic 15 | -- separate outputs for both mealy and moore 16 | architecture rtla of fsm is 17 | -- define custom type for states 18 | type state_type is (s0, s1, s2); 19 | signal state, state_next : state_type := s0; 20 | begin 21 | 22 | -- state registers 23 | process(clk) is 24 | begin 25 | if rising_edge(clk) then 26 | state <= state_next; 27 | end if; 28 | end process; 29 | 30 | -- next-state logic 31 | process(state, a, b) is 32 | begin 33 | case state is 34 | when s0 => 35 | if a = '1' then 36 | if b = '1' then 37 | state_next <= s2; 38 | else 39 | state_next <= s1; 40 | end if; 41 | else 42 | state_next <= s0; 43 | end if; 44 | when s1 => 45 | if a = '1' then 46 | state_next <= s0; 47 | else 48 | state_next <= s1; 49 | end if; 50 | when s2 => 51 | state_next <= s0; 52 | when others => 53 | state_next <= s0; 54 | end case; 55 | end process; 56 | 57 | -- output logic (moore) 58 | process(state) is 59 | begin 60 | case state is 61 | when s0 | s2 => 62 | moore <= '0'; 63 | when s1 => 64 | moore <= '1'; 65 | end case; 66 | end process; 67 | 68 | 69 | -- output logic (mealy) 70 | -- susceptible to short input changes 71 | -- might create glitches 72 | -- can be put behind a register 73 | process(state, a, b) is 74 | begin 75 | case state is 76 | when s0 => 77 | if a = '1' and b = '1' then 78 | mealy <= '1'; 79 | else 80 | mealy <= '0'; 81 | end if; 82 | when s1 | s2 => 83 | mealy <= '0'; 84 | end case; 85 | end process; 86 | end rtla; 87 | 88 | -- implementation #2 89 | -- next-state logic and outputs are 90 | -- merged into one process 91 | architecture rtlb of fsm is 92 | -- define custom type for states 93 | type state_type is (s0, s1, s2); 94 | signal state, state_next : state_type := s0; 95 | begin 96 | 97 | -- state registers 98 | process(clk) is 99 | begin 100 | if rising_edge(clk) then 101 | state <= state_next; 102 | end if; 103 | end process; 104 | 105 | -- next-state and output logic 106 | -- susceptible to short input changes 107 | -- for mealy outputs 108 | process(state, a, b) is 109 | begin 110 | -- default values for all the outputs 111 | -- used to avoid any accidental unintentional memory generation 112 | state_next <= state; 113 | mealy <= '0'; 114 | moore <= '0'; 115 | 116 | case state is 117 | when s0 => 118 | if a = '1' then 119 | if b = '1' then 120 | state_next <= s2; 121 | mealy <= '1'; 122 | else 123 | state_next <= s1; 124 | end if; 125 | else 126 | state_next <= s0; 127 | end if; 128 | when s1 => 129 | moore <= '1'; 130 | if a = '1' then 131 | state_next <= s0; 132 | else 133 | state_next <= s1; 134 | end if; 135 | when s2 => 136 | state_next <= s0; 137 | when others => 138 | state_next <= s0; 139 | end case; 140 | end process; 141 | end rtlb; 142 | 143 | -- implementation #3 144 | -- everything is merged into one process 145 | -- state is made a variable just to give a different example 146 | architecture rtlc of fsm is 147 | begin 148 | 149 | process(clk) is 150 | type state_type is (s0, s1, s2); 151 | variable state : state_type := s0; 152 | begin 153 | if rising_edge(clk) then 154 | -- default values for outputs 155 | moore <= '0'; 156 | mealy <= '0'; 157 | 158 | case state is 159 | when s0 => 160 | if a = '1' then 161 | if b = '1' then 162 | state := s2; 163 | -- will overwrite default mealy value 164 | mealy <= '1'; 165 | else 166 | state := s1; 167 | end if; 168 | end if; 169 | when s1 => 170 | -- will overwrite default moore value 171 | moore <= '1'; 172 | if a = '1' then 173 | state := s0; 174 | else 175 | state := s1; 176 | end if; 177 | when s2 => 178 | state := s0; 179 | end case; 180 | end if; 181 | end process; 182 | end rtlc; 183 | -------------------------------------------------------------------------------- /rtl/fsm_counter.vhd: -------------------------------------------------------------------------------- 1 | -- finite state machine implementations 2 | -- showing when using a counter on a simple pwm example 3 | library ieee; 4 | use ieee.std_logic_1164.all; 5 | use ieee.numeric_std.all; 6 | 7 | entity fsm_counter is 8 | port( 9 | clk : in std_logic; 10 | o : out std_logic 11 | ); 12 | end fsm_counter; 13 | 14 | -- implementation #1 15 | -- next-state and output logic are merged 16 | -- separate registes 17 | architecture rtla of fsm_counter is 18 | type state_type is (s1, s2); 19 | signal state, state_next : state_type := s1; 20 | 21 | signal cnt, cnt_next : integer range 0 to 15 := 0; 22 | signal trgt, trgt_next : integer range 0 to 15 := 0; 23 | 24 | begin 25 | 26 | -- state registers 27 | process(clk) is 28 | begin 29 | if rising_edge(clk) then 30 | state <= state_next; 31 | cnt <= cnt_next; 32 | trgt <= trgt_next; 33 | end if; 34 | end process; 35 | 36 | 37 | process(state, cnt, trgt) is 38 | begin 39 | -- defaults for latch avoidance 40 | -- read from regs and write to _next 41 | state_next <= state; 42 | cnt_next <= cnt; 43 | trgt_next <= trgt; 44 | 45 | case state is 46 | when s1 => 47 | o <= '1'; 48 | if cnt = trgt then 49 | state_next <= s2; 50 | if trgt = 15 then 51 | trgt_next <= 0; 52 | else 53 | trgt_next <= trgt + 1; 54 | end if; 55 | else 56 | cnt_next <= cnt + 1; 57 | end if; 58 | when s2 => 59 | o <= '0'; 60 | if cnt = 15 then 61 | cnt_next <= 0; 62 | state_next <= s1; 63 | else 64 | cnt_next <= cnt + 1; 65 | end if; 66 | end case; 67 | end process; 68 | 69 | end rtla; 70 | 71 | -- implementation #2 72 | -- registers, next-state and output logic are merged 73 | architecture rtlb of fsm_counter is 74 | type state_type is (s1, s2); 75 | signal state : state_type := s1; 76 | 77 | signal cnt : integer range 0 to 15 := 0; 78 | signal trgt : integer range 0 to 15 := 0; 79 | begin 80 | 81 | process(clk) is 82 | begin 83 | if rising_edge(clk) then 84 | case state is 85 | when s1 => 86 | o <= '1'; 87 | if cnt = trgt then 88 | state <= s2; 89 | if trgt = 15 then 90 | trgt <= 0; 91 | else 92 | trgt <= trgt + 1; 93 | end if; 94 | else 95 | cnt <= cnt + 1; 96 | end if; 97 | when s2 => 98 | o <= '0'; 99 | if cnt = 15 then 100 | cnt <= 0; 101 | state <= s1; 102 | else 103 | cnt <= cnt + 1; 104 | end if; 105 | end case; 106 | end if; 107 | end process; 108 | 109 | end rtlb; 110 | -------------------------------------------------------------------------------- /rtl/fsm_serializer.vhd: -------------------------------------------------------------------------------- 1 | -- finite state machine implementation: serializer 2 | -- whenever i_start is high for one clock cycle 3 | -- it will buffer the input data, and start transmission 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | use ieee.numeric_std.all; 7 | 8 | entity fsm_serializer is 9 | generic ( 10 | D : integer := 8 -- data bits 11 | ); 12 | port ( 13 | clk, rst : in std_logic; 14 | i_start : in std_logic; 15 | i_data : in std_logic_vector(D-1 downto 0); 16 | o_tx : out std_logic; 17 | o_tx_done : out std_logic 18 | ); 19 | end fsm_serializer; 20 | 21 | architecture rtl of fsm_serializer is 22 | type state_type is (idle, ones, payload, zeros); 23 | signal state, state_next : state_type := idle; 24 | signal cnt, cnt_next : integer range 0 to 15 := 0; 25 | signal data, data_next : std_logic_vector(D-1 downto 0) := (others =>'0'); 26 | begin 27 | 28 | -- state registers 29 | process(clk) is 30 | begin 31 | if rising_edge(clk) then 32 | if rst = '1' then 33 | state <= idle; 34 | cnt <= 0; 35 | data <= (others=>'0'); 36 | else 37 | state <= state_next; 38 | cnt <= cnt_next; 39 | data <= data_next; 40 | end if; 41 | end if; 42 | end process; 43 | 44 | -- next-state / output logic 45 | process(state, cnt, data, i_start, i_data) is 46 | begin 47 | -- defaults for latch avoidance 48 | -- read from regs and write to _next 49 | state_next <= state; 50 | cnt_next <= cnt; 51 | data_next <= data; 52 | -- since outputs are driven from here 53 | -- we need to pass defaults as well 54 | o_tx <= '0'; 55 | o_tx_done <= '0'; 56 | 57 | case state is 58 | when idle => 59 | if i_start = '1' then 60 | -- latch data so that if it changes 61 | -- our tx does not mess up 62 | data_next <= i_data; 63 | state_next <= ones; 64 | cnt_next <= 0; 65 | end if; 66 | when ones => 67 | -- output when in ones state 68 | o_tx <= '1'; 69 | 70 | if cnt = 3 then 71 | state_next <= payload; 72 | cnt_next <= 0; 73 | else 74 | cnt_next <= cnt + 1; 75 | end if; 76 | when payload => 77 | -- output when in payload state 78 | -- shift lsb out 79 | o_tx <= data(0); 80 | 81 | if cnt = D-1 then 82 | state_next <= zeros; 83 | cnt_next <= 0; 84 | else 85 | -- shift data to right 86 | data_next <= '0' & data(D-1 downto 1); 87 | cnt_next <= cnt + 1; 88 | end if; 89 | when zeros => 90 | -- output when in zeros state 91 | o_tx <= '0'; 92 | 93 | if cnt = 3 then 94 | -- this will send done on the last bit of zeros 95 | -- we could delay it one more cycle if needed 96 | o_tx_done <= '1'; 97 | state_next <= idle; 98 | cnt_next <= 0; 99 | else 100 | cnt_next <= cnt + 1; 101 | end if; 102 | end case; 103 | end process; 104 | 105 | end rtl; -------------------------------------------------------------------------------- /rtl/fsm_serializer_mc.vhd: -------------------------------------------------------------------------------- 1 | -- finite state machine implementation: serializer multi cycle 2 | -- whenever i_start is high for one clock cycle 3 | -- it will buffer the input data, and start transmission 4 | -- each transmission will last for M cycles 5 | library ieee; 6 | use ieee.std_logic_1164.all; 7 | use ieee.numeric_std.all; 8 | 9 | entity fsm_serializer_mc is 10 | generic ( 11 | M : integer := 100; -- timer duration 12 | D : integer := 8 -- data bits 13 | ); 14 | port ( 15 | clk, rst : in std_logic; 16 | i_start : in std_logic; 17 | i_data : in std_logic_vector(D-1 downto 0); 18 | o_tx : out std_logic; 19 | o_tx_done : out std_logic 20 | ); 21 | end fsm_serializer_mc; 22 | 23 | architecture rtl of fsm_serializer_mc is 24 | type state_type is (idle, ones, payload, zeros); 25 | signal state, state_next : state_type := idle; 26 | signal cnt, cnt_next : integer range 0 to 15 := 0; 27 | signal data, data_next : std_logic_vector(D-1 downto 0) := (others =>'0'); 28 | 29 | signal tmrst, tmrtick : std_logic := '0'; 30 | signal tmr : integer := 0; 31 | begin 32 | 33 | -- this is the timer part 34 | -- can be instantiated as a module and port mapped 35 | -- i.e. port map(clk=>clk, rst=>tmrst, done=>tmrtick); 36 | process(clk) is 37 | begin 38 | if rising_edge(clk) then 39 | if tmrst = '1' then 40 | tmr <= 0; 41 | tmrtick <= '0'; 42 | else 43 | if tmr = M-1 then 44 | tmr <= 0; 45 | tmrtick <= '1'; 46 | else 47 | tmr <= tmr + 1; 48 | tmrtick <= '0'; 49 | end if; 50 | end if; 51 | end if; 52 | end process; 53 | 54 | -- state registers 55 | process(clk) is 56 | begin 57 | if rising_edge(clk) then 58 | if rst = '1' then 59 | state <= idle; 60 | cnt <= 0; 61 | data <= (others=>'0'); 62 | else 63 | state <= state_next; 64 | cnt <= cnt_next; 65 | data <= data_next; 66 | end if; 67 | end if; 68 | end process; 69 | 70 | -- next-state / output logic 71 | process(state, cnt, data, i_start, i_data, tmrtick) is 72 | begin 73 | -- defaults for latch avoidance 74 | -- read from regs and write to _next 75 | state_next <= state; 76 | cnt_next <= cnt; 77 | data_next <= data; 78 | -- since outputs are driven from here 79 | -- we need to pass defaults as well 80 | o_tx <= '0'; 81 | o_tx_done <= '0'; 82 | 83 | -- keep timer running by default 84 | tmrst <= '0'; 85 | 86 | case state is 87 | when idle => 88 | if i_start = '1' then 89 | -- latch data so that if it changes 90 | -- our tx does not mess up 91 | data_next <= i_data; 92 | state_next <= ones; 93 | cnt_next <= 0; 94 | else 95 | -- reset timer when in idle and start is not here 96 | tmrst <= '1'; 97 | end if; 98 | when ones => 99 | -- output when in ones state 100 | o_tx <= '1'; 101 | 102 | if tmrtick = '1' then 103 | if cnt = 3 then 104 | state_next <= payload; 105 | cnt_next <= 0; 106 | else 107 | cnt_next <= cnt + 1; 108 | end if; 109 | end if; 110 | when payload => 111 | -- output when in payload state 112 | -- shift lsb out 113 | o_tx <= data(0); 114 | 115 | if tmrtick = '1' then 116 | if cnt = D-1 then 117 | state_next <= zeros; 118 | cnt_next <= 0; 119 | else 120 | -- shift data to right 121 | data_next <= '0' & data(D-1 downto 1); 122 | cnt_next <= cnt + 1; 123 | end if; 124 | end if; 125 | when zeros => 126 | -- output when in zeros state 127 | o_tx <= '0'; 128 | 129 | if tmrtick = '1' then 130 | if cnt = 3 then 131 | -- send tx_done for only one cycle 132 | -- can create another state if multi cycle done 133 | -- signal is needed 134 | o_tx_done <= '1'; 135 | state_next <= idle; 136 | cnt_next <= 0; 137 | else 138 | cnt_next <= cnt + 1; 139 | end if; 140 | end if; 141 | end case; 142 | end process; 143 | 144 | end rtl; -------------------------------------------------------------------------------- /rtl/full_adder.vhd: -------------------------------------------------------------------------------- 1 | -- 1-bit full adder 2 | -- two implementations are given 3 | -- behavioral 4 | -- structural using half_adder design 5 | library ieee; 6 | use ieee.std_logic_1164.all; 7 | 8 | entity full_adder is 9 | -- a, b, cin are inputs of the adder 10 | -- s, cout (carry out) are outputs of the adder 11 | port ( 12 | a, b : in std_logic; 13 | cin : in std_logic; 14 | s : out std_logic; 15 | cout : out std_logic 16 | ); 17 | end full_adder; 18 | 19 | -- behavioral description 20 | architecture bhv of full_adder is 21 | -- intermediate signals 22 | signal m : std_logic := '0'; 23 | begin 24 | 25 | -- concurrent assignments 26 | -- order does not matter 27 | m <= a xor b; 28 | s <= m xor cin; 29 | cout <= (a and b) or (cin and m); 30 | 31 | end bhv; 32 | 33 | -- structural description 34 | architecture str of full_adder is 35 | -- declare half_adder circut as a component 36 | component half_adder is 37 | port ( 38 | x : in std_logic; 39 | y : in std_logic; 40 | s : out std_logic; 41 | c : out std_logic 42 | ); 43 | end component; 44 | -- intermediate signals 45 | signal s0, c0, c1 : std_logic := '0'; 46 | begin 47 | 48 | -- instantiate half_adder component two times 49 | h0 : half_adder port map ( x => a, y => b, s => s0, c => c0 ); 50 | h1 : half_adder port map ( x => s0, y => cin, s => s, c => c1 ); 51 | cout <= c0 or c1; 52 | 53 | end str; -------------------------------------------------------------------------------- /rtl/half_adder.vhd: -------------------------------------------------------------------------------- 1 | -- half adder 2 | -- import std logic library for 3 | -- std_logic and std_logic_vector data types 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | 7 | -- entity of the design 8 | -- defines the input / output ports 9 | entity half_adder is 10 | -- x, y are inputs of the adder 11 | -- s (sum), c (carry) are outputs of the adder 12 | port ( 13 | x : in std_logic; 14 | y : in std_logic; 15 | s : out std_logic; 16 | c : out std_logic 17 | ); 18 | end half_adder; 19 | 20 | -- architecture of the design 21 | -- describes how the circuit works 22 | architecture bhv of half_adder is 23 | 24 | begin 25 | -- two concurrent assignments 26 | -- happens at the same time 27 | -- order does not matter 28 | s <= x xor y; 29 | c <= x and y; 30 | 31 | end bhv; -------------------------------------------------------------------------------- /rtl/hamming.vhd: -------------------------------------------------------------------------------- 1 | -- n-bit hamming distance finder 2 | library ieee; 3 | use ieee.std_logic_1164.all; 4 | use ieee.numeric_std.all; 5 | 6 | entity hamming is 7 | generic( M : integer := 32); 8 | port( 9 | i_a, i_b : in std_logic_vector(M-1 downto 0); 10 | o_dist : out std_logic_vector(7 downto 0) 11 | ); 12 | end hamming; 13 | 14 | architecture rtl of hamming is 15 | signal diff : std_logic_vector(M-1 downto 0) := (others =>'0'); 16 | 17 | -- a function example that sums all the given bits of a std_logic_array 18 | -- and returns an integer 19 | function sum_bits (s : std_logic_vector) return natural is 20 | variable sum : integer range 0 to s'length := 0; 21 | begin 22 | for i in s'range loop 23 | if s(i) = '1' then 24 | sum := sum + 1; 25 | end if; 26 | end loop; 27 | 28 | return sum; 29 | end function; 30 | 31 | begin 32 | 33 | -- we can write a function to sum the bits of a given vector 34 | -- that function returns an integer so we cast it back to std_logic_vector 35 | diff <= i_a xor i_b; 36 | o_dist <= std_logic_vector(to_unsigned( sum_bits(diff), 8)); 37 | 38 | end rtl; 39 | -------------------------------------------------------------------------------- /rtl/mux2.vhd: -------------------------------------------------------------------------------- 1 | -- 2-to-1 mux 2 | library ieee; 3 | use ieee.std_logic_1164.all; 4 | 5 | entity mux2 is 6 | port ( 7 | x : in std_logic_vector(1 downto 0); 8 | sel : in std_logic; 9 | y : out std_logic 10 | ); 11 | end mux2; 12 | 13 | architecture rtl of mux2 is 14 | begin 15 | 16 | with sel select 17 | y <= x(0) when '0', 18 | x(1) when others; 19 | 20 | end rtl; -------------------------------------------------------------------------------- /rtl/mux4.vhd: -------------------------------------------------------------------------------- 1 | -- 4-to-1 mux structural 2 | library ieee; 3 | use ieee.std_logic_1164.all; 4 | 5 | entity mux4 is 6 | port ( 7 | a : in std_logic_vector(3 downto 0); 8 | sel : in std_logic_vector(1 downto 0); 9 | y : out std_logic 10 | ); 11 | end mux4; 12 | 13 | architecture bhv of mux4 is 14 | begin 15 | 16 | with sel select 17 | y <= a(0) when "00", 18 | a(1) when "01", 19 | a(2) when "10", 20 | a(3) when others; 21 | 22 | end bhv; 23 | 24 | architecture str of mux4 is 25 | 26 | -- instantiate mux2 circuit (mux2.vhd) 27 | component mux2 is 28 | port ( 29 | a : in std_logic_vector(1 downto 0); 30 | sel : in std_logic; 31 | y : out std_logic 32 | ); 33 | end component; 34 | 35 | -- signal to hold the first stage mux outputs 36 | signal stage1 : std_logic_vector(1 downto 0) := "00"; 37 | 38 | begin 39 | 40 | -- first stage mux 41 | m1a: mux2 42 | port map ( 43 | a => a(3 downto 2), 44 | sel => sel(0), 45 | y => stage1(0) 46 | ); 47 | 48 | -- sirst stage mux 49 | m1b: mux2 50 | port map ( 51 | a => a(1 downto 0), 52 | sel => sel(0), 53 | y => stage1(1) 54 | ); 55 | 56 | -- second stage mux 57 | m2: mux2 58 | port map ( 59 | a => stage1, 60 | sel => sel(1), 61 | y => y 62 | ); 63 | 64 | end str; 65 | -------------------------------------------------------------------------------- /rtl/parity.vhd: -------------------------------------------------------------------------------- 1 | -- 8-bit parity generator 2 | -- t = 0 for even parity 3 | -- t = 1 for odd parity 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | use ieee.numeric_std.all; 7 | 8 | entity parity is 9 | port ( 10 | a : in std_logic_vector(7 downto 0); 11 | t : in std_logic; 12 | p : out std_logic 13 | ); 14 | end parity; 15 | 16 | architecture rtl of parity is 17 | begin 18 | 19 | process(a, t) is 20 | variable x: std_logic := '0'; 21 | begin 22 | -- 0 out x in the beginning of process 23 | x := '0'; 24 | for i in a'range loop 25 | x := x xor a(i); 26 | end loop; 27 | 28 | p <= x xor t; 29 | end process; 30 | 31 | end rtl; 32 | -------------------------------------------------------------------------------- /rtl/pipeline.vhd: -------------------------------------------------------------------------------- 1 | -- This is a demonstration of a pipeline design 2 | -- showing different implementations of the same design 3 | library ieee; 4 | use ieee.std_logic_1164.all; 5 | use ieee.numeric_std.all; 6 | 7 | entity pipeline is 8 | port ( 9 | clk : in std_logic; 10 | a : in std_logic_vector(7 downto 0); 11 | b : in std_logic_vector(7 downto 0); 12 | c : in std_logic_vector(7 downto 0); 13 | d : in std_logic_vector(7 downto 0); 14 | x : out std_logic_vector(23 downto 0) 15 | ); 16 | end pipeline; 17 | 18 | -- combinational logic 19 | architecture rtla of pipeline is 20 | signal as, bs, cs, ds : signed(7 downto 0) := (others => '0'); 21 | signal xs : signed(23 downto 0) := (others => '0'); 22 | begin 23 | 24 | -- type castings 25 | x <= std_logic_vector(xs); 26 | as <= signed(a); 27 | bs <= signed(b); 28 | cs <= signed(c); 29 | ds <= signed(d); 30 | 31 | -- logic equation: a*b*c + d 32 | xs <= (as * bs * cs) + ds; 33 | 34 | end rtla; 35 | 36 | -- clk bound operation 37 | architecture rtlb of pipeline is 38 | signal as, bs, cs, ds : signed(7 downto 0) := (others => '0'); 39 | signal xs : signed(23 downto 0) := (others => '0'); 40 | begin 41 | 42 | -- type castings 43 | x <= std_logic_vector(xs); 44 | as <= signed(a); 45 | bs <= signed(b); 46 | cs <= signed(c); 47 | ds <= signed(d); 48 | 49 | process(clk) is 50 | begin 51 | if rising_edge(clk) then 52 | xs <= (as * bs * cs) + ds; 53 | end if; 54 | end process; 55 | 56 | end rtlb; 57 | 58 | 59 | -- two clock cycle delayed output using register buffers 60 | architecture rtlc of pipeline is 61 | signal as, bs, cs, ds : signed(7 downto 0) := (others => '0'); 62 | signal xs1, xs2, xs3 : signed(23 downto 0) := (others => '0'); 63 | begin 64 | 65 | -- type castings 66 | x <= std_logic_vector(xs3); 67 | as <= signed(a); 68 | bs <= signed(b); 69 | cs <= signed(c); 70 | ds <= signed(d); 71 | 72 | process(clk) is 73 | begin 74 | if rising_edge(clk) then 75 | xs1 <= (as * bs * cs) + ds; 76 | -- two clk delay 77 | xs2 <= xs1; 78 | xs3 <= xs2; 79 | end if; 80 | end process; 81 | 82 | end rtlc; 83 | 84 | -- pipeline two multiplies and add in three stages 85 | architecture rtld of pipeline is 86 | signal as, bs, cs, ds, cbuf, dbuf1, dbuf2 : signed(7 downto 0) := (others => '0'); 87 | signal xs1 : signed(15 downto 0) := (others => '0'); 88 | signal xs2, xs3 : signed(23 downto 0) := (others => '0'); 89 | begin 90 | 91 | -- type castings 92 | x <= std_logic_vector(xs3); 93 | as <= signed(a); 94 | bs <= signed(b); 95 | cs <= signed(c); 96 | ds <= signed(d); 97 | 98 | process(clk) is 99 | begin 100 | if rising_edge(clk) then 101 | -- first stage: multiply two signals, buffer rest 102 | xs1 <= as * bs; 103 | cbuf <= cs; 104 | dbuf1 <= ds; 105 | -- second stage: multiply remaining signals, buffer rest 106 | xs2 <= xs1 * cbuf; 107 | dbuf2 <= dbuf1; 108 | -- third stage: do the final addition 109 | xs3 <= xs2 + dbuf2; 110 | end if; 111 | end process; 112 | 113 | end rtld; 114 | -------------------------------------------------------------------------------- /rtl/priority.vhd: -------------------------------------------------------------------------------- 1 | -- 32-5 priority encoder 2 | library ieee; 3 | use ieee.std_logic_1164.all; 4 | use ieee.numeric_std.all; 5 | 6 | entity priority is 7 | port ( 8 | a : in std_logic_vector(31 downto 0); 9 | b : out std_logic_vector(4 downto 0) 10 | ); 11 | end priority; 12 | 13 | architecture rtl of priority is 14 | begin 15 | 16 | process(a) is 17 | begin 18 | -- default state if no assignment is made 19 | b <= (others => '0'); 20 | -- go through each bit and assign the last one only 21 | for i in 0 to 31 loop 22 | if a(i) = '1' then 23 | b <= std_logic_vector(to_unsigned(i, 5)); 24 | end if; 25 | end loop; 26 | end process; 27 | end rtl; 28 | -------------------------------------------------------------------------------- /rtl/pulse_generator.vhd: -------------------------------------------------------------------------------- 1 | -- pulse generator 2 | -- generates a one-clock cycle pulse after every 99 clocks; 3 | library ieee; 4 | use ieee.std_logic_1164.all; 5 | use ieee.numeric_std.all; 6 | 7 | entity pulse_generator is 8 | port ( 9 | en, clk : in std_logic; 10 | o_pulse : out std_logic 11 | ); 12 | end pulse_generator; 13 | 14 | architecture rtl of pulse_generator is 15 | signal counter : natural range 0 to 100 := 0; 16 | begin 17 | 18 | process(clk) is 19 | begin 20 | if rising_edge(clk) then 21 | if en = '1' then 22 | -- default output 23 | o_pulse <= '0'; 24 | if counter = 99 then 25 | -- overwritten output 26 | o_pulse <= '1'; 27 | counter <= 0; 28 | else 29 | counter <= counter + 1; 30 | end if; 31 | end if; 32 | end if; 33 | end process; 34 | 35 | end rtl; 36 | -------------------------------------------------------------------------------- /rtl/rca.vhd: -------------------------------------------------------------------------------- 1 | -- ripple carry adder 2 | library ieee; 3 | use ieee.std_logic_1164.all; 4 | 5 | entity rca is 6 | generic (M : integer := 32); 7 | port ( 8 | a, b : in std_logic_vector(M-1 downto 0); 9 | cin : in std_logic; 10 | s : out std_logic_vector(M-1 downto 0); 11 | cout : out std_logic 12 | ); 13 | end rca; 14 | 15 | architecture rtl of rca is 16 | component full_adder 17 | port ( 18 | a, b, cin : in std_logic; 19 | s, cout : out std_logic 20 | ); 21 | end component; 22 | 23 | -- create intermediate signal that will hold c values 24 | signal c : std_logic_vector(M downto 0) := (others =>'0'); 25 | begin 26 | 27 | c(0) <= cin; 28 | cout <= c(M); 29 | 30 | gfa: for i in 0 to M-1 generate 31 | fa: full_adder 32 | port map (a=>a(i), b=>b(i), cin=>c(i), s=>s(i), cout=>c(i+1) ); 33 | end generate; 34 | 35 | end rtl; 36 | -------------------------------------------------------------------------------- /rtl/read_only_mem.vhd: -------------------------------------------------------------------------------- 1 | -- M-bit x N-bit read-only memory 2 | -- M-bit address locations, N-bit wide 3 | library ieee; 4 | use ieee.std_logic_1164.all; 5 | use ieee.numeric_std.all; 6 | 7 | entity read_only_mem is 8 | generic( 9 | M : integer := 4; 10 | N : integer := 8 11 | ); 12 | port( 13 | clk : in std_logic; 14 | addr : in std_logic_vector(M - 1 downto 0); 15 | dout : out std_logic_vector(N - 1 downto 0) 16 | ); 17 | end read_only_mem; 18 | 19 | architecture rtl of read_only_mem is 20 | 21 | type rom_type is array(0 to 2**M - 1) of std_logic_vector(N - 1 downto 0); 22 | 23 | -- 76543210 -> N-bit wide, N is 8 bits 24 | -- -------- 25 | -- 000 | xxxxxxxx 26 | -- 001 | xxxxxxxx 27 | -- 010 | xxxxxxxx 28 | -- ... | .... 29 | -- ... | .... 30 | -- 110 | xxxxxxxx 31 | -- 111 | xxxxxxxx 32 | -- ^ 33 | -- M-bit long, M is 3, 2**3 = 8 address lines 34 | 35 | signal ROM : rom_type := ( 36 | x"00", x"04", x"0C", x"0E", 37 | x"41", x"43", x"49", x"4D", 38 | x"80", x"84", x"8A", x"8E", 39 | x"F0", x"F4", x"FA", x"FF" 40 | ); 41 | 42 | -- set attribute to block RAM 43 | attribute rom_style : string; 44 | attribute rom_style of ROM : signal is "block"; 45 | 46 | begin 47 | 48 | process(clk) is 49 | begin 50 | if rising_edge(clk) then 51 | dout <= ROM(to_integer(unsigned(addr))); 52 | end if; 53 | end process; 54 | 55 | end rtl; 56 | -------------------------------------------------------------------------------- /rtl/rgb2grey.vhd: -------------------------------------------------------------------------------- 1 | -- rgb to greyscale conversion 2 | -- grey = 0.3r + 0.59g + 0.11b 3 | -- in order to get it working: 4 | -- add fixed_pkg_2018.vhd to the project (under scripts/rt/data/ folder in vivado installation) 5 | -- when adding use ieee for the library (compile fixed_pkg_2018 for ieee library) 6 | -- tested on vivado design suite 2018.2 7 | 8 | library ieee; 9 | use ieee.std_logic_1164.all; 10 | use ieee.numeric_std.all; 11 | 12 | -- use the following for synthesis 13 | use ieee.fixed_pkg.all; 14 | 15 | -- use the following for simulation 16 | --library ieee_proposed; 17 | --use ieee_proposed.fixed_pkg.all; 18 | 19 | entity rgb2grey is 20 | port ( 21 | rgb : in std_logic_vector(23 downto 0); 22 | grey : out std_logic_vector(7 downto 0) 23 | ); 24 | end rgb2grey; 25 | 26 | architecture rtl of rgb2grey is 27 | -- ufixed (and sfixed) is a special type that comes with fixed_pkg. 28 | -- max downto 0 represents the integer part 29 | -- -1 downto min represents the fraction part 30 | -- both gets combined into single max downto min representation 31 | signal r, g, b: ufixed(7 downto -2) := (others => '0'); 32 | signal t : ufixed(10 downto -10) := (others => '0'); 33 | begin 34 | 35 | r <= ufixed(rgb(23 downto 16) & "00"); 36 | g <= ufixed(rgb(15 downto 8) & "00"); 37 | b <= ufixed(rgb(7 downto 0) & "00"); 38 | 39 | -- in order to determine the size of t 40 | -- all the multiplications will bring 9 (8 + 1) integer and 10 (2 + 8) float bits 41 | -- the sum of three ufixed numbers will bring 11 (9 + 1 + 1) integer and 10 ( max(10, 10, 10)) float bits 42 | -- so t should be (10 downto 0) + (-1 downto -10) -> (10 downto -10) 43 | t <= r * to_ufixed(0.3, 0, -8) + g * to_ufixed(0.59, 0, -8) + b * to_ufixed(0.11, 0, -8); 44 | --t(8 downto -10) <= r * to_ufixed(0.59, 0, -8); 45 | 46 | grey <= std_logic_vector(to_unsigned(t, 8)); 47 | 48 | end rtl; 49 | -------------------------------------------------------------------------------- /rtl/rgb2yuv.vhd: -------------------------------------------------------------------------------- 1 | -- rgb2yuv converter 2 | -- y = 0.299 R + 0.587 G + 0.114 B 3 | -- u = -0.147 R - 0.289 G + 0.436 B 4 | -- v = 0.615 R - 0.515 G - 0.100 B 5 | 6 | library ieee; 7 | use ieee.std_logic_1164.all; 8 | use ieee.numeric_std.all; 9 | 10 | entity rgb2yuv is 11 | port( 12 | i_rgb : in std_logic_vector(23 downto 0); 13 | o_yuv : out std_logic_vector(23 downto 0) 14 | ); 15 | end rgb2yuv; 16 | 17 | architecture rtl of rgb2yuv is 18 | -- create yuv so that it will hold the multiplication of 19 | -- at least 587 and g value. 587 needs at least 11 20 | -- bits to represent as positive integer. g is 9 bits 21 | -- total which brings to 20 bits total. we give one 22 | -- extra bit from summation overflow to be on the save 23 | -- side 24 | signal y, u, v : signed(20 downto 0) := (others=>'0'); 25 | signal r, g, b : signed(8 downto 0) := (others=>'0'); 26 | begin 27 | 28 | -- convert rgb to signed, but append 0 first so that 29 | -- they don't get treated as negative 30 | r <= signed('0' & i_rgb(23 downto 16)); 31 | g <= signed('0' & i_rgb(15 downto 8)); 32 | b <= signed('0' & i_rgb( 7 downto 0)); 33 | 34 | y <= (to_signed(299, 12)*r + to_signed(587,12)*g + to_signed(114, 12)*b)/1000; 35 | u <= (to_signed(-147, 12)*r - to_signed(289,12)*g + to_signed(436, 12)*b)/1000; 36 | v <= (to_signed(615, 12)*r - to_signed(515,12)*g - to_signed(100, 12)*b)/1000; 37 | 38 | o_yuv <= std_logic_vector(y(7 downto 0) & u(7 downto 0) & v(7 downto 0)); 39 | 40 | end rtl; 41 | -------------------------------------------------------------------------------- /rtl/shift_register.vhd: -------------------------------------------------------------------------------- 1 | -- N-bit shift register 2 | -- a. using concatenation 3 | -- b. using for-loop 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | 7 | entity shreg is 8 | generic( 9 | N : integer := 32 10 | ); 11 | port( 12 | clk : in std_logic; 13 | si : in std_logic; 14 | so : out std_logic 15 | ); 16 | end shreg; 17 | 18 | architecture rtla of shreg is 19 | signal sreg : std_logic_vector(N - 1 downto 0); 20 | begin 21 | 22 | -- a. concatenation way 23 | process(clk) is 24 | begin 25 | if rising_edge(clk) then 26 | sreg <= sreg(N - 2 downto 0) & si; 27 | end if; 28 | end process; 29 | 30 | so <= sreg(N - 1); 31 | 32 | end rtla; 33 | 34 | architecture rtlb of shreg is 35 | signal sreg : std_logic_vector(N - 1 downto 0); 36 | begin 37 | 38 | -- b. for loop way 39 | process(clk) is 40 | begin 41 | if rising_edge(clk) then 42 | for i in 0 to N - 2 loop 43 | sreg(i+1) <= sreg(i); 44 | end loop; 45 | sreg(0) <= si; 46 | end if; 47 | end process; 48 | 49 | so <= sreg(N - 1); 50 | 51 | end rtlb; -------------------------------------------------------------------------------- /tb/tb_adder4.vhd: -------------------------------------------------------------------------------- 1 | -- 4-bit adder subtractor testbench 2 | library ieee; 3 | use ieee.std_logic_1164.all; 4 | use ieee.numeric_std.all; 5 | 6 | entity tb_adder4 is 7 | end tb_adder4; 8 | 9 | architecture bhv of tb_adder4 is 10 | -- declare addsub4 circut as a component 11 | component adder4 is 12 | port ( 13 | a, b : in std_logic_vector(3 downto 0); 14 | cin : in std_logic; 15 | s : out std_logic_vector(3 downto 0); 16 | v, cout : out std_logic 17 | ); 18 | end component; 19 | 20 | signal a, b : std_logic_vector(3 downto 0); 21 | signal s : std_logic_vector(3 downto 0); 22 | signal cin, cout : std_logic; 23 | begin 24 | -- instantiate addsub4 component. 25 | a0: adder4 26 | port map (a => a, b => b, cin => cin, s => s, cout => cout); 27 | 28 | process 29 | begin 30 | wait for 100 ns; 31 | for i in 0 to 15 loop 32 | for j in 0 to 15 loop 33 | a <= std_logic_vector(to_unsigned(i, 4)); 34 | b <= std_logic_vector(to_unsigned(j, 4)); 35 | wait for 1 ns; 36 | cin <= '1'; 37 | wait for 1 ns; 38 | cin <= '0'; 39 | end loop; 40 | end loop; 41 | wait for 10 ns; 42 | wait; 43 | end process; 44 | 45 | end bhv; -------------------------------------------------------------------------------- /tb/tb_addsub4.vhd: -------------------------------------------------------------------------------- 1 | -- 4-bit adder subtractor testbench 2 | library ieee; 3 | use ieee.std_logic_1164.all; 4 | use ieee.numeric_std.all; 5 | 6 | entity tb_addsub4 is 7 | end tb_addsub4; 8 | 9 | architecture bhv of tb_addsub4 is 10 | -- declare addsub4 circut as a component 11 | component addsub4 is 12 | port ( 13 | a, b : in std_logic_vector(3 downto 0); 14 | m : in std_logic; 15 | sum : out std_logic_vector(3 downto 0); 16 | v, cout : out std_logic ); 17 | end component; 18 | 19 | signal a, b : std_logic_vector(3 downto 0); 20 | -- simple 1-bit vector trick to convert integer to std_logic 21 | signal m : std_logic_vector(0 downto 0); 22 | signal sum : std_logic_vector(3 downto 0); 23 | signal v, cout : std_logic; 24 | begin 25 | -- instantiate addsub4 component. 26 | a0: addsub4 27 | port map (a => a, b => b, m => m(0), sum => sum, v => v, cout => cout); 28 | 29 | process 30 | begin 31 | wait for 100 ns; 32 | for sel in 0 to 1 loop 33 | m <= std_logic_vector(to_unsigned(sel, 1)); 34 | for i in 0 to 15 loop 35 | for j in 0 to 15 loop 36 | a <= std_logic_vector(to_unsigned(i, 4)); 37 | b <= std_logic_vector(to_unsigned(j, 4)); 38 | wait for 1 ns; 39 | end loop; 40 | end loop; 41 | wait for 10 ns; 42 | end loop; 43 | wait; 44 | end process; 45 | end bhv; -------------------------------------------------------------------------------- /tb/tb_counter.vhd: -------------------------------------------------------------------------------- 1 | -- 4-bit counter testbench 2 | library ieee; 3 | use ieee.std_logic_1164.all; 4 | use ieee.numeric_std.all; 5 | 6 | entity tb_counter is 7 | end tb_counter; 8 | 9 | architecture bhv of tb_counter is 10 | 11 | signal en, clk : std_logic := '0'; 12 | signal couta, coutb : std_logic_vector(3 downto 0); 13 | signal pulse_o : std_logic := '0'; 14 | 15 | signal clk_period : time := 10 ns; 16 | 17 | begin 18 | 19 | c0: entity work.counter(bhv) 20 | port map (en => en, clk => clk, cout => couta ); 21 | c1: entity work.counter(rtl) 22 | port map (en => en, clk => clk, cout => coutb ); 23 | 24 | -- generate clock signal 25 | clk_process : process 26 | begin 27 | for i in 0 to 100 loop 28 | clk <= not clk; 29 | wait for clk_period/2; 30 | end loop; 31 | wait; 32 | end process; 33 | 34 | -- stimulus 35 | process 36 | begin 37 | wait for clk_period; 38 | en <= '1'; 39 | wait for clk_period * 50; 40 | -- assert if cout != 50 % 12 41 | assert couta = coutb 42 | report "count values don't match" severity error; 43 | assert false 44 | report "completed" severity note; 45 | 46 | wait; 47 | end process; 48 | end bhv; -------------------------------------------------------------------------------- /tb/tb_dualram.vhd: -------------------------------------------------------------------------------- 1 | -- dualram testbench 2 | -- this testbench is for post-synthesis simulations 3 | -- or fixed M/N value pair behavioral simulations 4 | -- for M=5 and N=32 5 | library ieee; 6 | use ieee.std_logic_1164.all; 7 | use ieee.numeric_std.all; 8 | 9 | entity tb_dualram is 10 | end tb_dualram; 11 | 12 | architecture bhv of tb_dualram is 13 | component dualram is 14 | port( 15 | clka, clkb : in std_logic; 16 | ena, enb : in std_logic; 17 | wea : in std_logic; 18 | addra, addrb : in std_logic_vector(4 downto 0); 19 | dina : in std_logic_vector(31 downto 0); 20 | doutb : out std_logic_vector(31 downto 0) 21 | ); 22 | end component; 23 | 24 | constant CLKA_PERIOD : time := 8 ns; 25 | constant CLKB_PERIOD : time := 8 ns; 26 | 27 | signal clka, clkb : std_logic := '0'; 28 | signal ena, enb, wea : std_logic := '0'; 29 | signal addra, addrb : std_logic_vector(4 downto 0) := (others=>'0'); 30 | signal dina, doutb : std_logic_vector(31 downto 0) := (others=>'0'); 31 | 32 | begin 33 | 34 | uut0 : dualram 35 | port map (clka=>clka, clkb=>clkb, ena=>ena, enb=>enb, wea=>wea, 36 | addra=>addra, addrb=>addrb, dina=>dina, doutb=>doutb); 37 | 38 | process 39 | begin 40 | clka <= not clka; 41 | wait for CLKA_PERIOD/2; 42 | end process; 43 | 44 | process 45 | begin 46 | clkb <= not clkb; 47 | wait for CLKB_PERIOD/2; 48 | end process; 49 | 50 | -- stimulus 51 | process 52 | begin 53 | wait for 10 ns; 54 | ena <= '0'; 55 | enb <= '1'; 56 | wea <= '0'; 57 | for i in 0 to 2**5 - 1 loop 58 | addrb <= std_logic_vector(to_unsigned(i, 5)); 59 | wait for CLKA_PERIOD; 60 | end loop; 61 | wait; 62 | end process; 63 | end bhv; -------------------------------------------------------------------------------- /tb/tb_fifo.vhd: -------------------------------------------------------------------------------- 1 | -- fifo testbench 2 | library ieee; 3 | use ieee.std_logic_1164.all; 4 | use ieee.numeric_std.all; 5 | 6 | entity tb_fifo is 7 | end tb_fifo; 8 | 9 | architecture rtl of tb_fifo is 10 | 11 | constant M : integer := 4; 12 | constant N : integer := 8; 13 | signal rst, clk_wr, wr_en, clk_rd, rd_en : std_logic := '0'; 14 | signal din : std_logic_vector(N - 1 downto 0) := (others => '0'); 15 | 16 | signal empty_async, full_async : std_logic; 17 | signal empty_sync, full_sync : std_logic; 18 | signal dout_async : std_logic_vector(N - 1 downto 0) := (others => '0'); 19 | signal dout_sync : std_logic_vector(N - 1 downto 0) := (others => '0'); 20 | 21 | constant clk_wr_time : time := 20 ns; 22 | constant clk_rd_time : time := 10 ns; 23 | 24 | begin 25 | f0: entity work.fifo_sync(rtl) 26 | generic map ( M=>M, N=>N ) 27 | port map ( 28 | i_rst=>rst, i_clk=>clk_rd, i_wr_en=>wr_en, 29 | i_din=>din, i_rd_en=>rd_en, 30 | o_dout=>dout_sync, o_empty=>empty_sync, o_full=>full_sync 31 | ); 32 | 33 | f2: entity work.fifo_async(rtl) 34 | generic map ( M=>M, N=>N ) 35 | port map ( 36 | i_rst=>rst, i_clk_wr=>clk_wr, i_wr_en=>wr_en, 37 | i_din=>din, i_clk_rd=>clk_rd, i_rd_en=>rd_en, 38 | o_dout=>dout_async, o_empty=>empty_async, o_full=>full_async 39 | ); 40 | 41 | -- write clock 42 | gen_wr_clk: process 43 | begin 44 | for i in 0 to 100 loop 45 | wait for clk_wr_time/2; 46 | clk_wr <= '1'; 47 | wait for clk_wr_time/2; 48 | clk_wr <= '0'; 49 | end loop; 50 | wait; 51 | end process; 52 | 53 | -- read clock 54 | gen_rd_clk: process 55 | begin 56 | for i in 0 to 200 loop 57 | wait for clk_rd_time/2; 58 | clk_rd <= '1'; 59 | wait for clk_rd_time/2; 60 | clk_rd <= '0'; 61 | end loop; 62 | wait; 63 | end process; 64 | 65 | -- stimulus 66 | stimulus: process 67 | begin 68 | rst <= '1'; 69 | wait for 20 * clk_rd_time; 70 | rst <= '0'; 71 | 72 | for i in 1 to 20 loop 73 | din <= std_logic_vector(to_unsigned(i, N)); 74 | wait for clk_wr_time; 75 | wr_en <= '1'; 76 | wait for clk_wr_time; 77 | wr_en <= '0'; 78 | end loop; 79 | 80 | wait until clk_rd = '0'; 81 | rd_en <= '1'; 82 | wait for 3 * clk_rd_time; 83 | rd_en <= '0'; 84 | 85 | for i in 1 to 5 loop 86 | din <= std_logic_vector(to_unsigned(i, N)); 87 | wait for clk_wr_time; 88 | wr_en <= '1'; 89 | wait for clk_wr_time; 90 | wr_en <= '0'; 91 | end loop; 92 | 93 | wait until clk_rd = '0'; 94 | 95 | for i in 1 to 20 loop 96 | rd_en <= '1'; 97 | wait for clk_rd_time; 98 | end loop; 99 | 100 | wait; 101 | end process; 102 | 103 | end rtl; 104 | -------------------------------------------------------------------------------- /tb/tb_fsm.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.std_logic_1164.all; 3 | 4 | entity tb_fsm is 5 | end tb_fsm; 6 | 7 | architecture rtl of tb_fsm is 8 | 9 | signal clk : std_logic := '0'; 10 | signal a, b : std_logic := '0'; 11 | signal moore_a, mealy_a : std_logic; 12 | signal moore_b, mealy_b : std_logic; 13 | signal moore_c, mealy_c : std_logic; 14 | 15 | constant wait_time : time := 10 ns; 16 | 17 | begin 18 | 19 | fsma : entity work.fsm(rtla) 20 | port map(clk=>clk, a=>a, b=>b, moore=>moore_a, mealy=>mealy_a); 21 | fsmb : entity work.fsm(rtlb) 22 | port map(clk=>clk, a=>a, b=>b, moore=>moore_b, mealy=>mealy_b); 23 | fsmc : entity work.fsm(rtlc) 24 | port map(clk=>clk, a=>a, b=>b, moore=>moore_c, mealy=>mealy_c); 25 | 26 | process 27 | begin 28 | for i in 0 to 15 loop 29 | wait for wait_time; 30 | clk <= '1'; 31 | wait for wait_time; 32 | clk <= '0'; 33 | end loop; 34 | wait; 35 | end process; 36 | 37 | process 38 | begin 39 | a <= '0'; 40 | b <= '0'; 41 | wait for 25 ns; 42 | a <= '1'; 43 | wait for 52 ns; 44 | a <= '0'; 45 | wait for 30 ns; 46 | a <= '1'; 47 | b <= '1'; 48 | wait for 50 ns; 49 | b <= '0'; 50 | wait for 50 ns; 51 | a <= '0'; 52 | wait for 20 ns; 53 | a <= '1'; 54 | b <= '1'; 55 | wait for 30 ns; 56 | a <= '0'; 57 | wait; 58 | end process; 59 | end rtl; -------------------------------------------------------------------------------- /tb/tb_fsm_counter.vhd: -------------------------------------------------------------------------------- 1 | -- tb_fsm_counter.vhd 2 | library ieee; 3 | use ieee.std_logic_1164.all; 4 | 5 | entity tb_fsm_counter is 6 | end tb_fsm_counter; 7 | 8 | architecture rtl of tb_fsm_counter is 9 | 10 | signal clk : std_logic := '0'; 11 | signal o1, o2 : std_logic; 12 | 13 | constant wait_time : time := 10 ns; 14 | 15 | begin 16 | 17 | fsm2a : entity work.fsm_counter(rtla) 18 | port map(clk=>clk, o=>o1); 19 | fsm2b : entity work.fsm_counter(rtlb) 20 | port map(clk=>clk, o=>o2); 21 | 22 | process 23 | begin 24 | wait for wait_time; 25 | clk <= '1'; 26 | wait for wait_time; 27 | clk <= '0'; 28 | end process; 29 | 30 | -- no need to do anything extra. it is an automatic counter 31 | 32 | end rtl; -------------------------------------------------------------------------------- /tb/tb_fsm_serializer.vhd: -------------------------------------------------------------------------------- 1 | -- testbench for fsm_serializer and fsm_serializer_mc 2 | -- fsm_serializer will receive two data and transmit it 3 | -- fsm_serializer_mc will receive one data and transmit it 4 | -- since multi cycle will take way longer 5 | library ieee; 6 | use ieee.std_logic_1164.all; 7 | 8 | entity tb_fsm_serializer is 9 | end tb_fsm_serializer; 10 | 11 | architecture rtl of tb_fsm_serializer is 12 | 13 | constant M : integer := 10; 14 | constant D : integer := 8; 15 | 16 | signal clk : std_logic := '0'; 17 | signal rst : std_logic := '1'; 18 | signal i_data : std_logic_vector(D-1 downto 0) := (others=>'0'); 19 | signal i_start : std_logic := '0'; 20 | signal o_tx1, o_tx_done1 : std_logic := '0'; 21 | signal o_tx2, o_tx_done2 : std_logic := '0'; 22 | 23 | constant CLK_PERIOD : time := 10 ns; 24 | 25 | begin 26 | 27 | uut1 : entity work.fsm_serializer(rtl) 28 | generic map(D=>D) 29 | port map(clk=>clk, rst=>rst, 30 | i_start=>i_start, i_data=>i_data, 31 | o_tx=>o_tx1, o_tx_done=>o_tx_done1); 32 | 33 | uut2 : entity work.fsm_serializer_mc(rtl) 34 | generic map(M=>M, D=>D) 35 | port map(clk=>clk, rst=>rst, 36 | i_start=>i_start, i_data=>i_data, 37 | o_tx=>o_tx2, o_tx_done=>o_tx_done2); 38 | 39 | -- generate clock 40 | clk <= not clk after CLK_PERIOD/2; 41 | 42 | process 43 | begin 44 | wait for 100 ns; 45 | rst <= '0'; 46 | wait for 100 ns; 47 | -- first byte 48 | i_data <= x"A7"; 49 | i_start <= '1'; 50 | wait for CLK_PERIOD; 51 | -- intentionally zero out both data and start 52 | -- to see if data and start is properly latched 53 | i_start <= '0'; 54 | i_data <= x"00"; 55 | wait until o_tx_done1 = '1'; 56 | -- second byte 57 | wait for 4*CLK_PERIOD; 58 | i_data <= x"4C"; 59 | i_start <= '1'; 60 | wait for CLK_PERIOD; 61 | i_start <= '0'; 62 | i_data <= x"00"; 63 | wait until o_tx_done2 = '1'; 64 | wait; 65 | end process; 66 | end rtl; -------------------------------------------------------------------------------- /tb/tb_full_adder.vhd: -------------------------------------------------------------------------------- 1 | -- 1-bit full adder testbench 2 | -- modified from ghdl adder testbench example 3 | -- A testbench has no ports 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | 7 | entity tb_full_adder is 8 | end tb_full_adder; 9 | 10 | architecture bhv of tb_full_adder is 11 | -- with '93, component does not 12 | -- need to be declared anymore 13 | signal a, b, cin : std_logic; 14 | signal s0, s1, cout0, cout1 : std_logic; 15 | begin 16 | -- instantiate full_adder component 17 | -- syntax: entity work.entity_name(arch_name) 18 | f0: entity work.full_adder(bhv) 19 | port map (a => a, b => b, cin => cin, s => s0, cout => cout0); 20 | 21 | f1: entity work.full_adder(str) 22 | port map (a => a, b => b, cin => cin, s => s1, cout => cout1); 23 | 24 | process 25 | type pattern_type is record 26 | -- inputs of the adder. 27 | a, b, cin : std_logic; 28 | -- expected outputs of the adder. 29 | s, cout : std_logic; 30 | end record; 31 | -- patterns to apply. 32 | type pattern_array is array (natural range <>) of pattern_type; 33 | constant patterns : pattern_array := 34 | (('0', '0', '0', '0', '0'), 35 | ('0', '0', '1', '1', '0'), 36 | ('0', '1', '0', '1', '0'), 37 | ('0', '1', '1', '0', '1'), 38 | ('1', '0', '0', '1', '0'), 39 | ('1', '0', '1', '0', '1'), 40 | ('1', '1', '0', '0', '1'), 41 | ('1', '1', '1', '1', '1')); 42 | begin 43 | -- check each pattern. 44 | for i in patterns'range loop 45 | -- Set the inputs. 46 | a <= patterns(i).a; 47 | b <= patterns(i).b; 48 | cin <= patterns(i).cin; 49 | -- wait for the results. 50 | wait for 1 ns; 51 | -- check the outputs. 52 | assert s0 = patterns(i).s 53 | report "bad sum value" severity error; 54 | assert s1 = patterns(i).s 55 | report "bad sum value" severity error; 56 | assert cout0 = patterns(i).cout 57 | report "bad carray out value" severity error; 58 | assert cout1 = patterns(i).cout 59 | report "bad carray out value" severity error; 60 | end loop; 61 | assert false report "end of test" severity note; 62 | -- wait forever; this will finish the simulation. 63 | wait; 64 | end process; 65 | end bhv; -------------------------------------------------------------------------------- /tb/tb_half_adder.vhd: -------------------------------------------------------------------------------- 1 | -- half adder testbench 2 | -- essentially this is a wrapper around the 3 | -- circuit that we want to test; 4 | -- declares and connects the circuit under test 5 | -- generates signals for the inputs 6 | -- watches the ouputs 7 | library ieee; 8 | use ieee.std_logic_1164.all; 9 | 10 | -- testbench has no ports 11 | entity tb_half_adder is 12 | end tb_half_adder; 13 | 14 | architecture bhv of tb_half_adder is 15 | -- declare half_adder circut as a component 16 | component half_adder is 17 | port ( 18 | x : in std_logic; 19 | y : in std_logic; 20 | s : out std_logic; 21 | c : out std_logic 22 | ); 23 | end component; 24 | 25 | -- declare internal signals 26 | signal x, y, s, c : std_logic; 27 | 28 | begin 29 | -- instantiate half_adder component. 30 | h0: half_adder 31 | port map (x => x, y => y, s => s, c => c); 32 | 33 | -- stimuli 34 | process 35 | begin 36 | -- initial state wait 37 | wait for 10 ns; 38 | -- apply first set of patterns to the inputs 39 | x <= '0'; 40 | y <= '0'; 41 | -- hold this state for 10 ns 42 | wait for 10 ns; 43 | -- assert if sum or carry are not correcty 44 | assert s = '0' 45 | report "bad sum value" severity error; 46 | assert c = '0' 47 | report "bad carry value" severity error; 48 | -- apply second set 49 | x <= '0'; 50 | y <= '1'; 51 | wait for 10 ns; 52 | assert s = '1' 53 | report "bad sum value" severity error; 54 | assert c = '0' 55 | report "bad carry value" severity error; 56 | -- apply third set 57 | x <= '1'; 58 | y <= '0'; 59 | wait for 10 ns; 60 | assert s = '1' 61 | report "bad sum value" severity error; 62 | assert c = '0' 63 | report "bad carry value" severity error; 64 | -- apply forth set 65 | x <= '1'; 66 | y <= '1'; 67 | wait for 10 ns; 68 | assert s = '0' 69 | report "bad sum value" severity error; 70 | assert c = '1' 71 | report "bad carry value" severity error; 72 | 73 | assert false 74 | report "completed" severity note; 75 | 76 | -- wait forever; this will finish the simulation 77 | wait; 78 | end process; 79 | 80 | end bhv; -------------------------------------------------------------------------------- /tb/tb_hamming.vhd: -------------------------------------------------------------------------------- 1 | -- hamming distance finder testbench 2 | library ieee; 3 | use ieee.std_logic_1164.all; 4 | use ieee.numeric_std.all; 5 | 6 | entity tb_hamming is 7 | end tb_hamming; 8 | 9 | architecture bhv of tb_hamming is 10 | 11 | constant M : integer := 16; 12 | signal a, b : std_logic_vector(15 downto 0) := (others => '0'); 13 | signal d : std_logic_vector(7 downto 0); 14 | 15 | begin 16 | 17 | -- careful with positional mapping. not adviced 18 | -- use proper port mapping instead 19 | h0 : entity work.hamming(rtl) 20 | generic map (M => M) 21 | port map (i_a => a, i_b => b, o_dist => d); 22 | 23 | -- stimulus 24 | process 25 | begin 26 | wait for 10 ns; 27 | a <= x"AAAA"; 28 | b <= x"0000"; 29 | wait for 10 ns; 30 | a <= x"FFFF"; 31 | b <= x"FFFE"; 32 | wait for 10 ns; 33 | a <= x"1100"; 34 | b <= x"0011"; 35 | wait for 10 ns; 36 | a <= x"0000"; 37 | b <= x"FFFF"; 38 | wait for 10 ns; 39 | wait; 40 | end process; 41 | end bhv; -------------------------------------------------------------------------------- /tb/tb_parity.vhd: -------------------------------------------------------------------------------- 1 | -- parity calculation testbench 2 | library ieee; 3 | use ieee.std_logic_1164.all; 4 | use ieee.numeric_std.all; 5 | 6 | entity tb_parity is 7 | end tb_parity; 8 | 9 | architecture bhv of tb_parity is 10 | signal a : std_logic_vector(7 downto 0) := (others => '0'); 11 | signal t, p : std_logic; 12 | begin 13 | 14 | uut : entity work.parity(rtl) 15 | port map( a => a, t => t, p => p); 16 | 17 | process 18 | begin 19 | -- testing for even parity 20 | t <= '0'; 21 | a <= (others => '0'); 22 | wait for 10 ns; 23 | a <= "01000000"; 24 | wait for 10 ns; 25 | a <= "00000001"; 26 | wait for 10 ns; 27 | a <= "01000100"; 28 | wait for 10 ns; 29 | a <= "01010010"; 30 | wait for 10 ns; 31 | a <= "01010011"; 32 | wait for 10 ns; 33 | a <= "11111111"; 34 | wait for 30 ns; 35 | -- testing for odd parity 36 | t <= '1'; 37 | a <= (others => '0'); 38 | wait for 10 ns; 39 | a <= "01000000"; 40 | wait for 10 ns; 41 | a <= "00000001"; 42 | wait for 10 ns; 43 | a <= "01000100"; 44 | wait for 10 ns; 45 | a <= "01010010"; 46 | wait for 10 ns; 47 | a <= "01010011"; 48 | wait for 10 ns; 49 | a <= "11111111"; 50 | wait for 10 ns; 51 | wait; 52 | end process; 53 | 54 | end bhv; 55 | -------------------------------------------------------------------------------- /tb/tb_pipeline.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.std_logic_1164.all; 3 | use ieee.numeric_std.all; 4 | 5 | entity tb_pipeline is 6 | end tb_pipeline; 7 | 8 | architecture rtl of tb_pipeline is 9 | 10 | signal clk : std_logic := '0'; 11 | signal a, b, c, d : std_logic_vector(7 downto 0); 12 | signal xa, xb, xc, xd : std_logic_vector(23 downto 0); 13 | 14 | constant CLK_PERIOD : time := 40 ns; 15 | 16 | begin 17 | 18 | p0_comblogic : entity work.pipeline(rtla) 19 | port map(clk=>clk, a=>a, b=>b, c=>c, d=>d, x=>xa); 20 | p1_clkbound : entity work.pipeline(rtlb) 21 | port map(clk=>clk, a=>a, b=>b, c=>c, d=>d, x=>xb); 22 | p2_clkdelay : entity work.pipeline(rtlc) 23 | port map(clk=>clk, a=>a, b=>b, c=>c, d=>d, x=>xc); 24 | p2_pipeline : entity work.pipeline(rtld) 25 | port map(clk=>clk, a=>a, b=>b, c=>c, d=>d, x=>xd); 26 | 27 | -- generate clock 28 | clk <= not clk after CLK_PERIOD/2; 29 | 30 | process 31 | variable as, bs, cs, ds : signed(7 downto 0) := (others=>'0'); 32 | begin 33 | wait for 130 ns; -- wait for some time 34 | for i in 0 to 15 loop 35 | -- send data in every new clkc cycle 36 | --wait until clk = '1'; 37 | as := to_signed( 100, 8); 38 | bs := to_signed( i, 8); 39 | cs := to_signed( i*i, 8); 40 | ds := to_signed(60-i, 8); 41 | -- x = a * b * c + d 42 | -- x = 100 * i * i*i + 60-i 43 | a <= std_logic_vector(as); 44 | b <= std_logic_vector(bs); 45 | c <= std_logic_vector(cs); 46 | d <= std_logic_vector(ds); 47 | wait for 40 ns; 48 | end loop; 49 | 50 | wait; -- do not repeat 51 | end process; 52 | end rtl; -------------------------------------------------------------------------------- /tb/tb_priority.vhd: -------------------------------------------------------------------------------- 1 | -- priority encoder testbench 2 | library ieee; 3 | use ieee.std_logic_1164.all; 4 | use ieee.numeric_std.all; 5 | 6 | entity tb_priority is 7 | end tb_priority; 8 | 9 | architecture bhv of tb_priority is 10 | signal a : std_logic_vector(31 downto 0) := (others => '0'); 11 | signal b : std_logic_vector(4 downto 0); 12 | begin 13 | 14 | uut : entity work.priority(rtl) 15 | port map( a=>a, b=>b); 16 | 17 | process 18 | begin 19 | a <= (0=>'1', others=>'0'); 20 | wait for 10 ns; 21 | a <= (4=>'1', others=>'0'); 22 | wait for 10 ns; 23 | a <= (7=>'1', others=>'0'); 24 | wait for 10 ns; 25 | a <= (12=>'1', others=>'0'); 26 | wait for 10 ns; 27 | a <= (15=>'1', others=>'0'); 28 | wait for 10 ns; 29 | a <= (25=>'1', others=>'0'); 30 | wait for 10 ns; 31 | a <= (30=>'1', others=>'0'); 32 | wait for 10 ns; 33 | a <= (31=>'1', others=>'0'); 34 | wait for 30 ns; 35 | a <= x"0100AF00"; 36 | wait for 10 ns; 37 | a <= x"F0AC0301"; 38 | wait for 10 ns; 39 | a <= x"002F0001"; 40 | wait for 10 ns; 41 | a <= x"FFFFFFFF"; 42 | wait for 10 ns; 43 | wait; 44 | end process; 45 | 46 | end bhv; 47 | -------------------------------------------------------------------------------- /tb/tb_rgb2grey.vhd: -------------------------------------------------------------------------------- 1 | -- rgb to greyscale conversion testbench 2 | library ieee; 3 | use ieee.std_logic_1164.all; 4 | use ieee.numeric_std.all; 5 | 6 | entity tb_rgb2grey is 7 | end tb_rgb2grey; 8 | 9 | architecture bhv of tb_rgb2grey is 10 | signal rgb : std_logic_vector(23 downto 0); 11 | signal grey : std_logic_vector(7 downto 0); 12 | begin 13 | 14 | uut : entity work.rgb2grey(rtl) 15 | port map( rgb => rgb, grey => grey); 16 | 17 | process 18 | begin 19 | wait for 10 ns; 20 | rgb <= x"000000"; 21 | wait for 10 ns; 22 | rgb <= x"A0A0A0"; 23 | wait for 10 ns; 24 | rgb <= x"39491A"; 25 | wait for 10 ns; 26 | rgb <= x"300000"; 27 | wait for 10 ns; 28 | rgb <= x"123DEF"; 29 | wait for 10 ns; 30 | wait; 31 | end process; 32 | 33 | end bhv; 34 | -------------------------------------------------------------------------------- /tb/tb_rgb2yuv.vhd: -------------------------------------------------------------------------------- 1 | -- rgb to yuv conversion testbench 2 | library ieee; 3 | use ieee.std_logic_1164.all; 4 | use ieee.numeric_std.all; 5 | 6 | entity tb_rgb2yuv is 7 | end tb_rgb2yuv; 8 | 9 | architecture bhv of tb_rgb2yuv is 10 | signal rgb : std_logic_vector(23 downto 0); 11 | signal yuv : std_logic_vector(23 downto 0); 12 | begin 13 | 14 | uut : entity work.rgb2yuv(rtl) 15 | port map( i_rgb => rgb, o_yuv => yuv); 16 | 17 | process 18 | begin 19 | wait for 10 ns; 20 | rgb <= x"000000"; 21 | wait for 10 ns; 22 | rgb <= x"A0A0A0"; -- A08080 23 | wait for 10 ns; 24 | rgb <= x"39491A"; 25 | wait for 10 ns; 26 | rgb <= x"300000"; 27 | wait for 10 ns; 28 | rgb <= x"123DEF"; 29 | wait for 10 ns; 30 | wait; 31 | end process; 32 | 33 | end bhv; 34 | -------------------------------------------------------------------------------- /tools/ram_content.data: -------------------------------------------------------------------------------- 1 | 11111111111111111111111111111111 2 | 01111111111111111111111111111111 3 | 00111111111111111111111111111111 4 | 00011111111111111111111111111111 5 | 00001111111111111111111111111111 6 | 00000111111111111111111111111111 7 | 00000011111111111111111111111111 8 | 00000001111111111111111111111111 9 | 00000000111111111111111111111111 10 | 00000000011111111111111111111111 11 | 00000000001111111111111111111111 12 | 00000000000111111111111111111111 13 | 00000000000011111111111111111111 14 | 00000000000001111111111111111111 15 | 00000000000000111111111111111111 16 | 00000000000000011111111111111111 17 | 00000000000000001111111111111111 18 | 00000000000000000111111111111111 19 | 00000000000000000011111111111111 20 | 00000000000000000001111111111111 21 | 00000000000000000000111111111111 22 | 00000000000000000000011111111111 23 | 00000000000000000000001111111111 24 | 00000000000000000000000111111111 25 | 00000000000000000000000011111111 26 | 00000000000000000000000001111111 27 | 00000000000000000000000000111111 28 | 00000000000000000000000000011111 29 | 00000000000000000000000000001111 30 | 00000000000000000000000000000111 31 | 00000000000000000000000000000011 32 | 00000000000000000000000000000001 -------------------------------------------------------------------------------- /tools/rgb2yuv.py: -------------------------------------------------------------------------------- 1 | def rgb2yuv(r, g, b): 2 | y = 0.299 * r + 0.587 * g + 0.114 * b 3 | u = -0.147 * r - 0.289 * g + 0.436 * b 4 | v = 0.615 * r - 0.515 * g - 0.100 * b 5 | 6 | return hex(int(y)), hex(int(u)), hex(int(v)) 7 | 8 | print(rgb2yuv(int("00", 16), int("00", 16), int("00", 16))) 9 | print(rgb2yuv(int("A0", 16), int("A0", 16), int("A0", 16))) 10 | print(rgb2yuv(int("39", 16), int("49", 16), int("1A", 16))) 11 | print(rgb2yuv(int("30", 16), int("00", 16), int("00", 16))) 12 | print(rgb2yuv(int("12", 16), int("3D", 16), int("EF", 16))) 13 | --------------------------------------------------------------------------------