├── .gitignore ├── .travis.yml ├── AUTHORS ├── COPYING ├── README ├── README.md ├── rtl ├── arbiter.v ├── axis_wb_master.v ├── priority_encoder.v ├── wb_adapter.v ├── wb_arbiter.py ├── wb_arbiter_2.v ├── wb_async_reg.v ├── wb_dp_ram.v ├── wb_mux.py ├── wb_mux_2.v ├── wb_ram.v └── wb_reg.v └── tb ├── axis_ep.py ├── test_arbiter.py ├── test_arbiter.v ├── test_arbiter_rr.py ├── test_arbiter_rr.v ├── test_axis_wb_master_8_32.py ├── test_axis_wb_master_8_32.v ├── test_axis_wb_master_8_32_16.py ├── test_axis_wb_master_8_32_16.v ├── test_axis_wb_master_8_32_imp.py ├── test_axis_wb_master_8_32_imp.v ├── test_priority_encoder.py ├── test_priority_encoder.v ├── test_wb.py ├── test_wb_16.py ├── test_wb_adapter_16_32.py ├── test_wb_adapter_16_32.v ├── test_wb_adapter_32_16.py ├── test_wb_adapter_32_16.v ├── test_wb_adapter_32_8.py ├── test_wb_adapter_32_8.v ├── test_wb_adapter_8_32.py ├── test_wb_adapter_8_32.v ├── test_wb_arbiter_2.py ├── test_wb_arbiter_2.v ├── test_wb_async_reg.py ├── test_wb_async_reg.v ├── test_wb_dp_ram.py ├── test_wb_dp_ram.v ├── test_wb_mux_2.py ├── test_wb_mux_2.v ├── test_wb_ram.py ├── test_wb_ram.v ├── test_wb_ram_model.py ├── test_wb_reg.py ├── test_wb_reg.v └── wb.py /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.lxt 3 | *.pyc 4 | *.vvp 5 | *.kate-swp 6 | 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - "3.6" 4 | before_install: 5 | - export d=`pwd` 6 | - export PYTHON_EXE=`which python` 7 | - sudo apt-get update -qq 8 | - sudo apt-get install -y iverilog 9 | - git clone https://github.com/jandecaluwe/myhdl.git 10 | - cd $d/myhdl && sudo $PYTHON_EXE setup.py install 11 | - cd $d/myhdl/cosimulation/icarus && make && sudo install -m 0755 -D ./myhdl.vpi /usr/lib/x86_64-linux-gnu/ivl/myhdl.vpi 12 | - cd $d 13 | script: 14 | - cd tb && py.test 15 | 16 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Alex Forencich 2 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015-2016 Alex Forencich 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | 21 | 22 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | README.md -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Verilog Wishbone Components Readme 2 | 3 | For more information and updates: http://alexforencich.com/wiki/en/verilog/wishbone/start 4 | 5 | GitHub repository: https://github.com/alexforencich/verilog-wishbone 6 | 7 | ## Introduction 8 | 9 | Collection of Wishbone bus components. Most components are fully 10 | parametrizable in interface widths. Includes full MyHDL testbench with 11 | intelligent bus cosimulation endpoints. 12 | 13 | ## Documentation 14 | 15 | ### arbiter module 16 | 17 | General-purpose parametrizable arbiter. Supports priority and round-robin 18 | arbitration. Supports blocking until request release or acknowledge. 19 | 20 | ### axis_wb_master module 21 | 22 | AXI Stream Wishbone master. Intended to be used to bridge a streaming 23 | or packet-based protocol (serial, ethernet, etc.) to a Wishbone bus. 24 | 25 | ### priority_encoder module 26 | 27 | Parametrizable priority encoder. 28 | 29 | ### wb_adapter module 30 | 31 | Width adapter module to bridge wishbone buses of differing widths. The module 32 | is parametrizable, but their are certain restrictions. First, the bus word 33 | widths must be identical (same data bus width per select line). Second, the 34 | bus widths must be related by an integer multiple (e.g. 2 words and 6 words, 35 | but not 4 words and 6 words). 36 | 37 | ### wb_arbiter_N module 38 | 39 | Parametrizable arbiter module to enable sharing between multiple masters. 40 | 41 | Can be generated with arbitrary port counts with wb_arbiter.py. 42 | 43 | ### wb_async_reg module 44 | 45 | Asynchronous register module for clock domain crossing with parametrizable 46 | data and address interface widths. Uses internal synchronization to pass 47 | wishbone bus cycles across clock domain boundaries. 48 | 49 | ### wb_dp_ram module 50 | 51 | Dual-port, dual-clock RAM with parametrizable data and address interface 52 | widths. 53 | 54 | ### wb_mux_N module 55 | 56 | Wishbone multiplexer with parametrizable data and address interface widths. 57 | 58 | Can be generated with arbitrary port counts with wb_mux.py. 59 | 60 | ### wb_ram module 61 | 62 | RAM with parametrizable data and address interface widths. 63 | 64 | ### wb_reg module 65 | 66 | Synchronous register with parametrizable data and address interface widths. 67 | Registers all wishbone signals. Used to improve timing for long routes. 68 | 69 | ### Source Files 70 | 71 | arbiter.v : General-purpose parametrizable arbiter 72 | axis_wb_master.v : AXI Stream Wishbone master 73 | priority_encoder.v : Parametrizable priority encoder 74 | wb_adapter.v : Parametrizable bus width adapter 75 | wb_arbiter.py : Arbiter generator 76 | wb_arbiter_2.py : 2 port WB arbiter 77 | wb_async_reg.v : Asynchronous register 78 | wb_dp_ram.v : Dual port RAM 79 | wb_mux.py : WB mux generator 80 | wb_mux_2.v : 2 port WB mux 81 | wb_ram.v : Single port RAM 82 | wb_reg.v : Register 83 | 84 | ## Testing 85 | 86 | Running the included testbenches requires MyHDL and Icarus Verilog. Make sure 87 | that myhdl.vpi is installed properly for cosimulation to work correctly. The 88 | testbenches can be run with a Python test runner like nose or py.test, or the 89 | individual test scripts can be run with python directly. 90 | 91 | ### Testbench Files 92 | 93 | tb/axis_ep.py : MyHDL AXI Stream endpoints 94 | tb/wb.py : MyHDL Wishbone master model and RAM model 95 | -------------------------------------------------------------------------------- /rtl/arbiter.v: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2014-2021 Alex Forencich 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | */ 24 | 25 | // Language: Verilog 2001 26 | 27 | `timescale 1ns / 1ps 28 | 29 | /* 30 | * Arbiter module 31 | */ 32 | module arbiter # 33 | ( 34 | parameter PORTS = 4, 35 | // select round robin arbitration 36 | parameter ARB_TYPE_ROUND_ROBIN = 0, 37 | // blocking arbiter enable 38 | parameter ARB_BLOCK = 0, 39 | // block on acknowledge assert when nonzero, request deassert when 0 40 | parameter ARB_BLOCK_ACK = 1, 41 | // LSB priority selection 42 | parameter ARB_LSB_HIGH_PRIORITY = 0 43 | ) 44 | ( 45 | input wire clk, 46 | input wire rst, 47 | 48 | input wire [PORTS-1:0] request, 49 | input wire [PORTS-1:0] acknowledge, 50 | 51 | output wire [PORTS-1:0] grant, 52 | output wire grant_valid, 53 | output wire [$clog2(PORTS)-1:0] grant_encoded 54 | ); 55 | 56 | reg [PORTS-1:0] grant_reg = 0, grant_next; 57 | reg grant_valid_reg = 0, grant_valid_next; 58 | reg [$clog2(PORTS)-1:0] grant_encoded_reg = 0, grant_encoded_next; 59 | 60 | assign grant_valid = grant_valid_reg; 61 | assign grant = grant_reg; 62 | assign grant_encoded = grant_encoded_reg; 63 | 64 | wire request_valid; 65 | wire [$clog2(PORTS)-1:0] request_index; 66 | wire [PORTS-1:0] request_mask; 67 | 68 | priority_encoder #( 69 | .WIDTH(PORTS), 70 | .LSB_HIGH_PRIORITY(ARB_LSB_HIGH_PRIORITY) 71 | ) 72 | priority_encoder_inst ( 73 | .input_unencoded(request), 74 | .output_valid(request_valid), 75 | .output_encoded(request_index), 76 | .output_unencoded(request_mask) 77 | ); 78 | 79 | reg [PORTS-1:0] mask_reg = 0, mask_next; 80 | 81 | wire masked_request_valid; 82 | wire [$clog2(PORTS)-1:0] masked_request_index; 83 | wire [PORTS-1:0] masked_request_mask; 84 | 85 | priority_encoder #( 86 | .WIDTH(PORTS), 87 | .LSB_HIGH_PRIORITY(ARB_LSB_HIGH_PRIORITY) 88 | ) 89 | priority_encoder_masked ( 90 | .input_unencoded(request & mask_reg), 91 | .output_valid(masked_request_valid), 92 | .output_encoded(masked_request_index), 93 | .output_unencoded(masked_request_mask) 94 | ); 95 | 96 | always @* begin 97 | grant_next = 0; 98 | grant_valid_next = 0; 99 | grant_encoded_next = 0; 100 | mask_next = mask_reg; 101 | 102 | if (ARB_BLOCK && !ARB_BLOCK_ACK && grant_reg & request) begin 103 | // granted request still asserted; hold it 104 | grant_valid_next = grant_valid_reg; 105 | grant_next = grant_reg; 106 | grant_encoded_next = grant_encoded_reg; 107 | end else if (ARB_BLOCK && ARB_BLOCK_ACK && grant_valid && !(grant_reg & acknowledge)) begin 108 | // granted request not yet acknowledged; hold it 109 | grant_valid_next = grant_valid_reg; 110 | grant_next = grant_reg; 111 | grant_encoded_next = grant_encoded_reg; 112 | end else if (request_valid) begin 113 | if (ARB_TYPE_ROUND_ROBIN) begin 114 | if (masked_request_valid) begin 115 | grant_valid_next = 1; 116 | grant_next = masked_request_mask; 117 | grant_encoded_next = masked_request_index; 118 | if (ARB_LSB_HIGH_PRIORITY) begin 119 | mask_next = {PORTS{1'b1}} << (masked_request_index + 1); 120 | end else begin 121 | mask_next = {PORTS{1'b1}} >> (PORTS - masked_request_index); 122 | end 123 | end else begin 124 | grant_valid_next = 1; 125 | grant_next = request_mask; 126 | grant_encoded_next = request_index; 127 | if (ARB_LSB_HIGH_PRIORITY) begin 128 | mask_next = {PORTS{1'b1}} << (request_index + 1); 129 | end else begin 130 | mask_next = {PORTS{1'b1}} >> (PORTS - request_index); 131 | end 132 | end 133 | end else begin 134 | grant_valid_next = 1; 135 | grant_next = request_mask; 136 | grant_encoded_next = request_index; 137 | end 138 | end 139 | end 140 | 141 | always @(posedge clk) begin 142 | if (rst) begin 143 | grant_reg <= 0; 144 | grant_valid_reg <= 0; 145 | grant_encoded_reg <= 0; 146 | mask_reg <= 0; 147 | end else begin 148 | grant_reg <= grant_next; 149 | grant_valid_reg <= grant_valid_next; 150 | grant_encoded_reg <= grant_encoded_next; 151 | mask_reg <= mask_next; 152 | end 153 | end 154 | 155 | endmodule 156 | -------------------------------------------------------------------------------- /rtl/priority_encoder.v: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2014-2021 Alex Forencich 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | */ 24 | 25 | // Language: Verilog 2001 26 | 27 | `timescale 1ns / 1ps 28 | 29 | /* 30 | * Priority encoder module 31 | */ 32 | module priority_encoder # 33 | ( 34 | parameter WIDTH = 4, 35 | // LSB priority selection 36 | parameter LSB_HIGH_PRIORITY = 0 37 | ) 38 | ( 39 | input wire [WIDTH-1:0] input_unencoded, 40 | output wire output_valid, 41 | output wire [$clog2(WIDTH)-1:0] output_encoded, 42 | output wire [WIDTH-1:0] output_unencoded 43 | ); 44 | 45 | parameter LEVELS = WIDTH > 2 ? $clog2(WIDTH) : 1; 46 | parameter W = 2**LEVELS; 47 | 48 | // pad input to even power of two 49 | wire [W-1:0] input_padded = {{W-WIDTH{1'b0}}, input_unencoded}; 50 | 51 | wire [W/2-1:0] stage_valid[LEVELS-1:0]; 52 | wire [W/2-1:0] stage_enc[LEVELS-1:0]; 53 | 54 | generate 55 | genvar l, n; 56 | 57 | // process input bits; generate valid bit and encoded bit for each pair 58 | for (n = 0; n < W/2; n = n + 1) begin : loop_in 59 | assign stage_valid[0][n] = |input_padded[n*2+1:n*2]; 60 | if (LSB_HIGH_PRIORITY) begin 61 | // bit 0 is highest priority 62 | assign stage_enc[0][n] = !input_padded[n*2+0]; 63 | end else begin 64 | // bit 0 is lowest priority 65 | assign stage_enc[0][n] = input_padded[n*2+1]; 66 | end 67 | end 68 | 69 | // compress down to single valid bit and encoded bus 70 | for (l = 1; l < LEVELS; l = l + 1) begin : loop_levels 71 | for (n = 0; n < W/(2*2**l); n = n + 1) begin : loop_compress 72 | assign stage_valid[l][n] = |stage_valid[l-1][n*2+1:n*2]; 73 | if (LSB_HIGH_PRIORITY) begin 74 | // bit 0 is highest priority 75 | assign stage_enc[l][(n+1)*(l+1)-1:n*(l+1)] = stage_valid[l-1][n*2+0] ? {1'b0, stage_enc[l-1][(n*2+1)*l-1:(n*2+0)*l]} : {1'b1, stage_enc[l-1][(n*2+2)*l-1:(n*2+1)*l]}; 76 | end else begin 77 | // bit 0 is lowest priority 78 | assign stage_enc[l][(n+1)*(l+1)-1:n*(l+1)] = stage_valid[l-1][n*2+1] ? {1'b1, stage_enc[l-1][(n*2+2)*l-1:(n*2+1)*l]} : {1'b0, stage_enc[l-1][(n*2+1)*l-1:(n*2+0)*l]}; 79 | end 80 | end 81 | end 82 | endgenerate 83 | 84 | assign output_valid = stage_valid[LEVELS-1]; 85 | assign output_encoded = stage_enc[LEVELS-1]; 86 | assign output_unencoded = 1 << output_encoded; 87 | 88 | endmodule 89 | -------------------------------------------------------------------------------- /rtl/wb_arbiter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | Generates a Wishbone arbiter with the specified number of ports 4 | """ 5 | 6 | from __future__ import print_function 7 | 8 | import argparse 9 | import math 10 | from jinja2 import Template 11 | 12 | def main(): 13 | parser = argparse.ArgumentParser(description=__doc__.strip()) 14 | parser.add_argument('-p', '--ports', type=int, default=2, help="number of ports") 15 | parser.add_argument('-n', '--name', type=str, help="module name") 16 | parser.add_argument('-o', '--output', type=str, help="output file name") 17 | 18 | args = parser.parse_args() 19 | 20 | try: 21 | generate(**args.__dict__) 22 | except IOError as ex: 23 | print(ex) 24 | exit(1) 25 | 26 | def generate(ports=2, name=None, output=None): 27 | if name is None: 28 | name = "wb_arbiter_{0}".format(ports) 29 | 30 | if output is None: 31 | output = name + ".v" 32 | 33 | print("Opening file '{0}'...".format(output)) 34 | 35 | output_file = open(output, 'w') 36 | 37 | print("Generating {0} port Wishbone arbiter {1}...".format(ports, name)) 38 | 39 | select_width = int(math.ceil(math.log(ports, 2))) 40 | 41 | t = Template(u"""/* 42 | 43 | Copyright (c) 2015-2016 Alex Forencich 44 | 45 | Permission is hereby granted, free of charge, to any person obtaining a copy 46 | of this software and associated documentation files (the "Software"), to deal 47 | in the Software without restriction, including without limitation the rights 48 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 49 | copies of the Software, and to permit persons to whom the Software is 50 | furnished to do so, subject to the following conditions: 51 | 52 | The above copyright notice and this permission notice shall be included in 53 | all copies or substantial portions of the Software. 54 | 55 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 56 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 57 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 58 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 59 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 60 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 61 | THE SOFTWARE. 62 | 63 | */ 64 | 65 | // Language: Verilog 2001 66 | 67 | `timescale 1 ns / 1 ps 68 | 69 | /* 70 | * Wishbone {{n}} port arbiter 71 | */ 72 | module {{name}} # 73 | ( 74 | parameter DATA_WIDTH = 32, // width of data bus in bits (8, 16, 32, or 64) 75 | parameter ADDR_WIDTH = 32, // width of address bus in bits 76 | parameter SELECT_WIDTH = (DATA_WIDTH/8), // width of word select bus (1, 2, 4, or 8) 77 | parameter ARB_TYPE_ROUND_ROBIN = 0, // select round robin arbitration 78 | parameter ARB_LSB_HIGH_PRIORITY = 1 // LSB priority selection 79 | ) 80 | ( 81 | input wire clk, 82 | input wire rst, 83 | {%- for p in ports %} 84 | 85 | /* 86 | * Wishbone master {{p}} input 87 | */ 88 | input wire [ADDR_WIDTH-1:0] wbm{{p}}_adr_i, // ADR_I() address input 89 | input wire [DATA_WIDTH-1:0] wbm{{p}}_dat_i, // DAT_I() data in 90 | output wire [DATA_WIDTH-1:0] wbm{{p}}_dat_o, // DAT_O() data out 91 | input wire wbm{{p}}_we_i, // WE_I write enable input 92 | input wire [SELECT_WIDTH-1:0] wbm{{p}}_sel_i, // SEL_I() select input 93 | input wire wbm{{p}}_stb_i, // STB_I strobe input 94 | output wire wbm{{p}}_ack_o, // ACK_O acknowledge output 95 | output wire wbm{{p}}_err_o, // ERR_O error output 96 | output wire wbm{{p}}_rty_o, // RTY_O retry output 97 | input wire wbm{{p}}_cyc_i, // CYC_I cycle input 98 | {%- endfor %} 99 | 100 | /* 101 | * Wishbone slave output 102 | */ 103 | output wire [ADDR_WIDTH-1:0] wbs_adr_o, // ADR_O() address output 104 | input wire [DATA_WIDTH-1:0] wbs_dat_i, // DAT_I() data in 105 | output wire [DATA_WIDTH-1:0] wbs_dat_o, // DAT_O() data out 106 | output wire wbs_we_o, // WE_O write enable output 107 | output wire [SELECT_WIDTH-1:0] wbs_sel_o, // SEL_O() select output 108 | output wire wbs_stb_o, // STB_O strobe output 109 | input wire wbs_ack_i, // ACK_I acknowledge input 110 | input wire wbs_err_i, // ERR_I error input 111 | input wire wbs_rty_i, // RTY_I retry input 112 | output wire wbs_cyc_o // CYC_O cycle output 113 | ); 114 | 115 | wire [{{n-1}}:0] request; 116 | wire [{{n-1}}:0] grant; 117 | {% for p in ports %} 118 | assign request[{{p}}] = wbm{{p}}_cyc_i; 119 | {%- endfor %} 120 | {% for p in ports %} 121 | wire wbm{{p}}_sel = grant[{{p}}] & grant_valid; 122 | {%- endfor %} 123 | {%- for p in ports %} 124 | 125 | // master {{p}} 126 | assign wbm{{p}}_dat_o = wbs_dat_i; 127 | assign wbm{{p}}_ack_o = wbs_ack_i & wbm{{p}}_sel; 128 | assign wbm{{p}}_err_o = wbs_err_i & wbm{{p}}_sel; 129 | assign wbm{{p}}_rty_o = wbs_rty_i & wbm{{p}}_sel; 130 | {%- endfor %} 131 | 132 | // slave 133 | assign wbs_adr_o = {% for p in ports %}wbm{{p}}_sel ? wbm{{p}}_adr_i : 134 | {% endfor %}{ADDR_WIDTH{1'b0}}; 135 | 136 | assign wbs_dat_o = {% for p in ports %}wbm{{p}}_sel ? wbm{{p}}_dat_i : 137 | {% endfor %}{DATA_WIDTH{1'b0}}; 138 | 139 | assign wbs_we_o = {% for p in ports %}wbm{{p}}_sel ? wbm{{p}}_we_i : 140 | {% endfor %}1'b0; 141 | 142 | assign wbs_sel_o = {% for p in ports %}wbm{{p}}_sel ? wbm{{p}}_sel_i : 143 | {% endfor %}{SELECT_WIDTH{1'b0}}; 144 | 145 | assign wbs_stb_o = {% for p in ports %}wbm{{p}}_sel ? wbm{{p}}_stb_i : 146 | {% endfor %}1'b0; 147 | 148 | assign wbs_cyc_o = {% for p in ports %}wbm{{p}}_sel ? 1'b1 : 149 | {% endfor %}1'b0; 150 | 151 | // arbiter instance 152 | arbiter #( 153 | .PORTS({{n}}), 154 | .ARB_TYPE_ROUND_ROBIN(ARB_TYPE_ROUND_ROBIN), 155 | .ARB_BLOCK(1), 156 | .ARB_BLOCK_ACK(0), 157 | .ARB_LSB_HIGH_PRIORITY(ARB_LSB_HIGH_PRIORITY) 158 | ) 159 | arb_inst ( 160 | .clk(clk), 161 | .rst(rst), 162 | .request(request), 163 | .acknowledge(), 164 | .grant(grant), 165 | .grant_valid(grant_valid), 166 | .grant_encoded() 167 | ); 168 | 169 | endmodule 170 | 171 | """) 172 | 173 | output_file.write(t.render( 174 | n=ports, 175 | w=select_width, 176 | name=name, 177 | ports=range(ports) 178 | )) 179 | 180 | print("Done") 181 | 182 | if __name__ == "__main__": 183 | main() 184 | 185 | -------------------------------------------------------------------------------- /rtl/wb_arbiter_2.v: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2015-2016 Alex Forencich 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | */ 24 | 25 | // Language: Verilog 2001 26 | 27 | `timescale 1 ns / 1 ps 28 | 29 | /* 30 | * Wishbone 2 port arbiter 31 | */ 32 | module wb_arbiter_2 # 33 | ( 34 | parameter DATA_WIDTH = 32, // width of data bus in bits (8, 16, 32, or 64) 35 | parameter ADDR_WIDTH = 32, // width of address bus in bits 36 | parameter SELECT_WIDTH = (DATA_WIDTH/8), // width of word select bus (1, 2, 4, or 8) 37 | parameter ARB_TYPE_ROUND_ROBIN = 0, // select round robin arbitration 38 | parameter ARB_LSB_HIGH_PRIORITY = 1 // LSB priority selection 39 | ) 40 | ( 41 | input wire clk, 42 | input wire rst, 43 | 44 | /* 45 | * Wishbone master 0 input 46 | */ 47 | input wire [ADDR_WIDTH-1:0] wbm0_adr_i, // ADR_I() address input 48 | input wire [DATA_WIDTH-1:0] wbm0_dat_i, // DAT_I() data in 49 | output wire [DATA_WIDTH-1:0] wbm0_dat_o, // DAT_O() data out 50 | input wire wbm0_we_i, // WE_I write enable input 51 | input wire [SELECT_WIDTH-1:0] wbm0_sel_i, // SEL_I() select input 52 | input wire wbm0_stb_i, // STB_I strobe input 53 | output wire wbm0_ack_o, // ACK_O acknowledge output 54 | output wire wbm0_err_o, // ERR_O error output 55 | output wire wbm0_rty_o, // RTY_O retry output 56 | input wire wbm0_cyc_i, // CYC_I cycle input 57 | 58 | /* 59 | * Wishbone master 1 input 60 | */ 61 | input wire [ADDR_WIDTH-1:0] wbm1_adr_i, // ADR_I() address input 62 | input wire [DATA_WIDTH-1:0] wbm1_dat_i, // DAT_I() data in 63 | output wire [DATA_WIDTH-1:0] wbm1_dat_o, // DAT_O() data out 64 | input wire wbm1_we_i, // WE_I write enable input 65 | input wire [SELECT_WIDTH-1:0] wbm1_sel_i, // SEL_I() select input 66 | input wire wbm1_stb_i, // STB_I strobe input 67 | output wire wbm1_ack_o, // ACK_O acknowledge output 68 | output wire wbm1_err_o, // ERR_O error output 69 | output wire wbm1_rty_o, // RTY_O retry output 70 | input wire wbm1_cyc_i, // CYC_I cycle input 71 | 72 | /* 73 | * Wishbone slave output 74 | */ 75 | output wire [ADDR_WIDTH-1:0] wbs_adr_o, // ADR_O() address output 76 | input wire [DATA_WIDTH-1:0] wbs_dat_i, // DAT_I() data in 77 | output wire [DATA_WIDTH-1:0] wbs_dat_o, // DAT_O() data out 78 | output wire wbs_we_o, // WE_O write enable output 79 | output wire [SELECT_WIDTH-1:0] wbs_sel_o, // SEL_O() select output 80 | output wire wbs_stb_o, // STB_O strobe output 81 | input wire wbs_ack_i, // ACK_I acknowledge input 82 | input wire wbs_err_i, // ERR_I error input 83 | input wire wbs_rty_i, // RTY_I retry input 84 | output wire wbs_cyc_o // CYC_O cycle output 85 | ); 86 | 87 | wire [1:0] request; 88 | wire [1:0] grant; 89 | 90 | assign request[0] = wbm0_cyc_i; 91 | assign request[1] = wbm1_cyc_i; 92 | 93 | wire wbm0_sel = grant[0] & grant_valid; 94 | wire wbm1_sel = grant[1] & grant_valid; 95 | 96 | // master 0 97 | assign wbm0_dat_o = wbs_dat_i; 98 | assign wbm0_ack_o = wbs_ack_i & wbm0_sel; 99 | assign wbm0_err_o = wbs_err_i & wbm0_sel; 100 | assign wbm0_rty_o = wbs_rty_i & wbm0_sel; 101 | 102 | // master 1 103 | assign wbm1_dat_o = wbs_dat_i; 104 | assign wbm1_ack_o = wbs_ack_i & wbm1_sel; 105 | assign wbm1_err_o = wbs_err_i & wbm1_sel; 106 | assign wbm1_rty_o = wbs_rty_i & wbm1_sel; 107 | 108 | // slave 109 | assign wbs_adr_o = wbm0_sel ? wbm0_adr_i : 110 | wbm1_sel ? wbm1_adr_i : 111 | {ADDR_WIDTH{1'b0}}; 112 | 113 | assign wbs_dat_o = wbm0_sel ? wbm0_dat_i : 114 | wbm1_sel ? wbm1_dat_i : 115 | {DATA_WIDTH{1'b0}}; 116 | 117 | assign wbs_we_o = wbm0_sel ? wbm0_we_i : 118 | wbm1_sel ? wbm1_we_i : 119 | 1'b0; 120 | 121 | assign wbs_sel_o = wbm0_sel ? wbm0_sel_i : 122 | wbm1_sel ? wbm1_sel_i : 123 | {SELECT_WIDTH{1'b0}}; 124 | 125 | assign wbs_stb_o = wbm0_sel ? wbm0_stb_i : 126 | wbm1_sel ? wbm1_stb_i : 127 | 1'b0; 128 | 129 | assign wbs_cyc_o = wbm0_sel ? 1'b1 : 130 | wbm1_sel ? 1'b1 : 131 | 1'b0; 132 | 133 | // arbiter instance 134 | arbiter #( 135 | .PORTS(2), 136 | .ARB_TYPE_ROUND_ROBIN(ARB_TYPE_ROUND_ROBIN), 137 | .ARB_BLOCK(1), 138 | .ARB_BLOCK_ACK(0), 139 | .ARB_LSB_HIGH_PRIORITY(ARB_LSB_HIGH_PRIORITY) 140 | ) 141 | arb_inst ( 142 | .clk(clk), 143 | .rst(rst), 144 | .request(request), 145 | .acknowledge(), 146 | .grant(grant), 147 | .grant_valid(grant_valid), 148 | .grant_encoded() 149 | ); 150 | 151 | endmodule 152 | -------------------------------------------------------------------------------- /rtl/wb_async_reg.v: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2015-2016 Alex Forencich 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | */ 24 | 25 | // Language: Verilog 2001 26 | 27 | `timescale 1ns / 1ps 28 | 29 | /* 30 | * Wishbone register 31 | */ 32 | module wb_async_reg # 33 | ( 34 | parameter DATA_WIDTH = 32, // width of data bus in bits (8, 16, 32, or 64) 35 | parameter ADDR_WIDTH = 32, // width of address bus in bits 36 | parameter SELECT_WIDTH = (DATA_WIDTH/8) // width of word select bus (1, 2, 4, or 8) 37 | ) 38 | ( 39 | // master side 40 | input wire wbm_clk, 41 | input wire wbm_rst, 42 | input wire [ADDR_WIDTH-1:0] wbm_adr_i, // ADR_I() address 43 | input wire [DATA_WIDTH-1:0] wbm_dat_i, // DAT_I() data in 44 | output wire [DATA_WIDTH-1:0] wbm_dat_o, // DAT_O() data out 45 | input wire wbm_we_i, // WE_I write enable input 46 | input wire [SELECT_WIDTH-1:0] wbm_sel_i, // SEL_I() select input 47 | input wire wbm_stb_i, // STB_I strobe input 48 | output wire wbm_ack_o, // ACK_O acknowledge output 49 | output wire wbm_err_o, // ERR_O error output 50 | output wire wbm_rty_o, // RTY_O retry output 51 | input wire wbm_cyc_i, // CYC_I cycle input 52 | 53 | // slave side 54 | input wire wbs_clk, 55 | input wire wbs_rst, 56 | output wire [ADDR_WIDTH-1:0] wbs_adr_o, // ADR_O() address 57 | input wire [DATA_WIDTH-1:0] wbs_dat_i, // DAT_I() data in 58 | output wire [DATA_WIDTH-1:0] wbs_dat_o, // DAT_O() data out 59 | output wire wbs_we_o, // WE_O write enable output 60 | output wire [SELECT_WIDTH-1:0] wbs_sel_o, // SEL_O() select output 61 | output wire wbs_stb_o, // STB_O strobe output 62 | input wire wbs_ack_i, // ACK_I acknowledge input 63 | input wire wbs_err_i, // ERR_I error input 64 | input wire wbs_rty_i, // RTY_I retry input 65 | output wire wbs_cyc_o // CYC_O cycle output 66 | ); 67 | 68 | reg [ADDR_WIDTH-1:0] wbm_adr_i_reg = 0; 69 | reg [DATA_WIDTH-1:0] wbm_dat_i_reg = 0; 70 | reg [DATA_WIDTH-1:0] wbm_dat_o_reg = 0; 71 | reg wbm_we_i_reg = 0; 72 | reg [SELECT_WIDTH-1:0] wbm_sel_i_reg = 0; 73 | reg wbm_stb_i_reg = 0; 74 | reg wbm_ack_o_reg = 0; 75 | reg wbm_err_o_reg = 0; 76 | reg wbm_rty_o_reg = 0; 77 | reg wbm_cyc_i_reg = 0; 78 | 79 | reg wbm_done_sync1 = 0; 80 | reg wbm_done_sync2 = 0; 81 | reg wbm_done_sync3 = 0; 82 | 83 | reg [ADDR_WIDTH-1:0] wbs_adr_o_reg = 0; 84 | reg [DATA_WIDTH-1:0] wbs_dat_i_reg = 0; 85 | reg [DATA_WIDTH-1:0] wbs_dat_o_reg = 0; 86 | reg wbs_we_o_reg = 0; 87 | reg [SELECT_WIDTH-1:0] wbs_sel_o_reg = 0; 88 | reg wbs_stb_o_reg = 0; 89 | reg wbs_ack_i_reg = 0; 90 | reg wbs_err_i_reg = 0; 91 | reg wbs_rty_i_reg = 0; 92 | reg wbs_cyc_o_reg = 0; 93 | 94 | reg wbs_cyc_o_sync1 = 0; 95 | reg wbs_cyc_o_sync2 = 0; 96 | reg wbs_cyc_o_sync3 = 0; 97 | 98 | reg wbs_stb_o_sync1 = 0; 99 | reg wbs_stb_o_sync2 = 0; 100 | reg wbs_stb_o_sync3 = 0; 101 | 102 | reg wbs_done_reg = 0; 103 | 104 | assign wbm_dat_o = wbm_dat_o_reg; 105 | assign wbm_ack_o = wbm_ack_o_reg; 106 | assign wbm_err_o = wbm_err_o_reg; 107 | assign wbm_rty_o = wbm_rty_o_reg; 108 | 109 | assign wbs_adr_o = wbs_adr_o_reg; 110 | assign wbs_dat_o = wbs_dat_o_reg; 111 | assign wbs_we_o = wbs_we_o_reg; 112 | assign wbs_sel_o = wbs_sel_o_reg; 113 | assign wbs_stb_o = wbs_stb_o_reg; 114 | assign wbs_cyc_o = wbs_cyc_o_reg; 115 | 116 | // master side logic 117 | always @(posedge wbm_clk) begin 118 | if (wbm_rst) begin 119 | wbm_adr_i_reg <= 0; 120 | wbm_dat_i_reg <= 0; 121 | wbm_dat_o_reg <= 0; 122 | wbm_we_i_reg <= 0; 123 | wbm_sel_i_reg <= 0; 124 | wbm_stb_i_reg <= 0; 125 | wbm_ack_o_reg <= 0; 126 | wbm_err_o_reg <= 0; 127 | wbm_rty_o_reg <= 0; 128 | wbm_cyc_i_reg <= 0; 129 | end else begin 130 | if (wbm_cyc_i_reg & wbm_stb_i_reg) begin 131 | // cycle - hold master 132 | if (wbm_done_sync2 & ~wbm_done_sync3) begin 133 | // end of cycle - store slave 134 | wbm_dat_o_reg <= wbs_dat_i_reg; 135 | wbm_ack_o_reg <= wbs_ack_i_reg; 136 | wbm_err_o_reg <= wbs_err_i_reg; 137 | wbm_rty_o_reg <= wbs_rty_i_reg; 138 | wbm_we_i_reg <= 0; 139 | wbm_stb_i_reg <= 0; 140 | end 141 | end else begin 142 | // idle - store master 143 | wbm_adr_i_reg <= wbm_adr_i; 144 | wbm_dat_i_reg <= wbm_dat_i; 145 | wbm_dat_o_reg <= 0; 146 | wbm_we_i_reg <= wbm_we_i & ~(wbm_ack_o | wbm_err_o | wbm_rty_o); 147 | wbm_sel_i_reg <= wbm_sel_i; 148 | wbm_stb_i_reg <= wbm_stb_i & ~(wbm_ack_o | wbm_err_o | wbm_rty_o); 149 | wbm_ack_o_reg <= 0; 150 | wbm_err_o_reg <= 0; 151 | wbm_rty_o_reg <= 0; 152 | wbm_cyc_i_reg <= wbm_cyc_i; 153 | end 154 | end 155 | 156 | // synchronize signals 157 | wbm_done_sync1 <= wbs_done_reg; 158 | wbm_done_sync2 <= wbm_done_sync1; 159 | wbm_done_sync3 <= wbm_done_sync2; 160 | end 161 | 162 | // slave side logic 163 | always @(posedge wbs_clk) begin 164 | if (wbs_rst) begin 165 | wbs_adr_o_reg <= 0; 166 | wbs_dat_i_reg <= 0; 167 | wbs_dat_o_reg <= 0; 168 | wbs_we_o_reg <= 0; 169 | wbs_sel_o_reg <= 0; 170 | wbs_stb_o_reg <= 0; 171 | wbs_ack_i_reg <= 0; 172 | wbs_err_i_reg <= 0; 173 | wbs_rty_i_reg <= 0; 174 | wbs_cyc_o_reg <= 0; 175 | wbs_done_reg <= 0; 176 | end else begin 177 | if (wbs_ack_i | wbs_err_i | wbs_rty_i) begin 178 | // end of cycle - store slave 179 | wbs_dat_i_reg <= wbs_dat_i; 180 | wbs_ack_i_reg <= wbs_ack_i; 181 | wbs_err_i_reg <= wbs_err_i; 182 | wbs_rty_i_reg <= wbs_rty_i; 183 | wbs_we_o_reg <= 0; 184 | wbs_stb_o_reg <= 0; 185 | wbs_done_reg <= 1; 186 | end else if (wbs_stb_o_sync2 & ~wbs_stb_o_sync3) begin 187 | // beginning of cycle - store master 188 | wbs_adr_o_reg <= wbm_adr_i_reg; 189 | wbs_dat_i_reg <= 0; 190 | wbs_dat_o_reg <= wbm_dat_i_reg; 191 | wbs_we_o_reg <= wbm_we_i_reg; 192 | wbs_sel_o_reg <= wbm_sel_i_reg; 193 | wbs_stb_o_reg <= wbm_stb_i_reg; 194 | wbs_ack_i_reg <= 0; 195 | wbs_err_i_reg <= 0; 196 | wbs_rty_i_reg <= 0; 197 | wbs_cyc_o_reg <= wbm_cyc_i_reg; 198 | wbs_done_reg <= 0; 199 | end else if (~wbs_cyc_o_sync2 & wbs_cyc_o_sync3) begin 200 | // cyc deassert 201 | wbs_adr_o_reg <= 0; 202 | wbs_dat_i_reg <= 0; 203 | wbs_dat_o_reg <= 0; 204 | wbs_we_o_reg <= 0; 205 | wbs_sel_o_reg <= 0; 206 | wbs_stb_o_reg <= 0; 207 | wbs_ack_i_reg <= 0; 208 | wbs_err_i_reg <= 0; 209 | wbs_rty_i_reg <= 0; 210 | wbs_cyc_o_reg <= 0; 211 | wbs_done_reg <= 0; 212 | end 213 | end 214 | 215 | // synchronize signals 216 | wbs_cyc_o_sync1 <= wbm_cyc_i_reg; 217 | wbs_cyc_o_sync2 <= wbs_cyc_o_sync1; 218 | wbs_cyc_o_sync3 <= wbs_cyc_o_sync2; 219 | 220 | wbs_stb_o_sync1 <= wbm_stb_i_reg; 221 | wbs_stb_o_sync2 <= wbs_stb_o_sync1; 222 | wbs_stb_o_sync3 <= wbs_stb_o_sync2; 223 | end 224 | 225 | endmodule 226 | -------------------------------------------------------------------------------- /rtl/wb_dp_ram.v: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2015-2016 Alex Forencich 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | */ 24 | 25 | // Language: Verilog 2001 26 | 27 | `timescale 1ns / 1ps 28 | 29 | /* 30 | * Wishbone dual port RAM 31 | */ 32 | module wb_dp_ram # 33 | ( 34 | parameter DATA_WIDTH = 32, // width of data bus in bits (8, 16, 32, or 64) 35 | parameter ADDR_WIDTH = 16, // width of address bus in bits 36 | parameter SELECT_WIDTH = (DATA_WIDTH/8) // width of word select bus (1, 2, 4, or 8) 37 | ) 38 | ( 39 | // port A 40 | input wire a_clk, 41 | input wire [ADDR_WIDTH-1:0] a_adr_i, // ADR_I() address 42 | input wire [DATA_WIDTH-1:0] a_dat_i, // DAT_I() data in 43 | output wire [DATA_WIDTH-1:0] a_dat_o, // DAT_O() data out 44 | input wire a_we_i, // WE_I write enable input 45 | input wire [SELECT_WIDTH-1:0] a_sel_i, // SEL_I() select input 46 | input wire a_stb_i, // STB_I strobe input 47 | output wire a_ack_o, // ACK_O acknowledge output 48 | input wire a_cyc_i, // CYC_I cycle input 49 | 50 | // port B 51 | input wire b_clk, 52 | input wire [ADDR_WIDTH-1:0] b_adr_i, // ADR_I() address 53 | input wire [DATA_WIDTH-1:0] b_dat_i, // DAT_I() data in 54 | output wire [DATA_WIDTH-1:0] b_dat_o, // DAT_O() data out 55 | input wire b_we_i, // WE_I write enable input 56 | input wire [SELECT_WIDTH-1:0] b_sel_i, // SEL_I() select input 57 | input wire b_stb_i, // STB_I strobe input 58 | output wire b_ack_o, // ACK_O acknowledge output 59 | input wire b_cyc_i // CYC_I cycle input 60 | ); 61 | 62 | // for interfaces that are more than one word wide, disable address lines 63 | parameter VALID_ADDR_WIDTH = ADDR_WIDTH - $clog2(SELECT_WIDTH); 64 | // width of data port in words (1, 2, 4, or 8) 65 | parameter WORD_WIDTH = SELECT_WIDTH; 66 | // size of words (8, 16, 32, or 64 bits) 67 | parameter WORD_SIZE = DATA_WIDTH/WORD_WIDTH; 68 | 69 | reg [DATA_WIDTH-1:0] a_dat_o_reg = {DATA_WIDTH{1'b0}}; 70 | reg a_ack_o_reg = 1'b0; 71 | 72 | reg [DATA_WIDTH-1:0] b_dat_o_reg = {DATA_WIDTH{1'b0}}; 73 | reg b_ack_o_reg = 1'b0; 74 | 75 | // (* RAM_STYLE="BLOCK" *) 76 | reg [DATA_WIDTH-1:0] mem[(2**VALID_ADDR_WIDTH)-1:0]; 77 | 78 | wire [VALID_ADDR_WIDTH-1:0] a_adr_i_valid = a_adr_i >> (ADDR_WIDTH - VALID_ADDR_WIDTH); 79 | wire [VALID_ADDR_WIDTH-1:0] b_adr_i_valid = b_adr_i >> (ADDR_WIDTH - VALID_ADDR_WIDTH); 80 | 81 | assign a_dat_o = a_dat_o_reg; 82 | assign a_ack_o = a_ack_o_reg; 83 | 84 | assign b_dat_o = b_dat_o_reg; 85 | assign b_ack_o = b_ack_o_reg; 86 | 87 | integer i, j; 88 | 89 | initial begin 90 | // two nested loops for smaller number of iterations per loop 91 | // workaround for synthesizer complaints about large loop counts 92 | for (i = 0; i < 2**ADDR_WIDTH; i = i + 2**(ADDR_WIDTH/2)) begin 93 | for (j = i; j < i + 2**(ADDR_WIDTH/2); j = j + 1) begin 94 | mem[j] = 0; 95 | end 96 | end 97 | end 98 | 99 | // port A 100 | always @(posedge a_clk) begin 101 | a_ack_o_reg <= 1'b0; 102 | for (i = 0; i < WORD_WIDTH; i = i + 1) begin 103 | if (a_cyc_i & a_stb_i & ~a_ack_o) begin 104 | if (a_we_i & a_sel_i[i]) begin 105 | mem[a_adr_i_valid][WORD_SIZE*i +: WORD_SIZE] <= a_dat_i[WORD_SIZE*i +: WORD_SIZE]; 106 | end 107 | a_dat_o_reg[WORD_SIZE*i +: WORD_SIZE] <= mem[a_adr_i_valid][WORD_SIZE*i +: WORD_SIZE]; 108 | a_ack_o_reg <= 1'b1; 109 | end 110 | end 111 | end 112 | 113 | // port B 114 | always @(posedge b_clk) begin 115 | b_ack_o_reg <= 1'b0; 116 | for (i = 0; i < WORD_WIDTH; i = i + 1) begin 117 | if (b_cyc_i & b_stb_i & ~b_ack_o) begin 118 | if (b_we_i & b_sel_i[i]) begin 119 | mem[b_adr_i_valid][WORD_SIZE*i +: WORD_SIZE] <= b_dat_i[WORD_SIZE*i +: WORD_SIZE]; 120 | end 121 | b_dat_o_reg[WORD_SIZE*i +: WORD_SIZE] <= mem[b_adr_i_valid][WORD_SIZE*i +: WORD_SIZE]; 122 | b_ack_o_reg <= 1'b1; 123 | end 124 | end 125 | end 126 | 127 | endmodule 128 | -------------------------------------------------------------------------------- /rtl/wb_mux.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | Generates a Wishbone multiplexer with the specified number of ports 4 | """ 5 | 6 | from __future__ import print_function 7 | 8 | import argparse 9 | import math 10 | from jinja2 import Template 11 | 12 | def main(): 13 | parser = argparse.ArgumentParser(description=__doc__.strip()) 14 | parser.add_argument('-p', '--ports', type=int, default=2, help="number of ports") 15 | parser.add_argument('-n', '--name', type=str, help="module name") 16 | parser.add_argument('-o', '--output', type=str, help="output file name") 17 | 18 | args = parser.parse_args() 19 | 20 | try: 21 | generate(**args.__dict__) 22 | except IOError as ex: 23 | print(ex) 24 | exit(1) 25 | 26 | def generate(ports=2, name=None, output=None): 27 | if name is None: 28 | name = "wb_mux_{0}".format(ports) 29 | 30 | if output is None: 31 | output = name + ".v" 32 | 33 | print("Opening file '{0}'...".format(output)) 34 | 35 | output_file = open(output, 'w') 36 | 37 | print("Generating {0} port Wishbone mux {1}...".format(ports, name)) 38 | 39 | select_width = int(math.ceil(math.log(ports, 2))) 40 | 41 | t = Template(u"""/* 42 | 43 | Copyright (c) 2015-2016 Alex Forencich 44 | 45 | Permission is hereby granted, free of charge, to any person obtaining a copy 46 | of this software and associated documentation files (the "Software"), to deal 47 | in the Software without restriction, including without limitation the rights 48 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 49 | copies of the Software, and to permit persons to whom the Software is 50 | furnished to do so, subject to the following conditions: 51 | 52 | The above copyright notice and this permission notice shall be included in 53 | all copies or substantial portions of the Software. 54 | 55 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 56 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 57 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 58 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 59 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 60 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 61 | THE SOFTWARE. 62 | 63 | */ 64 | 65 | // Language: Verilog 2001 66 | 67 | `timescale 1 ns / 1 ps 68 | 69 | /* 70 | * Wishbone {{n}} port multiplexer 71 | */ 72 | module {{name}} # 73 | ( 74 | parameter DATA_WIDTH = 32, // width of data bus in bits (8, 16, 32, or 64) 75 | parameter ADDR_WIDTH = 32, // width of address bus in bits 76 | parameter SELECT_WIDTH = (DATA_WIDTH/8) // width of word select bus (1, 2, 4, or 8) 77 | ) 78 | ( 79 | input wire clk, 80 | input wire rst, 81 | 82 | /* 83 | * Wishbone master input 84 | */ 85 | input wire [ADDR_WIDTH-1:0] wbm_adr_i, // ADR_I() address input 86 | input wire [DATA_WIDTH-1:0] wbm_dat_i, // DAT_I() data in 87 | output wire [DATA_WIDTH-1:0] wbm_dat_o, // DAT_O() data out 88 | input wire wbm_we_i, // WE_I write enable input 89 | input wire [SELECT_WIDTH-1:0] wbm_sel_i, // SEL_I() select input 90 | input wire wbm_stb_i, // STB_I strobe input 91 | output wire wbm_ack_o, // ACK_O acknowledge output 92 | output wire wbm_err_o, // ERR_O error output 93 | output wire wbm_rty_o, // RTY_O retry output 94 | input wire wbm_cyc_i, // CYC_I cycle input 95 | {%- for p in ports %} 96 | 97 | /* 98 | * Wishbone slave {{p}} output 99 | */ 100 | output wire [ADDR_WIDTH-1:0] wbs{{p}}_adr_o, // ADR_O() address output 101 | input wire [DATA_WIDTH-1:0] wbs{{p}}_dat_i, // DAT_I() data in 102 | output wire [DATA_WIDTH-1:0] wbs{{p}}_dat_o, // DAT_O() data out 103 | output wire wbs{{p}}_we_o, // WE_O write enable output 104 | output wire [SELECT_WIDTH-1:0] wbs{{p}}_sel_o, // SEL_O() select output 105 | output wire wbs{{p}}_stb_o, // STB_O strobe output 106 | input wire wbs{{p}}_ack_i, // ACK_I acknowledge input 107 | input wire wbs{{p}}_err_i, // ERR_I error input 108 | input wire wbs{{p}}_rty_i, // RTY_I retry input 109 | output wire wbs{{p}}_cyc_o, // CYC_O cycle output 110 | 111 | /* 112 | * Wishbone slave {{p}} address configuration 113 | */ 114 | input wire [ADDR_WIDTH-1:0] wbs{{p}}_addr, // Slave address prefix 115 | input wire [ADDR_WIDTH-1:0] wbs{{p}}_addr_msk{% if not loop.last %},{% else %} {% endif %} // Slave address prefix mask 116 | {%- endfor %} 117 | ); 118 | {% for p in ports %} 119 | wire wbs{{p}}_match = ~|((wbm_adr_i ^ wbs{{p}}_addr) & wbs{{p}}_addr_msk); 120 | {%- endfor %} 121 | {% for p in ports %} 122 | wire wbs{{p}}_sel = wbs{{p}}_match{% if p > 0 %} & ~({% for q in range(p) %}wbs{{q}}_match{% if not loop.last %} | {% endif %}{% endfor %}){% endif %}; 123 | {%- endfor %} 124 | 125 | wire master_cycle = wbm_cyc_i & wbm_stb_i; 126 | 127 | wire select_error = ~({% for p in ports %}wbs{{p}}_sel{% if not loop.last %} | {% endif %}{% endfor %}) & master_cycle; 128 | 129 | // master 130 | assign wbm_dat_o = {% for p in ports %}wbs{{p}}_sel ? wbs{{p}}_dat_i : 131 | {% endfor %}{DATA_WIDTH{1'b0}}; 132 | 133 | assign wbm_ack_o = {% for p in ports %}wbs{{p}}_ack_i{% if not loop.last %} | 134 | {% endif %}{% endfor %}; 135 | 136 | assign wbm_err_o = {% for p in ports %}wbs{{p}}_err_i | 137 | {% endfor %}select_error; 138 | 139 | assign wbm_rty_o = {% for p in ports %}wbs{{p}}_rty_i{% if not loop.last %} | 140 | {% endif %}{% endfor %}; 141 | {% for p in ports %} 142 | // slave {{p}} 143 | assign wbs{{p}}_adr_o = wbm_adr_i; 144 | assign wbs{{p}}_dat_o = wbm_dat_i; 145 | assign wbs{{p}}_we_o = wbm_we_i & wbs{{p}}_sel; 146 | assign wbs{{p}}_sel_o = wbm_sel_i; 147 | assign wbs{{p}}_stb_o = wbm_stb_i & wbs{{p}}_sel; 148 | assign wbs{{p}}_cyc_o = wbm_cyc_i & wbs{{p}}_sel; 149 | {% endfor %} 150 | 151 | endmodule 152 | 153 | """) 154 | 155 | output_file.write(t.render( 156 | n=ports, 157 | w=select_width, 158 | name=name, 159 | ports=range(ports) 160 | )) 161 | 162 | print("Done") 163 | 164 | if __name__ == "__main__": 165 | main() 166 | 167 | -------------------------------------------------------------------------------- /rtl/wb_mux_2.v: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2015-2016 Alex Forencich 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | */ 24 | 25 | // Language: Verilog 2001 26 | 27 | `timescale 1 ns / 1 ps 28 | 29 | /* 30 | * Wishbone 2 port multiplexer 31 | */ 32 | module wb_mux_2 # 33 | ( 34 | parameter DATA_WIDTH = 32, // width of data bus in bits (8, 16, 32, or 64) 35 | parameter ADDR_WIDTH = 32, // width of address bus in bits 36 | parameter SELECT_WIDTH = (DATA_WIDTH/8) // width of word select bus (1, 2, 4, or 8) 37 | ) 38 | ( 39 | input wire clk, 40 | input wire rst, 41 | 42 | /* 43 | * Wishbone master input 44 | */ 45 | input wire [ADDR_WIDTH-1:0] wbm_adr_i, // ADR_I() address input 46 | input wire [DATA_WIDTH-1:0] wbm_dat_i, // DAT_I() data in 47 | output wire [DATA_WIDTH-1:0] wbm_dat_o, // DAT_O() data out 48 | input wire wbm_we_i, // WE_I write enable input 49 | input wire [SELECT_WIDTH-1:0] wbm_sel_i, // SEL_I() select input 50 | input wire wbm_stb_i, // STB_I strobe input 51 | output wire wbm_ack_o, // ACK_O acknowledge output 52 | output wire wbm_err_o, // ERR_O error output 53 | output wire wbm_rty_o, // RTY_O retry output 54 | input wire wbm_cyc_i, // CYC_I cycle input 55 | 56 | /* 57 | * Wishbone slave 0 output 58 | */ 59 | output wire [ADDR_WIDTH-1:0] wbs0_adr_o, // ADR_O() address output 60 | input wire [DATA_WIDTH-1:0] wbs0_dat_i, // DAT_I() data in 61 | output wire [DATA_WIDTH-1:0] wbs0_dat_o, // DAT_O() data out 62 | output wire wbs0_we_o, // WE_O write enable output 63 | output wire [SELECT_WIDTH-1:0] wbs0_sel_o, // SEL_O() select output 64 | output wire wbs0_stb_o, // STB_O strobe output 65 | input wire wbs0_ack_i, // ACK_I acknowledge input 66 | input wire wbs0_err_i, // ERR_I error input 67 | input wire wbs0_rty_i, // RTY_I retry input 68 | output wire wbs0_cyc_o, // CYC_O cycle output 69 | 70 | /* 71 | * Wishbone slave 0 address configuration 72 | */ 73 | input wire [ADDR_WIDTH-1:0] wbs0_addr, // Slave address prefix 74 | input wire [ADDR_WIDTH-1:0] wbs0_addr_msk, // Slave address prefix mask 75 | 76 | /* 77 | * Wishbone slave 1 output 78 | */ 79 | output wire [ADDR_WIDTH-1:0] wbs1_adr_o, // ADR_O() address output 80 | input wire [DATA_WIDTH-1:0] wbs1_dat_i, // DAT_I() data in 81 | output wire [DATA_WIDTH-1:0] wbs1_dat_o, // DAT_O() data out 82 | output wire wbs1_we_o, // WE_O write enable output 83 | output wire [SELECT_WIDTH-1:0] wbs1_sel_o, // SEL_O() select output 84 | output wire wbs1_stb_o, // STB_O strobe output 85 | input wire wbs1_ack_i, // ACK_I acknowledge input 86 | input wire wbs1_err_i, // ERR_I error input 87 | input wire wbs1_rty_i, // RTY_I retry input 88 | output wire wbs1_cyc_o, // CYC_O cycle output 89 | 90 | /* 91 | * Wishbone slave 1 address configuration 92 | */ 93 | input wire [ADDR_WIDTH-1:0] wbs1_addr, // Slave address prefix 94 | input wire [ADDR_WIDTH-1:0] wbs1_addr_msk // Slave address prefix mask 95 | ); 96 | 97 | wire wbs0_match = ~|((wbm_adr_i ^ wbs0_addr) & wbs0_addr_msk); 98 | wire wbs1_match = ~|((wbm_adr_i ^ wbs1_addr) & wbs1_addr_msk); 99 | 100 | wire wbs0_sel = wbs0_match; 101 | wire wbs1_sel = wbs1_match & ~(wbs0_match); 102 | 103 | wire master_cycle = wbm_cyc_i & wbm_stb_i; 104 | 105 | wire select_error = ~(wbs0_sel | wbs1_sel) & master_cycle; 106 | 107 | // master 108 | assign wbm_dat_o = wbs0_sel ? wbs0_dat_i : 109 | wbs1_sel ? wbs1_dat_i : 110 | {DATA_WIDTH{1'b0}}; 111 | 112 | assign wbm_ack_o = wbs0_ack_i | 113 | wbs1_ack_i; 114 | 115 | assign wbm_err_o = wbs0_err_i | 116 | wbs1_err_i | 117 | select_error; 118 | 119 | assign wbm_rty_o = wbs0_rty_i | 120 | wbs1_rty_i; 121 | 122 | // slave 0 123 | assign wbs0_adr_o = wbm_adr_i; 124 | assign wbs0_dat_o = wbm_dat_i; 125 | assign wbs0_we_o = wbm_we_i & wbs0_sel; 126 | assign wbs0_sel_o = wbm_sel_i; 127 | assign wbs0_stb_o = wbm_stb_i & wbs0_sel; 128 | assign wbs0_cyc_o = wbm_cyc_i & wbs0_sel; 129 | 130 | // slave 1 131 | assign wbs1_adr_o = wbm_adr_i; 132 | assign wbs1_dat_o = wbm_dat_i; 133 | assign wbs1_we_o = wbm_we_i & wbs1_sel; 134 | assign wbs1_sel_o = wbm_sel_i; 135 | assign wbs1_stb_o = wbm_stb_i & wbs1_sel; 136 | assign wbs1_cyc_o = wbm_cyc_i & wbs1_sel; 137 | 138 | 139 | endmodule 140 | -------------------------------------------------------------------------------- /rtl/wb_ram.v: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2015-2016 Alex Forencich 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | */ 24 | 25 | // Language: Verilog 2001 26 | 27 | `timescale 1ns / 1ps 28 | 29 | /* 30 | * Wishbone RAM 31 | */ 32 | module wb_ram # 33 | ( 34 | parameter DATA_WIDTH = 32, // width of data bus in bits (8, 16, 32, or 64) 35 | parameter ADDR_WIDTH = 16, // width of address bus in bits 36 | parameter SELECT_WIDTH = (DATA_WIDTH/8) // width of word select bus (1, 2, 4, or 8) 37 | ) 38 | ( 39 | input wire clk, 40 | 41 | input wire [ADDR_WIDTH-1:0] adr_i, // ADR_I() address 42 | input wire [DATA_WIDTH-1:0] dat_i, // DAT_I() data in 43 | output wire [DATA_WIDTH-1:0] dat_o, // DAT_O() data out 44 | input wire we_i, // WE_I write enable input 45 | input wire [SELECT_WIDTH-1:0] sel_i, // SEL_I() select input 46 | input wire stb_i, // STB_I strobe input 47 | output wire ack_o, // ACK_O acknowledge output 48 | input wire cyc_i // CYC_I cycle input 49 | ); 50 | 51 | // for interfaces that are more than one word wide, disable address lines 52 | parameter VALID_ADDR_WIDTH = ADDR_WIDTH - $clog2(SELECT_WIDTH); 53 | // width of data port in words (1, 2, 4, or 8) 54 | parameter WORD_WIDTH = SELECT_WIDTH; 55 | // size of words (8, 16, 32, or 64 bits) 56 | parameter WORD_SIZE = DATA_WIDTH/WORD_WIDTH; 57 | 58 | reg [DATA_WIDTH-1:0] dat_o_reg = {DATA_WIDTH{1'b0}}; 59 | reg ack_o_reg = 1'b0; 60 | 61 | // (* RAM_STYLE="BLOCK" *) 62 | reg [DATA_WIDTH-1:0] mem[(2**VALID_ADDR_WIDTH)-1:0]; 63 | 64 | wire [VALID_ADDR_WIDTH-1:0] adr_i_valid = adr_i >> (ADDR_WIDTH - VALID_ADDR_WIDTH); 65 | 66 | assign dat_o = dat_o_reg; 67 | assign ack_o = ack_o_reg; 68 | 69 | integer i, j; 70 | 71 | initial begin 72 | // two nested loops for smaller number of iterations per loop 73 | // workaround for synthesizer complaints about large loop counts 74 | for (i = 0; i < 2**VALID_ADDR_WIDTH; i = i + 2**(VALID_ADDR_WIDTH/2)) begin 75 | for (j = i; j < i + 2**(VALID_ADDR_WIDTH/2); j = j + 1) begin 76 | mem[j] = 0; 77 | end 78 | end 79 | end 80 | 81 | always @(posedge clk) begin 82 | ack_o_reg <= 1'b0; 83 | for (i = 0; i < WORD_WIDTH; i = i + 1) begin 84 | if (cyc_i & stb_i & ~ack_o) begin 85 | if (we_i & sel_i[i]) begin 86 | mem[adr_i_valid][WORD_SIZE*i +: WORD_SIZE] <= dat_i[WORD_SIZE*i +: WORD_SIZE]; 87 | end 88 | dat_o_reg[WORD_SIZE*i +: WORD_SIZE] <= mem[adr_i_valid][WORD_SIZE*i +: WORD_SIZE]; 89 | ack_o_reg <= 1'b1; 90 | end 91 | end 92 | end 93 | 94 | endmodule 95 | -------------------------------------------------------------------------------- /rtl/wb_reg.v: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2015-2016 Alex Forencich 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | */ 24 | 25 | // Language: Verilog 2001 26 | 27 | `timescale 1ns / 1ps 28 | 29 | /* 30 | * Wishbone register 31 | */ 32 | module wb_reg # 33 | ( 34 | parameter DATA_WIDTH = 32, // width of data bus in bits (8, 16, 32, or 64) 35 | parameter ADDR_WIDTH = 32, // width of address bus in bits 36 | parameter SELECT_WIDTH = (DATA_WIDTH/8) // width of word select bus (1, 2, 4, or 8) 37 | ) 38 | ( 39 | input wire clk, 40 | input wire rst, 41 | 42 | // master side 43 | input wire [ADDR_WIDTH-1:0] wbm_adr_i, // ADR_I() address 44 | input wire [DATA_WIDTH-1:0] wbm_dat_i, // DAT_I() data in 45 | output wire [DATA_WIDTH-1:0] wbm_dat_o, // DAT_O() data out 46 | input wire wbm_we_i, // WE_I write enable input 47 | input wire [SELECT_WIDTH-1:0] wbm_sel_i, // SEL_I() select input 48 | input wire wbm_stb_i, // STB_I strobe input 49 | output wire wbm_ack_o, // ACK_O acknowledge output 50 | output wire wbm_err_o, // ERR_O error output 51 | output wire wbm_rty_o, // RTY_O retry output 52 | input wire wbm_cyc_i, // CYC_I cycle input 53 | 54 | // slave side 55 | output wire [ADDR_WIDTH-1:0] wbs_adr_o, // ADR_O() address 56 | input wire [DATA_WIDTH-1:0] wbs_dat_i, // DAT_I() data in 57 | output wire [DATA_WIDTH-1:0] wbs_dat_o, // DAT_O() data out 58 | output wire wbs_we_o, // WE_O write enable output 59 | output wire [SELECT_WIDTH-1:0] wbs_sel_o, // SEL_O() select output 60 | output wire wbs_stb_o, // STB_O strobe output 61 | input wire wbs_ack_i, // ACK_I acknowledge input 62 | input wire wbs_err_i, // ERR_I error input 63 | input wire wbs_rty_i, // RTY_I retry input 64 | output wire wbs_cyc_o // CYC_O cycle output 65 | ); 66 | 67 | reg [DATA_WIDTH-1:0] wbm_dat_o_reg = 0; 68 | reg wbm_ack_o_reg = 0; 69 | reg wbm_err_o_reg = 0; 70 | reg wbm_rty_o_reg = 0; 71 | 72 | reg [ADDR_WIDTH-1:0] wbs_adr_o_reg = 0; 73 | reg [DATA_WIDTH-1:0] wbs_dat_o_reg = 0; 74 | reg wbs_we_o_reg = 0; 75 | reg [SELECT_WIDTH-1:0] wbs_sel_o_reg = 0; 76 | reg wbs_stb_o_reg = 0; 77 | reg wbs_cyc_o_reg = 0; 78 | 79 | assign wbm_dat_o = wbm_dat_o_reg; 80 | assign wbm_ack_o = wbm_ack_o_reg; 81 | assign wbm_err_o = wbm_err_o_reg; 82 | assign wbm_rty_o = wbm_rty_o_reg; 83 | 84 | assign wbs_adr_o = wbs_adr_o_reg; 85 | assign wbs_dat_o = wbs_dat_o_reg; 86 | assign wbs_we_o = wbs_we_o_reg; 87 | assign wbs_sel_o = wbs_sel_o_reg; 88 | assign wbs_stb_o = wbs_stb_o_reg; 89 | assign wbs_cyc_o = wbs_cyc_o_reg; 90 | 91 | always @(posedge clk) begin 92 | if (rst) begin 93 | wbm_dat_o_reg <= 0; 94 | wbm_ack_o_reg <= 0; 95 | wbm_err_o_reg <= 0; 96 | wbm_rty_o_reg <= 0; 97 | wbs_adr_o_reg <= 0; 98 | wbs_dat_o_reg <= 0; 99 | wbs_we_o_reg <= 0; 100 | wbs_sel_o_reg <= 0; 101 | wbs_stb_o_reg <= 0; 102 | wbs_cyc_o_reg <= 0; 103 | end else begin 104 | if (wbs_cyc_o_reg & wbs_stb_o_reg) begin 105 | // cycle - hold values 106 | if (wbs_ack_i | wbs_err_i | wbs_rty_i) begin 107 | // end of cycle - pass through slave to master 108 | wbm_dat_o_reg <= wbs_dat_i; 109 | wbm_ack_o_reg <= wbs_ack_i; 110 | wbm_err_o_reg <= wbs_err_i; 111 | wbm_rty_o_reg <= wbs_rty_i; 112 | wbs_we_o_reg <= 0; 113 | wbs_stb_o_reg <= 0; 114 | end 115 | end else begin 116 | // idle - pass through master to slave 117 | wbm_dat_o_reg <= 0; 118 | wbm_ack_o_reg <= 0; 119 | wbm_err_o_reg <= 0; 120 | wbm_rty_o_reg <= 0; 121 | wbs_adr_o_reg <= wbm_adr_i; 122 | wbs_dat_o_reg <= wbm_dat_i; 123 | wbs_we_o_reg <= wbm_we_i & ~(wbm_ack_o | wbm_err_o | wbm_rty_o); 124 | wbs_sel_o_reg <= wbm_sel_i; 125 | wbs_stb_o_reg <= wbm_stb_i & ~(wbm_ack_o | wbm_err_o | wbm_rty_o); 126 | wbs_cyc_o_reg <= wbm_cyc_i; 127 | end 128 | end 129 | end 130 | 131 | endmodule 132 | -------------------------------------------------------------------------------- /tb/test_arbiter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | 4 | Copyright (c) 2014-2018 Alex Forencich 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | 24 | """ 25 | 26 | from myhdl import * 27 | import os 28 | 29 | module = 'arbiter' 30 | testbench = 'test_%s' % module 31 | 32 | srcs = [] 33 | 34 | srcs.append("../rtl/%s.v" % module) 35 | srcs.append("../rtl/priority_encoder.v") 36 | srcs.append("%s.v" % testbench) 37 | 38 | src = ' '.join(srcs) 39 | 40 | build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) 41 | 42 | def bench(): 43 | 44 | # Parameters 45 | PORTS = 32 46 | ARB_TYPE_ROUND_ROBIN = 0 47 | ARB_BLOCK = 1 48 | ARB_BLOCK_ACK = 0 49 | ARB_LSB_HIGH_PRIORITY = 0 50 | 51 | # Inputs 52 | clk = Signal(bool(0)) 53 | rst = Signal(bool(0)) 54 | current_test = Signal(intbv(0)[8:]) 55 | 56 | request = Signal(intbv(0)[PORTS:]) 57 | acknowledge = Signal(intbv(0)[PORTS:]) 58 | 59 | # Outputs 60 | grant = Signal(intbv(0)[PORTS:]) 61 | grant_valid = Signal(bool(0)) 62 | grant_encoded = Signal(intbv(0)[5:]) 63 | 64 | # DUT 65 | if os.system(build_cmd): 66 | raise Exception("Error running build command") 67 | 68 | dut = Cosimulation( 69 | "vvp -m myhdl %s.vvp -lxt2" % testbench, 70 | clk=clk, 71 | rst=rst, 72 | current_test=current_test, 73 | 74 | request=request, 75 | acknowledge=acknowledge, 76 | 77 | grant=grant, 78 | grant_valid=grant_valid, 79 | grant_encoded=grant_encoded 80 | ) 81 | 82 | @always(delay(4)) 83 | def clkgen(): 84 | clk.next = not clk 85 | 86 | @instance 87 | def check(): 88 | yield delay(100) 89 | yield clk.posedge 90 | rst.next = 1 91 | yield clk.posedge 92 | rst.next = 0 93 | yield clk.posedge 94 | yield delay(100) 95 | yield clk.posedge 96 | 97 | yield clk.posedge 98 | 99 | print("test 1: one bit") 100 | current_test.next = 1 101 | 102 | yield clk.posedge 103 | 104 | for i in range(32): 105 | l = [i] 106 | k = 0 107 | for y in l: 108 | k = k | 1 << y 109 | request.next = k 110 | yield clk.posedge 111 | request.next = 0 112 | yield clk.posedge 113 | 114 | assert grant == 1 << i 115 | assert grant_encoded == i 116 | 117 | yield clk.posedge 118 | 119 | yield delay(100) 120 | 121 | yield clk.posedge 122 | 123 | print("test 2: two bits") 124 | current_test.next = 2 125 | 126 | for i in range(32): 127 | for j in range(32): 128 | l = [i, j] 129 | k = 0 130 | for y in l: 131 | k = k | 1 << y 132 | request.next = k 133 | yield clk.posedge 134 | request.next = 0 135 | yield clk.posedge 136 | 137 | assert grant == 1 << max(l) 138 | assert grant_encoded == max(l) 139 | 140 | request.next = 0 141 | 142 | yield clk.posedge 143 | 144 | print("test 3: five bits") 145 | current_test.next = 3 146 | 147 | for i in range(32): 148 | l = [(i*x) % 32 for x in [1,2,3,4,5]] 149 | k = 0 150 | for y in l: 151 | k = k | 1 << y 152 | request.next = k 153 | yield clk.posedge 154 | request.next = 0 155 | yield clk.posedge 156 | 157 | assert grant == 1 << max(l) 158 | assert grant_encoded == max(l) 159 | 160 | prev = int(grant_encoded) 161 | 162 | yield clk.posedge 163 | 164 | yield delay(100) 165 | 166 | raise StopSimulation 167 | 168 | return instances() 169 | 170 | def test_bench(): 171 | os.chdir(os.path.dirname(os.path.abspath(__file__))) 172 | sim = Simulation(bench()) 173 | sim.run() 174 | 175 | if __name__ == '__main__': 176 | print("Running test...") 177 | test_bench() 178 | 179 | -------------------------------------------------------------------------------- /tb/test_arbiter.v: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2014-2018 Alex Forencich 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | */ 24 | 25 | // Language: Verilog 2001 26 | 27 | `timescale 1ns / 1ps 28 | 29 | /* 30 | * Testbench for arbiter 31 | */ 32 | module test_arbiter; 33 | 34 | // Parameters 35 | localparam PORTS = 32; 36 | localparam ARB_TYPE_ROUND_ROBIN = 0; 37 | localparam ARB_BLOCK = 1; 38 | localparam ARB_BLOCK_ACK = 0; 39 | localparam ARB_LSB_HIGH_PRIORITY = 0; 40 | 41 | // Inputs 42 | reg clk = 0; 43 | reg rst = 0; 44 | reg [7:0] current_test = 0; 45 | 46 | reg [PORTS-1:0] request = 0; 47 | reg [PORTS-1:0] acknowledge = 0; 48 | 49 | // Outputs 50 | wire [PORTS-1:0] grant; 51 | wire grant_valid; 52 | wire [$clog2(PORTS)-1:0] grant_encoded; 53 | 54 | initial begin 55 | // myhdl integration 56 | $from_myhdl( 57 | clk, 58 | rst, 59 | current_test, 60 | request, 61 | acknowledge 62 | ); 63 | $to_myhdl( 64 | grant, 65 | grant_valid, 66 | grant_encoded 67 | ); 68 | 69 | // dump file 70 | $dumpfile("test_arbiter.lxt"); 71 | $dumpvars(0, test_arbiter); 72 | end 73 | 74 | arbiter #( 75 | .PORTS(PORTS), 76 | .ARB_TYPE_ROUND_ROBIN(ARB_TYPE_ROUND_ROBIN), 77 | .ARB_BLOCK(ARB_BLOCK), 78 | .ARB_BLOCK_ACK(ARB_BLOCK_ACK), 79 | .ARB_LSB_HIGH_PRIORITY(ARB_LSB_HIGH_PRIORITY) 80 | ) 81 | UUT ( 82 | .clk(clk), 83 | .rst(rst), 84 | .request(request), 85 | .acknowledge(acknowledge), 86 | .grant(grant), 87 | .grant_valid(grant_valid), 88 | .grant_encoded(grant_encoded) 89 | ); 90 | 91 | endmodule 92 | -------------------------------------------------------------------------------- /tb/test_arbiter_rr.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | 4 | Copyright (c) 2014-2018 Alex Forencich 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | 24 | """ 25 | 26 | from myhdl import * 27 | import os 28 | 29 | module = 'arbiter' 30 | testbench = 'test_%s_rr' % module 31 | 32 | srcs = [] 33 | 34 | srcs.append("../rtl/%s.v" % module) 35 | srcs.append("../rtl/priority_encoder.v") 36 | srcs.append("%s.v" % testbench) 37 | 38 | src = ' '.join(srcs) 39 | 40 | build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) 41 | 42 | def bench(): 43 | 44 | # Parameters 45 | PORTS = 32 46 | ARB_TYPE_ROUND_ROBIN = 1 47 | ARB_BLOCK = 1 48 | ARB_BLOCK_ACK = 0 49 | ARB_LSB_HIGH_PRIORITY = 0 50 | 51 | # Inputs 52 | clk = Signal(bool(0)) 53 | rst = Signal(bool(0)) 54 | current_test = Signal(intbv(0)[8:]) 55 | 56 | request = Signal(intbv(0)[PORTS:]) 57 | acknowledge = Signal(intbv(0)[PORTS:]) 58 | 59 | # Outputs 60 | grant = Signal(intbv(0)[PORTS:]) 61 | grant_valid = Signal(bool(0)) 62 | grant_encoded = Signal(intbv(0)[5:]) 63 | 64 | # DUT 65 | if os.system(build_cmd): 66 | raise Exception("Error running build command") 67 | 68 | dut = Cosimulation( 69 | "vvp -m myhdl %s.vvp -lxt2" % testbench, 70 | clk=clk, 71 | rst=rst, 72 | current_test=current_test, 73 | 74 | request=request, 75 | acknowledge=acknowledge, 76 | 77 | grant=grant, 78 | grant_valid=grant_valid, 79 | grant_encoded=grant_encoded 80 | ) 81 | 82 | @always(delay(4)) 83 | def clkgen(): 84 | clk.next = not clk 85 | 86 | @instance 87 | def check(): 88 | yield delay(100) 89 | yield clk.posedge 90 | rst.next = 1 91 | yield clk.posedge 92 | rst.next = 0 93 | yield clk.posedge 94 | yield delay(100) 95 | yield clk.posedge 96 | 97 | yield clk.posedge 98 | 99 | prev = 0 100 | 101 | print("test 1: one bit") 102 | current_test.next = 1 103 | 104 | yield clk.posedge 105 | 106 | for i in range(32): 107 | l = [i] 108 | k = 0 109 | for y in l: 110 | k = k | 1 << y 111 | request.next = k 112 | yield clk.posedge 113 | request.next = 0 114 | yield clk.posedge 115 | 116 | # emulate round robin 117 | l2 = [x for x in l if x < prev] 118 | if len(l2) == 0: 119 | l2 = l 120 | g = max(l2) 121 | 122 | assert grant == 1 << g 123 | assert grant_encoded == g 124 | 125 | prev = int(grant_encoded) 126 | 127 | yield clk.posedge 128 | 129 | yield delay(100) 130 | 131 | yield clk.posedge 132 | 133 | print("test 2: cycle") 134 | current_test.next = 2 135 | 136 | for i in range(32): 137 | l = [0, 5, 10, 15, 20, 25, 30] 138 | k = 0 139 | for y in l: 140 | k = k | 1 << y 141 | request.next = k 142 | yield clk.posedge 143 | request.next = 0 144 | yield clk.posedge 145 | 146 | # emulate round robin 147 | l2 = [x for x in l if x < prev] 148 | if len(l2) == 0: 149 | l2 = l 150 | g = max(l2) 151 | 152 | assert grant == 1 << g 153 | assert grant_encoded == g 154 | 155 | prev = int(grant_encoded) 156 | 157 | yield clk.posedge 158 | 159 | yield delay(100) 160 | 161 | yield clk.posedge 162 | 163 | print("test 3: two bits") 164 | current_test.next = 3 165 | 166 | for i in range(32): 167 | for j in range(32): 168 | l = [i, j] 169 | k = 0 170 | for y in l: 171 | k = k | 1 << y 172 | request.next = k 173 | yield clk.posedge 174 | request.next = 0 175 | yield clk.posedge 176 | 177 | # emulate round robin 178 | l2 = [x for x in l if x < prev] 179 | if len(l2) == 0: 180 | l2 = l 181 | g = max(l2) 182 | 183 | assert grant == 1 << g 184 | assert grant_encoded == g 185 | 186 | prev = int(grant_encoded) 187 | 188 | yield clk.posedge 189 | 190 | yield delay(100) 191 | 192 | yield clk.posedge 193 | 194 | print("test 4: five bits") 195 | current_test.next = 4 196 | 197 | for i in range(32): 198 | l = [(i*x) % 32 for x in [1,2,3,4,5]] 199 | k = 0 200 | for y in l: 201 | k = k | 1 << y 202 | request.next = k 203 | yield clk.posedge 204 | request.next = 0 205 | yield clk.posedge 206 | 207 | # emulate round robin 208 | l2 = [x for x in l if x < prev] 209 | if len(l2) == 0: 210 | l2 = l 211 | g = max(l2) 212 | 213 | assert grant == 1 << g 214 | assert grant_encoded == g 215 | 216 | prev = int(grant_encoded) 217 | 218 | yield clk.posedge 219 | 220 | yield delay(100) 221 | 222 | yield clk.posedge 223 | 224 | yield delay(100) 225 | 226 | raise StopSimulation 227 | 228 | return instances() 229 | 230 | def test_bench(): 231 | os.chdir(os.path.dirname(os.path.abspath(__file__))) 232 | sim = Simulation(bench()) 233 | sim.run() 234 | 235 | if __name__ == '__main__': 236 | print("Running test...") 237 | test_bench() 238 | 239 | -------------------------------------------------------------------------------- /tb/test_arbiter_rr.v: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2014-2018 Alex Forencich 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | */ 24 | 25 | // Language: Verilog 2001 26 | 27 | `timescale 1ns / 1ps 28 | 29 | /* 30 | * Testbench for arbiter 31 | */ 32 | module test_arbiter_rr; 33 | 34 | // Parameters 35 | localparam PORTS = 32; 36 | localparam ARB_TYPE_ROUND_ROBIN = 1; 37 | localparam ARB_BLOCK = 1; 38 | localparam ARB_BLOCK_ACK = 0; 39 | localparam ARB_LSB_HIGH_PRIORITY = 0; 40 | 41 | // Inputs 42 | reg clk = 0; 43 | reg rst = 0; 44 | reg [7:0] current_test = 0; 45 | 46 | reg [PORTS-1:0] request = 0; 47 | reg [PORTS-1:0] acknowledge = 0; 48 | 49 | // Outputs 50 | wire [PORTS-1:0] grant; 51 | wire grant_valid; 52 | wire [$clog2(PORTS)-1:0] grant_encoded; 53 | 54 | initial begin 55 | // myhdl integration 56 | $from_myhdl( 57 | clk, 58 | rst, 59 | current_test, 60 | request, 61 | acknowledge 62 | ); 63 | $to_myhdl( 64 | grant, 65 | grant_valid, 66 | grant_encoded 67 | ); 68 | 69 | // dump file 70 | $dumpfile("test_arbiter_rr.lxt"); 71 | $dumpvars(0, test_arbiter_rr); 72 | end 73 | 74 | arbiter #( 75 | .PORTS(PORTS), 76 | .ARB_TYPE_ROUND_ROBIN(ARB_TYPE_ROUND_ROBIN), 77 | .ARB_BLOCK(ARB_BLOCK), 78 | .ARB_BLOCK_ACK(ARB_BLOCK_ACK), 79 | .ARB_LSB_HIGH_PRIORITY(ARB_LSB_HIGH_PRIORITY) 80 | ) 81 | UUT ( 82 | .clk(clk), 83 | .rst(rst), 84 | .request(request), 85 | .acknowledge(acknowledge), 86 | .grant(grant), 87 | .grant_valid(grant_valid), 88 | .grant_encoded(grant_encoded) 89 | ); 90 | 91 | endmodule 92 | -------------------------------------------------------------------------------- /tb/test_axis_wb_master_8_32.v: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2016 Alex Forencich 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | */ 24 | 25 | // Language: Verilog 2001 26 | 27 | `timescale 1ns / 1ps 28 | 29 | /* 30 | * Testbench for axis_wb_master 31 | */ 32 | module test_axis_wb_master_8_32; 33 | 34 | // Parameters 35 | parameter IMPLICIT_FRAMING = 0; 36 | parameter COUNT_SIZE = 16; 37 | parameter AXIS_DATA_WIDTH = 8; 38 | parameter AXIS_KEEP_WIDTH = (AXIS_DATA_WIDTH/8); 39 | parameter WB_DATA_WIDTH = 32; 40 | parameter WB_ADDR_WIDTH = 32; 41 | parameter WB_SELECT_WIDTH = (WB_DATA_WIDTH/8); 42 | parameter READ_REQ = 8'hA1; 43 | parameter WRITE_REQ = 8'hA2; 44 | parameter READ_RESP = 8'hA3; 45 | parameter WRITE_RESP = 8'hA4; 46 | 47 | // Inputs 48 | reg clk = 0; 49 | reg rst = 0; 50 | reg [7:0] current_test = 0; 51 | 52 | reg [AXIS_DATA_WIDTH-1:0] input_axis_tdata = 0; 53 | reg [AXIS_KEEP_WIDTH-1:0] input_axis_tkeep = 0; 54 | reg input_axis_tvalid = 0; 55 | reg input_axis_tlast = 0; 56 | reg input_axis_tuser = 0; 57 | reg output_axis_tready = 0; 58 | reg [WB_DATA_WIDTH-1:0] wb_dat_i = 0; 59 | reg wb_ack_i = 0; 60 | reg wb_err_i = 0; 61 | 62 | // Outputs 63 | wire input_axis_tready; 64 | wire [AXIS_DATA_WIDTH-1:0] output_axis_tdata; 65 | wire [AXIS_KEEP_WIDTH-1:0] output_axis_tkeep; 66 | wire output_axis_tvalid; 67 | wire output_axis_tlast; 68 | wire output_axis_tuser; 69 | wire [WB_ADDR_WIDTH-1:0] wb_adr_o; 70 | wire [WB_DATA_WIDTH-1:0] wb_dat_o; 71 | wire wb_we_o; 72 | wire [WB_SELECT_WIDTH-1:0] wb_sel_o; 73 | wire wb_stb_o; 74 | wire wb_cyc_o; 75 | wire busy; 76 | 77 | initial begin 78 | // myhdl integration 79 | $from_myhdl( 80 | clk, 81 | rst, 82 | current_test, 83 | input_axis_tdata, 84 | input_axis_tkeep, 85 | input_axis_tvalid, 86 | input_axis_tlast, 87 | input_axis_tuser, 88 | output_axis_tready, 89 | wb_dat_i, 90 | wb_ack_i, 91 | wb_err_i 92 | ); 93 | $to_myhdl( 94 | input_axis_tready, 95 | output_axis_tdata, 96 | output_axis_tkeep, 97 | output_axis_tvalid, 98 | output_axis_tlast, 99 | output_axis_tuser, 100 | wb_adr_o, 101 | wb_dat_o, 102 | wb_we_o, 103 | wb_sel_o, 104 | wb_stb_o, 105 | wb_cyc_o, 106 | busy 107 | ); 108 | 109 | // dump file 110 | $dumpfile("test_axis_wb_master_8_32.lxt"); 111 | $dumpvars(0, test_axis_wb_master_8_32); 112 | end 113 | 114 | axis_wb_master #( 115 | .IMPLICIT_FRAMING(IMPLICIT_FRAMING), 116 | .COUNT_SIZE(COUNT_SIZE), 117 | .AXIS_DATA_WIDTH(AXIS_DATA_WIDTH), 118 | .AXIS_KEEP_WIDTH(AXIS_KEEP_WIDTH), 119 | .WB_DATA_WIDTH(WB_DATA_WIDTH), 120 | .WB_ADDR_WIDTH(WB_ADDR_WIDTH), 121 | .WB_SELECT_WIDTH(WB_SELECT_WIDTH), 122 | .READ_REQ(READ_REQ), 123 | .WRITE_REQ(WRITE_REQ), 124 | .READ_RESP(READ_RESP), 125 | .WRITE_RESP(WRITE_RESP) 126 | ) 127 | UUT ( 128 | .clk(clk), 129 | .rst(rst), 130 | .input_axis_tdata(input_axis_tdata), 131 | .input_axis_tkeep(input_axis_tkeep), 132 | .input_axis_tvalid(input_axis_tvalid), 133 | .input_axis_tready(input_axis_tready), 134 | .input_axis_tlast(input_axis_tlast), 135 | .input_axis_tuser(input_axis_tuser), 136 | .output_axis_tdata(output_axis_tdata), 137 | .output_axis_tkeep(output_axis_tkeep), 138 | .output_axis_tvalid(output_axis_tvalid), 139 | .output_axis_tready(output_axis_tready), 140 | .output_axis_tlast(output_axis_tlast), 141 | .output_axis_tuser(output_axis_tuser), 142 | .wb_adr_o(wb_adr_o), 143 | .wb_dat_i(wb_dat_i), 144 | .wb_dat_o(wb_dat_o), 145 | .wb_we_o(wb_we_o), 146 | .wb_sel_o(wb_sel_o), 147 | .wb_stb_o(wb_stb_o), 148 | .wb_ack_i(wb_ack_i), 149 | .wb_err_i(wb_err_i), 150 | .wb_cyc_o(wb_cyc_o), 151 | .busy(busy) 152 | ); 153 | 154 | endmodule 155 | -------------------------------------------------------------------------------- /tb/test_axis_wb_master_8_32_16.v: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2016 Alex Forencich 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | */ 24 | 25 | // Language: Verilog 2001 26 | 27 | `timescale 1ns / 1ps 28 | 29 | /* 30 | * Testbench for axis_wb_master 31 | */ 32 | module test_axis_wb_master_8_32_16; 33 | 34 | // Parameters 35 | parameter IMPLICIT_FRAMING = 0; 36 | parameter COUNT_SIZE = 16; 37 | parameter AXIS_DATA_WIDTH = 8; 38 | parameter AXIS_KEEP_WIDTH = (AXIS_DATA_WIDTH/8); 39 | parameter WB_DATA_WIDTH = 32; 40 | parameter WB_ADDR_WIDTH = 31; 41 | parameter WB_SELECT_WIDTH = 2; 42 | parameter READ_REQ = 8'hA1; 43 | parameter WRITE_REQ = 8'hA2; 44 | parameter READ_RESP = 8'hA3; 45 | parameter WRITE_RESP = 8'hA4; 46 | 47 | // Inputs 48 | reg clk = 0; 49 | reg rst = 0; 50 | reg [7:0] current_test = 0; 51 | 52 | reg [AXIS_DATA_WIDTH-1:0] input_axis_tdata = 0; 53 | reg [AXIS_KEEP_WIDTH-1:0] input_axis_tkeep = 0; 54 | reg input_axis_tvalid = 0; 55 | reg input_axis_tlast = 0; 56 | reg input_axis_tuser = 0; 57 | reg output_axis_tready = 0; 58 | reg [WB_DATA_WIDTH-1:0] wb_dat_i = 0; 59 | reg wb_ack_i = 0; 60 | reg wb_err_i = 0; 61 | 62 | // Outputs 63 | wire input_axis_tready; 64 | wire [AXIS_DATA_WIDTH-1:0] output_axis_tdata; 65 | wire [AXIS_KEEP_WIDTH-1:0] output_axis_tkeep; 66 | wire output_axis_tvalid; 67 | wire output_axis_tlast; 68 | wire output_axis_tuser; 69 | wire [WB_ADDR_WIDTH-1:0] wb_adr_o; 70 | wire [WB_DATA_WIDTH-1:0] wb_dat_o; 71 | wire wb_we_o; 72 | wire [WB_SELECT_WIDTH-1:0] wb_sel_o; 73 | wire wb_stb_o; 74 | wire wb_cyc_o; 75 | wire busy; 76 | 77 | initial begin 78 | // myhdl integration 79 | $from_myhdl( 80 | clk, 81 | rst, 82 | current_test, 83 | input_axis_tdata, 84 | input_axis_tkeep, 85 | input_axis_tvalid, 86 | input_axis_tlast, 87 | input_axis_tuser, 88 | output_axis_tready, 89 | wb_dat_i, 90 | wb_ack_i, 91 | wb_err_i 92 | ); 93 | $to_myhdl( 94 | input_axis_tready, 95 | output_axis_tdata, 96 | output_axis_tkeep, 97 | output_axis_tvalid, 98 | output_axis_tlast, 99 | output_axis_tuser, 100 | wb_adr_o, 101 | wb_dat_o, 102 | wb_we_o, 103 | wb_sel_o, 104 | wb_stb_o, 105 | wb_cyc_o, 106 | busy 107 | ); 108 | 109 | // dump file 110 | $dumpfile("test_axis_wb_master_8_32_16.lxt"); 111 | $dumpvars(0, test_axis_wb_master_8_32_16); 112 | end 113 | 114 | axis_wb_master #( 115 | .IMPLICIT_FRAMING(IMPLICIT_FRAMING), 116 | .COUNT_SIZE(COUNT_SIZE), 117 | .AXIS_DATA_WIDTH(AXIS_DATA_WIDTH), 118 | .AXIS_KEEP_WIDTH(AXIS_KEEP_WIDTH), 119 | .WB_DATA_WIDTH(WB_DATA_WIDTH), 120 | .WB_ADDR_WIDTH(WB_ADDR_WIDTH), 121 | .WB_SELECT_WIDTH(WB_SELECT_WIDTH), 122 | .READ_REQ(READ_REQ), 123 | .WRITE_REQ(WRITE_REQ), 124 | .READ_RESP(READ_RESP), 125 | .WRITE_RESP(WRITE_RESP) 126 | ) 127 | UUT ( 128 | .clk(clk), 129 | .rst(rst), 130 | .input_axis_tdata(input_axis_tdata), 131 | .input_axis_tkeep(input_axis_tkeep), 132 | .input_axis_tvalid(input_axis_tvalid), 133 | .input_axis_tready(input_axis_tready), 134 | .input_axis_tlast(input_axis_tlast), 135 | .input_axis_tuser(input_axis_tuser), 136 | .output_axis_tdata(output_axis_tdata), 137 | .output_axis_tkeep(output_axis_tkeep), 138 | .output_axis_tvalid(output_axis_tvalid), 139 | .output_axis_tready(output_axis_tready), 140 | .output_axis_tlast(output_axis_tlast), 141 | .output_axis_tuser(output_axis_tuser), 142 | .wb_adr_o(wb_adr_o), 143 | .wb_dat_i(wb_dat_i), 144 | .wb_dat_o(wb_dat_o), 145 | .wb_we_o(wb_we_o), 146 | .wb_sel_o(wb_sel_o), 147 | .wb_stb_o(wb_stb_o), 148 | .wb_ack_i(wb_ack_i), 149 | .wb_err_i(wb_err_i), 150 | .wb_cyc_o(wb_cyc_o), 151 | .busy(busy) 152 | ); 153 | 154 | endmodule 155 | -------------------------------------------------------------------------------- /tb/test_axis_wb_master_8_32_imp.v: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2016 Alex Forencich 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | */ 24 | 25 | // Language: Verilog 2001 26 | 27 | `timescale 1ns / 1ps 28 | 29 | /* 30 | * Testbench for axis_wb_master 31 | */ 32 | module test_axis_wb_master_8_32_imp; 33 | 34 | // Parameters 35 | parameter IMPLICIT_FRAMING = 1; 36 | parameter COUNT_SIZE = 16; 37 | parameter AXIS_DATA_WIDTH = 8; 38 | parameter AXIS_KEEP_WIDTH = (AXIS_DATA_WIDTH/8); 39 | parameter WB_DATA_WIDTH = 32; 40 | parameter WB_ADDR_WIDTH = 32; 41 | parameter WB_SELECT_WIDTH = (WB_DATA_WIDTH/8); 42 | parameter READ_REQ = 8'hA1; 43 | parameter WRITE_REQ = 8'hA2; 44 | parameter READ_RESP = 8'hA3; 45 | parameter WRITE_RESP = 8'hA4; 46 | 47 | // Inputs 48 | reg clk = 0; 49 | reg rst = 0; 50 | reg [7:0] current_test = 0; 51 | 52 | reg [AXIS_DATA_WIDTH-1:0] input_axis_tdata = 0; 53 | reg [AXIS_KEEP_WIDTH-1:0] input_axis_tkeep = 0; 54 | reg input_axis_tvalid = 0; 55 | reg input_axis_tlast = 0; 56 | reg input_axis_tuser = 0; 57 | reg output_axis_tready = 0; 58 | reg [WB_DATA_WIDTH-1:0] wb_dat_i = 0; 59 | reg wb_ack_i = 0; 60 | reg wb_err_i = 0; 61 | 62 | // Outputs 63 | wire input_axis_tready; 64 | wire [AXIS_DATA_WIDTH-1:0] output_axis_tdata; 65 | wire [AXIS_KEEP_WIDTH-1:0] output_axis_tkeep; 66 | wire output_axis_tvalid; 67 | wire output_axis_tlast; 68 | wire output_axis_tuser; 69 | wire [WB_ADDR_WIDTH-1:0] wb_adr_o; 70 | wire [WB_DATA_WIDTH-1:0] wb_dat_o; 71 | wire wb_we_o; 72 | wire [WB_SELECT_WIDTH-1:0] wb_sel_o; 73 | wire wb_stb_o; 74 | wire wb_cyc_o; 75 | wire busy; 76 | 77 | initial begin 78 | // myhdl integration 79 | $from_myhdl( 80 | clk, 81 | rst, 82 | current_test, 83 | input_axis_tdata, 84 | input_axis_tkeep, 85 | input_axis_tvalid, 86 | input_axis_tlast, 87 | input_axis_tuser, 88 | output_axis_tready, 89 | wb_dat_i, 90 | wb_ack_i, 91 | wb_err_i 92 | ); 93 | $to_myhdl( 94 | input_axis_tready, 95 | output_axis_tdata, 96 | output_axis_tkeep, 97 | output_axis_tvalid, 98 | output_axis_tlast, 99 | output_axis_tuser, 100 | wb_adr_o, 101 | wb_dat_o, 102 | wb_we_o, 103 | wb_sel_o, 104 | wb_stb_o, 105 | wb_cyc_o, 106 | busy 107 | ); 108 | 109 | // dump file 110 | $dumpfile("test_axis_wb_master_8_32_imp.lxt"); 111 | $dumpvars(0, test_axis_wb_master_8_32_imp); 112 | end 113 | 114 | axis_wb_master #( 115 | .IMPLICIT_FRAMING(IMPLICIT_FRAMING), 116 | .COUNT_SIZE(COUNT_SIZE), 117 | .AXIS_DATA_WIDTH(AXIS_DATA_WIDTH), 118 | .AXIS_KEEP_WIDTH(AXIS_KEEP_WIDTH), 119 | .WB_DATA_WIDTH(WB_DATA_WIDTH), 120 | .WB_ADDR_WIDTH(WB_ADDR_WIDTH), 121 | .WB_SELECT_WIDTH(WB_SELECT_WIDTH), 122 | .READ_REQ(READ_REQ), 123 | .WRITE_REQ(WRITE_REQ), 124 | .READ_RESP(READ_RESP), 125 | .WRITE_RESP(WRITE_RESP) 126 | ) 127 | UUT ( 128 | .clk(clk), 129 | .rst(rst), 130 | .input_axis_tdata(input_axis_tdata), 131 | .input_axis_tkeep(input_axis_tkeep), 132 | .input_axis_tvalid(input_axis_tvalid), 133 | .input_axis_tready(input_axis_tready), 134 | .input_axis_tlast(input_axis_tlast), 135 | .input_axis_tuser(input_axis_tuser), 136 | .output_axis_tdata(output_axis_tdata), 137 | .output_axis_tkeep(output_axis_tkeep), 138 | .output_axis_tvalid(output_axis_tvalid), 139 | .output_axis_tready(output_axis_tready), 140 | .output_axis_tlast(output_axis_tlast), 141 | .output_axis_tuser(output_axis_tuser), 142 | .wb_adr_o(wb_adr_o), 143 | .wb_dat_i(wb_dat_i), 144 | .wb_dat_o(wb_dat_o), 145 | .wb_we_o(wb_we_o), 146 | .wb_sel_o(wb_sel_o), 147 | .wb_stb_o(wb_stb_o), 148 | .wb_ack_i(wb_ack_i), 149 | .wb_err_i(wb_err_i), 150 | .wb_cyc_o(wb_cyc_o), 151 | .busy(busy) 152 | ); 153 | 154 | endmodule 155 | -------------------------------------------------------------------------------- /tb/test_priority_encoder.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | 4 | Copyright (c) 2014-2018 Alex Forencich 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | 24 | """ 25 | 26 | from myhdl import * 27 | import os 28 | 29 | module = 'priority_encoder' 30 | testbench = 'test_%s' % module 31 | 32 | srcs = [] 33 | 34 | srcs.append("../rtl/%s.v" % module) 35 | srcs.append("%s.v" % testbench) 36 | 37 | src = ' '.join(srcs) 38 | 39 | build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) 40 | 41 | def bench(): 42 | 43 | # Parameters 44 | WIDTH = 32 45 | LSB_HIGH_PRIORITY = 0 46 | 47 | # Inputs 48 | clk = Signal(bool(0)) 49 | rst = Signal(bool(0)) 50 | current_test = Signal(intbv(0)[8:]) 51 | 52 | input_unencoded = Signal(intbv(0)[WIDTH:]) 53 | 54 | # Outputs 55 | output_valid = Signal(bool(0)) 56 | output_encoded = Signal(intbv(0)[5:]) 57 | output_unencoded = Signal(intbv(0)[WIDTH:]) 58 | 59 | # DUT 60 | if os.system(build_cmd): 61 | raise Exception("Error running build command") 62 | 63 | dut = Cosimulation( 64 | "vvp -m myhdl %s.vvp -lxt2" % testbench, 65 | clk=clk, 66 | rst=rst, 67 | current_test=current_test, 68 | 69 | input_unencoded=input_unencoded, 70 | 71 | output_valid=output_valid, 72 | output_encoded=output_encoded, 73 | output_unencoded=output_unencoded 74 | ) 75 | 76 | @always(delay(4)) 77 | def clkgen(): 78 | clk.next = not clk 79 | 80 | @instance 81 | def check(): 82 | yield delay(100) 83 | yield clk.posedge 84 | rst.next = 1 85 | yield clk.posedge 86 | rst.next = 0 87 | yield clk.posedge 88 | yield delay(100) 89 | yield clk.posedge 90 | 91 | yield clk.posedge 92 | 93 | print("test 1: one bit") 94 | current_test.next = 1 95 | 96 | for i in range(32): 97 | input_unencoded.next = 1 << i 98 | 99 | yield clk.posedge 100 | 101 | assert output_encoded == i 102 | assert output_unencoded == 1 << i 103 | 104 | yield delay(100) 105 | 106 | yield clk.posedge 107 | 108 | print("test 2: two bits") 109 | current_test.next = 2 110 | 111 | for i in range(32): 112 | for j in range(32): 113 | 114 | input_unencoded.next = (1 << i) | (1 << j) 115 | 116 | yield clk.posedge 117 | 118 | assert output_encoded == max(i,j) 119 | assert output_unencoded == 1 << max(i,j) 120 | 121 | yield delay(100) 122 | 123 | raise StopSimulation 124 | 125 | return instances() 126 | 127 | def test_bench(): 128 | os.chdir(os.path.dirname(os.path.abspath(__file__))) 129 | sim = Simulation(bench()) 130 | sim.run() 131 | 132 | if __name__ == '__main__': 133 | print("Running test...") 134 | test_bench() 135 | 136 | -------------------------------------------------------------------------------- /tb/test_priority_encoder.v: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2014-2018 Alex Forencich 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | */ 24 | 25 | // Language: Verilog 2001 26 | 27 | `timescale 1ns / 1ps 28 | 29 | /* 30 | * Testbench for priority_encoder 31 | */ 32 | module test_priority_encoder; 33 | 34 | // Parameters 35 | localparam WIDTH = 32; 36 | localparam LSB_HIGH_PRIORITY = 0; 37 | 38 | // Inputs 39 | reg clk = 0; 40 | reg rst = 0; 41 | reg [7:0] current_test = 0; 42 | 43 | reg [WIDTH-1:0] input_unencoded = 0; 44 | 45 | // Outputs 46 | wire output_valid; 47 | wire [$clog2(WIDTH)-1:0] output_encoded; 48 | wire [WIDTH-1:0] output_unencoded; 49 | 50 | initial begin 51 | // myhdl integration 52 | $from_myhdl( 53 | clk, 54 | rst, 55 | current_test, 56 | input_unencoded 57 | ); 58 | $to_myhdl( 59 | output_valid, 60 | output_encoded, 61 | output_unencoded 62 | ); 63 | 64 | // dump file 65 | $dumpfile("test_priority_encoder.lxt"); 66 | $dumpvars(0, test_priority_encoder); 67 | end 68 | 69 | priority_encoder #( 70 | .WIDTH(WIDTH), 71 | .LSB_HIGH_PRIORITY(LSB_HIGH_PRIORITY) 72 | ) 73 | UUT ( 74 | .input_unencoded(input_unencoded), 75 | .output_valid(output_valid), 76 | .output_encoded(output_encoded), 77 | .output_unencoded(output_unencoded) 78 | ); 79 | 80 | endmodule 81 | -------------------------------------------------------------------------------- /tb/test_wb.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | 4 | Copyright (c) 2015-2016 Alex Forencich 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | 24 | """ 25 | 26 | from myhdl import * 27 | import os 28 | 29 | import wb 30 | 31 | def bench(): 32 | 33 | # Inputs 34 | clk = Signal(bool(0)) 35 | rst = Signal(bool(0)) 36 | current_test = Signal(intbv(0)[8:]) 37 | 38 | port0_adr_i = Signal(intbv(0)[32:]) 39 | port0_dat_i = Signal(intbv(0)[32:]) 40 | port0_we_i = Signal(bool(0)) 41 | port0_sel_i = Signal(intbv(0)[4:]) 42 | port0_stb_i = Signal(bool(0)) 43 | port0_cyc_i = Signal(bool(0)) 44 | 45 | # Outputs 46 | port0_dat_o = Signal(intbv(0)[32:]) 47 | port0_ack_o = Signal(bool(0)) 48 | 49 | # WB master 50 | wb_master_inst = wb.WBMaster() 51 | 52 | wb_master_logic = wb_master_inst.create_logic( 53 | clk, 54 | adr_o=port0_adr_i, 55 | dat_i=port0_dat_o, 56 | dat_o=port0_dat_i, 57 | we_o=port0_we_i, 58 | sel_o=port0_sel_i, 59 | stb_o=port0_stb_i, 60 | ack_i=port0_ack_o, 61 | cyc_o=port0_cyc_i, 62 | name='master' 63 | ) 64 | 65 | # WB RAM model 66 | wb_ram_inst = wb.WBRam(2**16) 67 | 68 | wb_ram_port0 = wb_ram_inst.create_port( 69 | clk, 70 | adr_i=port0_adr_i, 71 | dat_i=port0_dat_i, 72 | dat_o=port0_dat_o, 73 | we_i=port0_we_i, 74 | sel_i=port0_sel_i, 75 | stb_i=port0_stb_i, 76 | ack_o=port0_ack_o, 77 | cyc_i=port0_cyc_i, 78 | latency=1, 79 | asynchronous=False, 80 | name='port0' 81 | ) 82 | 83 | @always(delay(4)) 84 | def clkgen(): 85 | clk.next = not clk 86 | 87 | @instance 88 | def check(): 89 | yield delay(100) 90 | yield clk.posedge 91 | rst.next = 1 92 | yield clk.posedge 93 | rst.next = 0 94 | yield clk.posedge 95 | yield delay(100) 96 | yield clk.posedge 97 | 98 | yield clk.posedge 99 | print("test 1: baseline") 100 | current_test.next = 1 101 | 102 | data = wb_ram_inst.read_mem(0, 32) 103 | for i in range(0, len(data), 16): 104 | print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16])))) 105 | 106 | yield delay(100) 107 | 108 | yield clk.posedge 109 | print("test 2: direct write") 110 | current_test.next = 2 111 | 112 | wb_ram_inst.write_mem(0, b'test') 113 | 114 | data = wb_ram_inst.read_mem(0, 32) 115 | for i in range(0, len(data), 16): 116 | print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16])))) 117 | 118 | assert wb_ram_inst.read_mem(0,4) == b'test' 119 | 120 | yield clk.posedge 121 | print("test 3: write via port0") 122 | current_test.next = 3 123 | 124 | wb_master_inst.init_write(4, b'\x11\x22\x33\x44') 125 | 126 | yield wb_master_inst.wait() 127 | yield clk.posedge 128 | 129 | data = wb_ram_inst.read_mem(0, 32) 130 | for i in range(0, len(data), 16): 131 | print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16])))) 132 | 133 | assert wb_ram_inst.read_mem(4,4) == b'\x11\x22\x33\x44' 134 | 135 | yield delay(100) 136 | 137 | yield clk.posedge 138 | print("test 4: read via port0") 139 | current_test.next = 4 140 | 141 | wb_master_inst.init_read(4, 4) 142 | 143 | yield wb_master_inst.wait() 144 | yield clk.posedge 145 | 146 | data = wb_master_inst.get_read_data() 147 | assert data[0] == 4 148 | assert data[1] == b'\x11\x22\x33\x44' 149 | 150 | yield delay(100) 151 | 152 | yield clk.posedge 153 | print("test 5: various writes") 154 | current_test.next = 5 155 | 156 | for length in range(1,8): 157 | for offset in range(4,8): 158 | wb_ram_inst.write_mem(256*(16*offset+length), b'\xAA'*32) 159 | wb_master_inst.init_write(256*(16*offset+length)+offset, b'\x11\x22\x33\x44\x55\x66\x77\x88'[0:length]) 160 | 161 | yield wb_master_inst.wait() 162 | yield clk.posedge 163 | 164 | data = wb_ram_inst.read_mem(256*(16*offset+length), 32) 165 | for i in range(0, len(data), 16): 166 | print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16])))) 167 | 168 | assert wb_ram_inst.read_mem(256*(16*offset+length)+offset, length) == b'\x11\x22\x33\x44\x55\x66\x77\x88'[0:length] 169 | assert wb_ram_inst.read_mem(256*(16*offset+length)+offset-1, 1) == b'\xAA' 170 | assert wb_ram_inst.read_mem(256*(16*offset+length)+offset+length, 1) == b'\xAA' 171 | 172 | yield delay(100) 173 | 174 | yield clk.posedge 175 | print("test 6: various reads") 176 | current_test.next = 6 177 | 178 | for length in range(1,8): 179 | for offset in range(4,8): 180 | wb_master_inst.init_read(256*(16*offset+length)+offset, length) 181 | 182 | yield wb_master_inst.wait() 183 | yield clk.posedge 184 | 185 | data = wb_master_inst.get_read_data() 186 | assert data[0] == 256*(16*offset+length)+offset 187 | assert data[1] == b'\x11\x22\x33\x44\x55\x66\x77\x88'[0:length] 188 | 189 | yield delay(100) 190 | 191 | yield clk.posedge 192 | print("test 7: write words") 193 | current_test.next = 7 194 | 195 | for offset in range(4): 196 | wb_master_inst.init_write_words((0x4000+offset*64+0)/2+offset, [0x1234]) 197 | wb_master_inst.init_write_dwords((0x4000+offset*64+16)/4+offset, [0x12345678]) 198 | wb_master_inst.init_write_qwords((0x4000+offset*64+32)/8+offset, [0x1234567887654321]) 199 | 200 | yield wb_master_inst.wait() 201 | yield clk.posedge 202 | 203 | data = wb_ram_inst.read_mem(0x4000+offset*64, 64) 204 | for i in range(0, len(data), 16): 205 | print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16])))) 206 | 207 | assert wb_ram_inst.read_mem((0x4000+offset*64+0)+offset*2, 2) == b'\x34\x12' 208 | assert wb_ram_inst.read_mem((0x4000+offset*64+16)+offset*4, 4) == b'\x78\x56\x34\x12' 209 | assert wb_ram_inst.read_mem((0x4000+offset*64+32)+offset*8, 8) == b'\x21\x43\x65\x87\x78\x56\x34\x12' 210 | 211 | assert wb_ram_inst.read_words((0x4000+offset*64+0)/2+offset, 1)[0] == 0x1234 212 | assert wb_ram_inst.read_dwords((0x4000+offset*64+16)/4+offset, 1)[0] == 0x12345678 213 | assert wb_ram_inst.read_qwords((0x4000+offset*64+32)/8+offset, 1)[0] == 0x1234567887654321 214 | 215 | yield delay(100) 216 | 217 | yield clk.posedge 218 | print("test 8: read words") 219 | current_test.next = 8 220 | 221 | for offset in range(4): 222 | wb_master_inst.init_read_words((0x4000+offset*64+0)/2+offset, 1) 223 | wb_master_inst.init_read_dwords((0x4000+offset*64+16)/4+offset, 1) 224 | wb_master_inst.init_read_qwords((0x4000+offset*64+32)/8+offset, 1) 225 | 226 | yield wb_master_inst.wait() 227 | yield clk.posedge 228 | 229 | data = wb_master_inst.get_read_data_words() 230 | assert data[0] == (0x4000+offset*64+0)/2+offset 231 | assert data[1][0] == 0x1234 232 | 233 | data = wb_master_inst.get_read_data_dwords() 234 | assert data[0] == (0x4000+offset*64+16)/4+offset 235 | assert data[1][0] == 0x12345678 236 | 237 | data = wb_master_inst.get_read_data_qwords() 238 | assert data[0] == (0x4000+offset*64+32)/8+offset 239 | assert data[1][0] == 0x1234567887654321 240 | 241 | yield delay(100) 242 | 243 | raise StopSimulation 244 | 245 | return instances() 246 | 247 | def test_bench(): 248 | os.chdir(os.path.dirname(os.path.abspath(__file__))) 249 | #sim = Simulation(bench()) 250 | traceSignals.name = os.path.basename(__file__).rsplit('.',1)[0] 251 | sim = Simulation(traceSignals(bench)) 252 | sim.run() 253 | 254 | if __name__ == '__main__': 255 | print("Running test...") 256 | test_bench() 257 | 258 | -------------------------------------------------------------------------------- /tb/test_wb_adapter_16_32.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | 4 | Copyright (c) 2015-2016 Alex Forencich 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | 24 | """ 25 | 26 | from myhdl import * 27 | import os 28 | 29 | import wb 30 | 31 | module = 'wb_adapter' 32 | testbench = 'test_%s_16_32' % module 33 | 34 | srcs = [] 35 | 36 | srcs.append("../rtl/%s.v" % module) 37 | srcs.append("../rtl/priority_encoder.v") 38 | srcs.append("%s.v" % testbench) 39 | 40 | src = ' '.join(srcs) 41 | 42 | build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) 43 | 44 | def bench(): 45 | 46 | # Parameters 47 | ADDR_WIDTH = 32 48 | WBM_DATA_WIDTH = 16 49 | WBM_SELECT_WIDTH = 2 50 | WBS_DATA_WIDTH = 32 51 | WBS_SELECT_WIDTH = 4 52 | 53 | # Inputs 54 | clk = Signal(bool(0)) 55 | rst = Signal(bool(0)) 56 | current_test = Signal(intbv(0)[8:]) 57 | 58 | wbm_adr_i = Signal(intbv(0)[ADDR_WIDTH:]) 59 | wbm_dat_i = Signal(intbv(0)[WBM_DATA_WIDTH:]) 60 | wbm_we_i = Signal(bool(0)) 61 | wbm_sel_i = Signal(intbv(0)[WBM_SELECT_WIDTH:]) 62 | wbm_stb_i = Signal(bool(0)) 63 | wbm_cyc_i = Signal(bool(0)) 64 | wbs_dat_i = Signal(intbv(0)[WBS_DATA_WIDTH:]) 65 | wbs_ack_i = Signal(bool(0)) 66 | wbs_err_i = Signal(bool(0)) 67 | wbs_rty_i = Signal(bool(0)) 68 | 69 | # Outputs 70 | wbm_dat_o = Signal(intbv(0)[WBM_DATA_WIDTH:]) 71 | wbm_ack_o = Signal(bool(0)) 72 | wbm_err_o = Signal(bool(0)) 73 | wbm_rty_o = Signal(bool(0)) 74 | wbs_adr_o = Signal(intbv(0)[ADDR_WIDTH:]) 75 | wbs_dat_o = Signal(intbv(0)[WBS_DATA_WIDTH:]) 76 | wbs_we_o = Signal(bool(0)) 77 | wbs_sel_o = Signal(intbv(0)[WBS_SELECT_WIDTH:]) 78 | wbs_stb_o = Signal(bool(0)) 79 | wbs_cyc_o = Signal(bool(0)) 80 | 81 | # WB master 82 | wbm_inst = wb.WBMaster() 83 | 84 | wbm_logic = wbm_inst.create_logic( 85 | clk, 86 | adr_o=wbm_adr_i, 87 | dat_i=wbm_dat_o, 88 | dat_o=wbm_dat_i, 89 | we_o=wbm_we_i, 90 | sel_o=wbm_sel_i, 91 | stb_o=wbm_stb_i, 92 | ack_i=wbm_ack_o, 93 | cyc_o=wbm_cyc_i, 94 | name='master' 95 | ) 96 | 97 | # WB RAM model 98 | wb_ram_inst = wb.WBRam(2**16) 99 | 100 | wb_ram_port0 = wb_ram_inst.create_port( 101 | clk, 102 | adr_i=wbs_adr_o, 103 | dat_i=wbs_dat_o, 104 | dat_o=wbs_dat_i, 105 | we_i=wbs_we_o, 106 | sel_i=wbs_sel_o, 107 | stb_i=wbs_stb_o, 108 | ack_o=wbs_ack_i, 109 | cyc_i=wbs_cyc_o, 110 | latency=1, 111 | asynchronous=False, 112 | name='slave' 113 | ) 114 | 115 | # DUT 116 | if os.system(build_cmd): 117 | raise Exception("Error running build command") 118 | 119 | dut = Cosimulation( 120 | "vvp -m myhdl %s.vvp -lxt2" % testbench, 121 | clk=clk, 122 | rst=rst, 123 | current_test=current_test, 124 | wbm_adr_i=wbm_adr_i, 125 | wbm_dat_i=wbm_dat_i, 126 | wbm_dat_o=wbm_dat_o, 127 | wbm_we_i=wbm_we_i, 128 | wbm_sel_i=wbm_sel_i, 129 | wbm_stb_i=wbm_stb_i, 130 | wbm_ack_o=wbm_ack_o, 131 | wbm_err_o=wbm_err_o, 132 | wbm_rty_o=wbm_rty_o, 133 | wbm_cyc_i=wbm_cyc_i, 134 | wbs_adr_o=wbs_adr_o, 135 | wbs_dat_i=wbs_dat_i, 136 | wbs_dat_o=wbs_dat_o, 137 | wbs_we_o=wbs_we_o, 138 | wbs_sel_o=wbs_sel_o, 139 | wbs_stb_o=wbs_stb_o, 140 | wbs_ack_i=wbs_ack_i, 141 | wbs_err_i=wbs_err_i, 142 | wbs_rty_i=wbs_rty_i, 143 | wbs_cyc_o=wbs_cyc_o 144 | ) 145 | 146 | @always(delay(4)) 147 | def clkgen(): 148 | clk.next = not clk 149 | 150 | @instance 151 | def check(): 152 | yield delay(100) 153 | yield clk.posedge 154 | rst.next = 1 155 | yield clk.posedge 156 | rst.next = 0 157 | yield clk.posedge 158 | yield delay(100) 159 | yield clk.posedge 160 | 161 | yield clk.posedge 162 | print("test 1: write") 163 | current_test.next = 1 164 | 165 | wbm_inst.init_write(4, b'\x11\x22\x33\x44') 166 | 167 | yield wbm_inst.wait() 168 | yield clk.posedge 169 | 170 | data = wb_ram_inst.read_mem(0, 32) 171 | for i in range(0, len(data), 16): 172 | print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16])))) 173 | 174 | assert wb_ram_inst.read_mem(4,4) == b'\x11\x22\x33\x44' 175 | 176 | yield delay(100) 177 | 178 | yield clk.posedge 179 | print("test 2: read") 180 | current_test.next = 2 181 | 182 | wbm_inst.init_read(4, 4) 183 | 184 | yield wbm_inst.wait() 185 | yield clk.posedge 186 | 187 | data = wbm_inst.get_read_data() 188 | assert data[0] == 4 189 | assert data[1] == b'\x11\x22\x33\x44' 190 | 191 | yield delay(100) 192 | 193 | yield clk.posedge 194 | print("test 3: various writes") 195 | current_test.next = 3 196 | 197 | for length in range(1,8): 198 | for offset in range(4,8): 199 | wb_ram_inst.write_mem(256*(16*offset+length), b'\xAA'*32) 200 | wbm_inst.init_write(256*(16*offset+length)+offset, b'\x11\x22\x33\x44\x55\x66\x77\x88'[0:length]) 201 | 202 | yield wbm_inst.wait() 203 | yield clk.posedge 204 | 205 | data = wb_ram_inst.read_mem(256*(16*offset+length), 32) 206 | for i in range(0, len(data), 16): 207 | print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16])))) 208 | 209 | assert wb_ram_inst.read_mem(256*(16*offset+length)+offset, length) == b'\x11\x22\x33\x44\x55\x66\x77\x88'[0:length] 210 | assert wb_ram_inst.read_mem(256*(16*offset+length)+offset-1, 1) == b'\xAA' 211 | assert wb_ram_inst.read_mem(256*(16*offset+length)+offset+length, 1) == b'\xAA' 212 | 213 | yield delay(100) 214 | 215 | yield clk.posedge 216 | print("test 4: various reads") 217 | current_test.next = 4 218 | 219 | for length in range(1,8): 220 | for offset in range(4,8): 221 | wbm_inst.init_read(256*(16*offset+length)+offset, length) 222 | 223 | yield wbm_inst.wait() 224 | yield clk.posedge 225 | 226 | data = wbm_inst.get_read_data() 227 | assert data[0] == 256*(16*offset+length)+offset 228 | assert data[1] == b'\x11\x22\x33\x44\x55\x66\x77\x88'[0:length] 229 | 230 | yield delay(100) 231 | 232 | raise StopSimulation 233 | 234 | return instances() 235 | 236 | def test_bench(): 237 | sim = Simulation(bench()) 238 | sim.run() 239 | 240 | if __name__ == '__main__': 241 | print("Running test...") 242 | test_bench() 243 | -------------------------------------------------------------------------------- /tb/test_wb_adapter_16_32.v: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2015-2016 Alex Forencich 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | */ 24 | 25 | // Language: Verilog 2001 26 | 27 | `timescale 1ns / 1ps 28 | 29 | /* 30 | * Testbench for wb_adapter 31 | */ 32 | module test_wb_adapter_16_32; 33 | 34 | // Parameters 35 | parameter ADDR_WIDTH = 32; 36 | parameter WBM_DATA_WIDTH = 16; 37 | parameter WBM_SELECT_WIDTH = 2; 38 | parameter WBS_DATA_WIDTH = 32; 39 | parameter WBS_SELECT_WIDTH = 4; 40 | 41 | // Inputs 42 | reg clk = 0; 43 | reg rst = 0; 44 | reg [7:0] current_test = 0; 45 | 46 | reg [ADDR_WIDTH-1:0] wbm_adr_i = 0; 47 | reg [WBM_DATA_WIDTH-1:0] wbm_dat_i = 0; 48 | reg wbm_we_i = 0; 49 | reg [WBM_SELECT_WIDTH-1:0] wbm_sel_i = 0; 50 | reg wbm_stb_i = 0; 51 | reg wbm_cyc_i = 0; 52 | reg [WBS_DATA_WIDTH-1:0] wbs_dat_i = 0; 53 | reg wbs_ack_i = 0; 54 | reg wbs_err_i = 0; 55 | reg wbs_rty_i = 0; 56 | 57 | // Outputs 58 | wire [WBM_DATA_WIDTH-1:0] wbm_dat_o; 59 | wire wbm_ack_o; 60 | wire wbm_err_o; 61 | wire wbm_rty_o; 62 | wire [ADDR_WIDTH-1:0] wbs_adr_o; 63 | wire [WBS_DATA_WIDTH-1:0] wbs_dat_o; 64 | wire wbs_we_o; 65 | wire [WBS_SELECT_WIDTH-1:0] wbs_sel_o; 66 | wire wbs_stb_o; 67 | wire wbs_cyc_o; 68 | 69 | initial begin 70 | // myhdl integration 71 | $from_myhdl( 72 | clk, 73 | rst, 74 | current_test, 75 | wbm_adr_i, 76 | wbm_dat_i, 77 | wbm_we_i, 78 | wbm_sel_i, 79 | wbm_stb_i, 80 | wbm_cyc_i, 81 | wbs_dat_i, 82 | wbs_ack_i, 83 | wbs_err_i, 84 | wbs_rty_i 85 | ); 86 | $to_myhdl( 87 | wbm_dat_o, 88 | wbm_ack_o, 89 | wbm_err_o, 90 | wbm_rty_o, 91 | wbs_adr_o, 92 | wbs_dat_o, 93 | wbs_we_o, 94 | wbs_sel_o, 95 | wbs_stb_o, 96 | wbs_cyc_o 97 | ); 98 | 99 | // dump file 100 | $dumpfile("test_wb_adapter_16_32.lxt"); 101 | $dumpvars(0, test_wb_adapter_16_32); 102 | end 103 | 104 | wb_adapter #( 105 | .ADDR_WIDTH(ADDR_WIDTH), 106 | .WBM_DATA_WIDTH(WBM_DATA_WIDTH), 107 | .WBM_SELECT_WIDTH(WBM_SELECT_WIDTH), 108 | .WBS_DATA_WIDTH(WBS_DATA_WIDTH), 109 | .WBS_SELECT_WIDTH(WBS_SELECT_WIDTH) 110 | ) 111 | UUT ( 112 | .clk(clk), 113 | .rst(rst), 114 | .wbm_adr_i(wbm_adr_i), 115 | .wbm_dat_i(wbm_dat_i), 116 | .wbm_dat_o(wbm_dat_o), 117 | .wbm_we_i(wbm_we_i), 118 | .wbm_sel_i(wbm_sel_i), 119 | .wbm_stb_i(wbm_stb_i), 120 | .wbm_ack_o(wbm_ack_o), 121 | .wbm_err_o(wbm_err_o), 122 | .wbm_rty_o(wbm_rty_o), 123 | .wbm_cyc_i(wbm_cyc_i), 124 | .wbs_adr_o(wbs_adr_o), 125 | .wbs_dat_i(wbs_dat_i), 126 | .wbs_dat_o(wbs_dat_o), 127 | .wbs_we_o(wbs_we_o), 128 | .wbs_sel_o(wbs_sel_o), 129 | .wbs_stb_o(wbs_stb_o), 130 | .wbs_ack_i(wbs_ack_i), 131 | .wbs_err_i(wbs_err_i), 132 | .wbs_rty_i(wbs_rty_i), 133 | .wbs_cyc_o(wbs_cyc_o) 134 | ); 135 | 136 | endmodule 137 | -------------------------------------------------------------------------------- /tb/test_wb_adapter_32_16.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | 4 | Copyright (c) 2015-2016 Alex Forencich 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | 24 | """ 25 | 26 | from myhdl import * 27 | import os 28 | 29 | import wb 30 | 31 | module = 'wb_adapter' 32 | testbench = 'test_%s_32_16' % module 33 | 34 | srcs = [] 35 | 36 | srcs.append("../rtl/%s.v" % module) 37 | srcs.append("../rtl/priority_encoder.v") 38 | srcs.append("%s.v" % testbench) 39 | 40 | src = ' '.join(srcs) 41 | 42 | build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) 43 | 44 | def bench(): 45 | 46 | # Parameters 47 | ADDR_WIDTH = 32 48 | WBM_DATA_WIDTH = 32 49 | WBM_SELECT_WIDTH = 4 50 | WBS_DATA_WIDTH = 16 51 | WBS_SELECT_WIDTH = 2 52 | 53 | # Inputs 54 | clk = Signal(bool(0)) 55 | rst = Signal(bool(0)) 56 | current_test = Signal(intbv(0)[8:]) 57 | 58 | wbm_adr_i = Signal(intbv(0)[ADDR_WIDTH:]) 59 | wbm_dat_i = Signal(intbv(0)[WBM_DATA_WIDTH:]) 60 | wbm_we_i = Signal(bool(0)) 61 | wbm_sel_i = Signal(intbv(0)[WBM_SELECT_WIDTH:]) 62 | wbm_stb_i = Signal(bool(0)) 63 | wbm_cyc_i = Signal(bool(0)) 64 | wbs_dat_i = Signal(intbv(0)[WBS_DATA_WIDTH:]) 65 | wbs_ack_i = Signal(bool(0)) 66 | wbs_err_i = Signal(bool(0)) 67 | wbs_rty_i = Signal(bool(0)) 68 | 69 | # Outputs 70 | wbm_dat_o = Signal(intbv(0)[WBM_DATA_WIDTH:]) 71 | wbm_ack_o = Signal(bool(0)) 72 | wbm_err_o = Signal(bool(0)) 73 | wbm_rty_o = Signal(bool(0)) 74 | wbs_adr_o = Signal(intbv(0)[ADDR_WIDTH:]) 75 | wbs_dat_o = Signal(intbv(0)[WBS_DATA_WIDTH:]) 76 | wbs_we_o = Signal(bool(0)) 77 | wbs_sel_o = Signal(intbv(0)[WBS_SELECT_WIDTH:]) 78 | wbs_stb_o = Signal(bool(0)) 79 | wbs_cyc_o = Signal(bool(0)) 80 | 81 | # WB master 82 | wbm_inst = wb.WBMaster() 83 | 84 | wbm_logic = wbm_inst.create_logic( 85 | clk, 86 | adr_o=wbm_adr_i, 87 | dat_i=wbm_dat_o, 88 | dat_o=wbm_dat_i, 89 | we_o=wbm_we_i, 90 | sel_o=wbm_sel_i, 91 | stb_o=wbm_stb_i, 92 | ack_i=wbm_ack_o, 93 | cyc_o=wbm_cyc_i, 94 | name='master' 95 | ) 96 | 97 | # WB RAM model 98 | wb_ram_inst = wb.WBRam(2**16) 99 | 100 | wb_ram_port0 = wb_ram_inst.create_port( 101 | clk, 102 | adr_i=wbs_adr_o, 103 | dat_i=wbs_dat_o, 104 | dat_o=wbs_dat_i, 105 | we_i=wbs_we_o, 106 | sel_i=wbs_sel_o, 107 | stb_i=wbs_stb_o, 108 | ack_o=wbs_ack_i, 109 | cyc_i=wbs_cyc_o, 110 | latency=1, 111 | asynchronous=False, 112 | name='slave' 113 | ) 114 | 115 | # DUT 116 | if os.system(build_cmd): 117 | raise Exception("Error running build command") 118 | 119 | dut = Cosimulation( 120 | "vvp -m myhdl %s.vvp -lxt2" % testbench, 121 | clk=clk, 122 | rst=rst, 123 | current_test=current_test, 124 | wbm_adr_i=wbm_adr_i, 125 | wbm_dat_i=wbm_dat_i, 126 | wbm_dat_o=wbm_dat_o, 127 | wbm_we_i=wbm_we_i, 128 | wbm_sel_i=wbm_sel_i, 129 | wbm_stb_i=wbm_stb_i, 130 | wbm_ack_o=wbm_ack_o, 131 | wbm_err_o=wbm_err_o, 132 | wbm_rty_o=wbm_rty_o, 133 | wbm_cyc_i=wbm_cyc_i, 134 | wbs_adr_o=wbs_adr_o, 135 | wbs_dat_i=wbs_dat_i, 136 | wbs_dat_o=wbs_dat_o, 137 | wbs_we_o=wbs_we_o, 138 | wbs_sel_o=wbs_sel_o, 139 | wbs_stb_o=wbs_stb_o, 140 | wbs_ack_i=wbs_ack_i, 141 | wbs_err_i=wbs_err_i, 142 | wbs_rty_i=wbs_rty_i, 143 | wbs_cyc_o=wbs_cyc_o 144 | ) 145 | 146 | @always(delay(4)) 147 | def clkgen(): 148 | clk.next = not clk 149 | 150 | @instance 151 | def check(): 152 | yield delay(100) 153 | yield clk.posedge 154 | rst.next = 1 155 | yield clk.posedge 156 | rst.next = 0 157 | yield clk.posedge 158 | yield delay(100) 159 | yield clk.posedge 160 | 161 | yield clk.posedge 162 | print("test 1: write") 163 | current_test.next = 1 164 | 165 | wbm_inst.init_write(4, b'\x11\x22\x33\x44') 166 | 167 | yield wbm_inst.wait() 168 | yield clk.posedge 169 | 170 | data = wb_ram_inst.read_mem(0, 32) 171 | for i in range(0, len(data), 16): 172 | print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16])))) 173 | 174 | assert wb_ram_inst.read_mem(4,4) == b'\x11\x22\x33\x44' 175 | 176 | yield delay(100) 177 | 178 | yield clk.posedge 179 | print("test 2: read") 180 | current_test.next = 2 181 | 182 | wbm_inst.init_read(4, 4) 183 | 184 | yield wbm_inst.wait() 185 | yield clk.posedge 186 | 187 | data = wbm_inst.get_read_data() 188 | assert data[0] == 4 189 | assert data[1] == b'\x11\x22\x33\x44' 190 | 191 | yield delay(100) 192 | 193 | yield clk.posedge 194 | print("test 3: various writes") 195 | current_test.next = 3 196 | 197 | for length in range(1,8): 198 | for offset in range(4,8): 199 | wb_ram_inst.write_mem(256*(16*offset+length), b'\xAA'*32) 200 | wbm_inst.init_write(256*(16*offset+length)+offset, b'\x11\x22\x33\x44\x55\x66\x77\x88'[0:length]) 201 | 202 | yield wbm_inst.wait() 203 | yield clk.posedge 204 | 205 | data = wb_ram_inst.read_mem(256*(16*offset+length), 32) 206 | for i in range(0, len(data), 16): 207 | print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16])))) 208 | 209 | assert wb_ram_inst.read_mem(256*(16*offset+length)+offset, length) == b'\x11\x22\x33\x44\x55\x66\x77\x88'[0:length] 210 | assert wb_ram_inst.read_mem(256*(16*offset+length)+offset-1, 1) == b'\xAA' 211 | assert wb_ram_inst.read_mem(256*(16*offset+length)+offset+length, 1) == b'\xAA' 212 | 213 | yield delay(100) 214 | 215 | yield clk.posedge 216 | print("test 4: various reads") 217 | current_test.next = 4 218 | 219 | for length in range(1,8): 220 | for offset in range(4,8): 221 | wbm_inst.init_read(256*(16*offset+length)+offset, length) 222 | 223 | yield wbm_inst.wait() 224 | yield clk.posedge 225 | 226 | data = wbm_inst.get_read_data() 227 | assert data[0] == 256*(16*offset+length)+offset 228 | assert data[1] == b'\x11\x22\x33\x44\x55\x66\x77\x88'[0:length] 229 | 230 | yield delay(100) 231 | 232 | raise StopSimulation 233 | 234 | return instances() 235 | 236 | def test_bench(): 237 | sim = Simulation(bench()) 238 | sim.run() 239 | 240 | if __name__ == '__main__': 241 | print("Running test...") 242 | test_bench() 243 | -------------------------------------------------------------------------------- /tb/test_wb_adapter_32_16.v: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2015-2016 Alex Forencich 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | */ 24 | 25 | // Language: Verilog 2001 26 | 27 | `timescale 1ns / 1ps 28 | 29 | /* 30 | * Testbench for wb_adapter 31 | */ 32 | module test_wb_adapter_32_16; 33 | 34 | // Parameters 35 | parameter ADDR_WIDTH = 32; 36 | parameter WBM_DATA_WIDTH = 32; 37 | parameter WBM_SELECT_WIDTH = 4; 38 | parameter WBS_DATA_WIDTH = 16; 39 | parameter WBS_SELECT_WIDTH = 2; 40 | 41 | // Inputs 42 | reg clk = 0; 43 | reg rst = 0; 44 | reg [7:0] current_test = 0; 45 | 46 | reg [ADDR_WIDTH-1:0] wbm_adr_i = 0; 47 | reg [WBM_DATA_WIDTH-1:0] wbm_dat_i = 0; 48 | reg wbm_we_i = 0; 49 | reg [WBM_SELECT_WIDTH-1:0] wbm_sel_i = 0; 50 | reg wbm_stb_i = 0; 51 | reg wbm_cyc_i = 0; 52 | reg [WBS_DATA_WIDTH-1:0] wbs_dat_i = 0; 53 | reg wbs_ack_i = 0; 54 | reg wbs_err_i = 0; 55 | reg wbs_rty_i = 0; 56 | 57 | // Outputs 58 | wire [WBM_DATA_WIDTH-1:0] wbm_dat_o; 59 | wire wbm_ack_o; 60 | wire wbm_err_o; 61 | wire wbm_rty_o; 62 | wire [ADDR_WIDTH-1:0] wbs_adr_o; 63 | wire [WBS_DATA_WIDTH-1:0] wbs_dat_o; 64 | wire wbs_we_o; 65 | wire [WBS_SELECT_WIDTH-1:0] wbs_sel_o; 66 | wire wbs_stb_o; 67 | wire wbs_cyc_o; 68 | 69 | initial begin 70 | // myhdl integration 71 | $from_myhdl( 72 | clk, 73 | rst, 74 | current_test, 75 | wbm_adr_i, 76 | wbm_dat_i, 77 | wbm_we_i, 78 | wbm_sel_i, 79 | wbm_stb_i, 80 | wbm_cyc_i, 81 | wbs_dat_i, 82 | wbs_ack_i, 83 | wbs_err_i, 84 | wbs_rty_i 85 | ); 86 | $to_myhdl( 87 | wbm_dat_o, 88 | wbm_ack_o, 89 | wbm_err_o, 90 | wbm_rty_o, 91 | wbs_adr_o, 92 | wbs_dat_o, 93 | wbs_we_o, 94 | wbs_sel_o, 95 | wbs_stb_o, 96 | wbs_cyc_o 97 | ); 98 | 99 | // dump file 100 | $dumpfile("test_wb_adapter_32_16.lxt"); 101 | $dumpvars(0, test_wb_adapter_32_16); 102 | end 103 | 104 | wb_adapter #( 105 | .ADDR_WIDTH(ADDR_WIDTH), 106 | .WBM_DATA_WIDTH(WBM_DATA_WIDTH), 107 | .WBM_SELECT_WIDTH(WBM_SELECT_WIDTH), 108 | .WBS_DATA_WIDTH(WBS_DATA_WIDTH), 109 | .WBS_SELECT_WIDTH(WBS_SELECT_WIDTH) 110 | ) 111 | UUT ( 112 | .clk(clk), 113 | .rst(rst), 114 | .wbm_adr_i(wbm_adr_i), 115 | .wbm_dat_i(wbm_dat_i), 116 | .wbm_dat_o(wbm_dat_o), 117 | .wbm_we_i(wbm_we_i), 118 | .wbm_sel_i(wbm_sel_i), 119 | .wbm_stb_i(wbm_stb_i), 120 | .wbm_ack_o(wbm_ack_o), 121 | .wbm_err_o(wbm_err_o), 122 | .wbm_rty_o(wbm_rty_o), 123 | .wbm_cyc_i(wbm_cyc_i), 124 | .wbs_adr_o(wbs_adr_o), 125 | .wbs_dat_i(wbs_dat_i), 126 | .wbs_dat_o(wbs_dat_o), 127 | .wbs_we_o(wbs_we_o), 128 | .wbs_sel_o(wbs_sel_o), 129 | .wbs_stb_o(wbs_stb_o), 130 | .wbs_ack_i(wbs_ack_i), 131 | .wbs_err_i(wbs_err_i), 132 | .wbs_rty_i(wbs_rty_i), 133 | .wbs_cyc_o(wbs_cyc_o) 134 | ); 135 | 136 | endmodule 137 | -------------------------------------------------------------------------------- /tb/test_wb_adapter_32_8.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | 4 | Copyright (c) 2015-2016 Alex Forencich 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | 24 | """ 25 | 26 | from myhdl import * 27 | import os 28 | 29 | import wb 30 | 31 | module = 'wb_adapter' 32 | testbench = 'test_%s_32_8' % module 33 | 34 | srcs = [] 35 | 36 | srcs.append("../rtl/%s.v" % module) 37 | srcs.append("../rtl/priority_encoder.v") 38 | srcs.append("%s.v" % testbench) 39 | 40 | src = ' '.join(srcs) 41 | 42 | build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) 43 | 44 | def bench(): 45 | 46 | # Parameters 47 | ADDR_WIDTH = 32 48 | WBM_DATA_WIDTH = 32 49 | WBM_SELECT_WIDTH = 4 50 | WBS_DATA_WIDTH = 8 51 | WBS_SELECT_WIDTH = 1 52 | 53 | # Inputs 54 | clk = Signal(bool(0)) 55 | rst = Signal(bool(0)) 56 | current_test = Signal(intbv(0)[8:]) 57 | 58 | wbm_adr_i = Signal(intbv(0)[ADDR_WIDTH:]) 59 | wbm_dat_i = Signal(intbv(0)[WBM_DATA_WIDTH:]) 60 | wbm_we_i = Signal(bool(0)) 61 | wbm_sel_i = Signal(intbv(0)[WBM_SELECT_WIDTH:]) 62 | wbm_stb_i = Signal(bool(0)) 63 | wbm_cyc_i = Signal(bool(0)) 64 | wbs_dat_i = Signal(intbv(0)[WBS_DATA_WIDTH:]) 65 | wbs_ack_i = Signal(bool(0)) 66 | wbs_err_i = Signal(bool(0)) 67 | wbs_rty_i = Signal(bool(0)) 68 | 69 | # Outputs 70 | wbm_dat_o = Signal(intbv(0)[WBM_DATA_WIDTH:]) 71 | wbm_ack_o = Signal(bool(0)) 72 | wbm_err_o = Signal(bool(0)) 73 | wbm_rty_o = Signal(bool(0)) 74 | wbs_adr_o = Signal(intbv(0)[ADDR_WIDTH:]) 75 | wbs_dat_o = Signal(intbv(0)[WBS_DATA_WIDTH:]) 76 | wbs_we_o = Signal(bool(0)) 77 | wbs_sel_o = Signal(intbv(0)[WBS_SELECT_WIDTH:]) 78 | wbs_stb_o = Signal(bool(0)) 79 | wbs_cyc_o = Signal(bool(0)) 80 | 81 | # WB master 82 | wbm_inst = wb.WBMaster() 83 | 84 | wbm_logic = wbm_inst.create_logic( 85 | clk, 86 | adr_o=wbm_adr_i, 87 | dat_i=wbm_dat_o, 88 | dat_o=wbm_dat_i, 89 | we_o=wbm_we_i, 90 | sel_o=wbm_sel_i, 91 | stb_o=wbm_stb_i, 92 | ack_i=wbm_ack_o, 93 | cyc_o=wbm_cyc_i, 94 | name='master' 95 | ) 96 | 97 | # WB RAM model 98 | wb_ram_inst = wb.WBRam(2**16) 99 | 100 | wb_ram_port0 = wb_ram_inst.create_port( 101 | clk, 102 | adr_i=wbs_adr_o, 103 | dat_i=wbs_dat_o, 104 | dat_o=wbs_dat_i, 105 | we_i=wbs_we_o, 106 | sel_i=wbs_sel_o, 107 | stb_i=wbs_stb_o, 108 | ack_o=wbs_ack_i, 109 | cyc_i=wbs_cyc_o, 110 | latency=1, 111 | asynchronous=False, 112 | name='slave' 113 | ) 114 | 115 | # DUT 116 | if os.system(build_cmd): 117 | raise Exception("Error running build command") 118 | 119 | dut = Cosimulation( 120 | "vvp -m myhdl %s.vvp -lxt2" % testbench, 121 | clk=clk, 122 | rst=rst, 123 | current_test=current_test, 124 | wbm_adr_i=wbm_adr_i, 125 | wbm_dat_i=wbm_dat_i, 126 | wbm_dat_o=wbm_dat_o, 127 | wbm_we_i=wbm_we_i, 128 | wbm_sel_i=wbm_sel_i, 129 | wbm_stb_i=wbm_stb_i, 130 | wbm_ack_o=wbm_ack_o, 131 | wbm_err_o=wbm_err_o, 132 | wbm_rty_o=wbm_rty_o, 133 | wbm_cyc_i=wbm_cyc_i, 134 | wbs_adr_o=wbs_adr_o, 135 | wbs_dat_i=wbs_dat_i, 136 | wbs_dat_o=wbs_dat_o, 137 | wbs_we_o=wbs_we_o, 138 | wbs_sel_o=wbs_sel_o, 139 | wbs_stb_o=wbs_stb_o, 140 | wbs_ack_i=wbs_ack_i, 141 | wbs_err_i=wbs_err_i, 142 | wbs_rty_i=wbs_rty_i, 143 | wbs_cyc_o=wbs_cyc_o 144 | ) 145 | 146 | @always(delay(4)) 147 | def clkgen(): 148 | clk.next = not clk 149 | 150 | @instance 151 | def check(): 152 | yield delay(100) 153 | yield clk.posedge 154 | rst.next = 1 155 | yield clk.posedge 156 | rst.next = 0 157 | yield clk.posedge 158 | yield delay(100) 159 | yield clk.posedge 160 | 161 | yield clk.posedge 162 | print("test 1: write") 163 | current_test.next = 1 164 | 165 | wbm_inst.init_write(4, b'\x11\x22\x33\x44') 166 | 167 | yield wbm_inst.wait() 168 | yield clk.posedge 169 | 170 | data = wb_ram_inst.read_mem(0, 32) 171 | for i in range(0, len(data), 16): 172 | print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16])))) 173 | 174 | assert wb_ram_inst.read_mem(4,4) == b'\x11\x22\x33\x44' 175 | 176 | yield delay(100) 177 | 178 | yield clk.posedge 179 | print("test 2: read") 180 | current_test.next = 2 181 | 182 | wbm_inst.init_read(4, 4) 183 | 184 | yield wbm_inst.wait() 185 | yield clk.posedge 186 | 187 | data = wbm_inst.get_read_data() 188 | assert data[0] == 4 189 | assert data[1] == b'\x11\x22\x33\x44' 190 | 191 | yield delay(100) 192 | 193 | yield clk.posedge 194 | print("test 3: various writes") 195 | current_test.next = 3 196 | 197 | for length in range(1,8): 198 | for offset in range(4,8): 199 | wb_ram_inst.write_mem(256*(16*offset+length), b'\xAA'*16) 200 | wbm_inst.init_write(256*(16*offset+length)+offset, b'\x11\x22\x33\x44\x55\x66\x77\x88'[0:length]) 201 | 202 | yield wbm_inst.wait() 203 | yield clk.posedge 204 | 205 | data = wb_ram_inst.read_mem(256*(16*offset+length), 32) 206 | for i in range(0, len(data), 16): 207 | print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16])))) 208 | 209 | assert wb_ram_inst.read_mem(256*(16*offset+length)+offset, length) == b'\x11\x22\x33\x44\x55\x66\x77\x88'[0:length] 210 | assert wb_ram_inst.read_mem(256*(16*offset+length)+offset-1, 1) == b'\xAA' 211 | assert wb_ram_inst.read_mem(256*(16*offset+length)+offset+length, 1) == b'\xAA' 212 | 213 | yield delay(100) 214 | 215 | yield clk.posedge 216 | print("test 4: various reads") 217 | current_test.next = 4 218 | 219 | for length in range(1,8): 220 | for offset in range(4,8): 221 | wbm_inst.init_read(256*(16*offset+length)+offset, length) 222 | 223 | yield wbm_inst.wait() 224 | yield clk.posedge 225 | 226 | data = wbm_inst.get_read_data() 227 | assert data[0] == 256*(16*offset+length)+offset 228 | assert data[1] == b'\x11\x22\x33\x44\x55\x66\x77\x88'[0:length] 229 | 230 | yield delay(100) 231 | 232 | raise StopSimulation 233 | 234 | return instances() 235 | 236 | def test_bench(): 237 | sim = Simulation(bench()) 238 | sim.run() 239 | 240 | if __name__ == '__main__': 241 | print("Running test...") 242 | test_bench() 243 | -------------------------------------------------------------------------------- /tb/test_wb_adapter_32_8.v: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2015-2016 Alex Forencich 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | */ 24 | 25 | // Language: Verilog 2001 26 | 27 | `timescale 1ns / 1ps 28 | 29 | /* 30 | * Testbench for wb_adapter 31 | */ 32 | module test_wb_adapter_32_8; 33 | 34 | // Parameters 35 | parameter ADDR_WIDTH = 32; 36 | parameter WBM_DATA_WIDTH = 32; 37 | parameter WBM_SELECT_WIDTH = 4; 38 | parameter WBS_DATA_WIDTH = 8; 39 | parameter WBS_SELECT_WIDTH = 1; 40 | 41 | // Inputs 42 | reg clk = 0; 43 | reg rst = 0; 44 | reg [7:0] current_test = 0; 45 | 46 | reg [ADDR_WIDTH-1:0] wbm_adr_i = 0; 47 | reg [WBM_DATA_WIDTH-1:0] wbm_dat_i = 0; 48 | reg wbm_we_i = 0; 49 | reg [WBM_SELECT_WIDTH-1:0] wbm_sel_i = 0; 50 | reg wbm_stb_i = 0; 51 | reg wbm_cyc_i = 0; 52 | reg [WBS_DATA_WIDTH-1:0] wbs_dat_i = 0; 53 | reg wbs_ack_i = 0; 54 | reg wbs_err_i = 0; 55 | reg wbs_rty_i = 0; 56 | 57 | // Outputs 58 | wire [WBM_DATA_WIDTH-1:0] wbm_dat_o; 59 | wire wbm_ack_o; 60 | wire wbm_err_o; 61 | wire wbm_rty_o; 62 | wire [ADDR_WIDTH-1:0] wbs_adr_o; 63 | wire [WBS_DATA_WIDTH-1:0] wbs_dat_o; 64 | wire wbs_we_o; 65 | wire [WBS_SELECT_WIDTH-1:0] wbs_sel_o; 66 | wire wbs_stb_o; 67 | wire wbs_cyc_o; 68 | 69 | initial begin 70 | // myhdl integration 71 | $from_myhdl( 72 | clk, 73 | rst, 74 | current_test, 75 | wbm_adr_i, 76 | wbm_dat_i, 77 | wbm_we_i, 78 | wbm_sel_i, 79 | wbm_stb_i, 80 | wbm_cyc_i, 81 | wbs_dat_i, 82 | wbs_ack_i, 83 | wbs_err_i, 84 | wbs_rty_i 85 | ); 86 | $to_myhdl( 87 | wbm_dat_o, 88 | wbm_ack_o, 89 | wbm_err_o, 90 | wbm_rty_o, 91 | wbs_adr_o, 92 | wbs_dat_o, 93 | wbs_we_o, 94 | wbs_sel_o, 95 | wbs_stb_o, 96 | wbs_cyc_o 97 | ); 98 | 99 | // dump file 100 | $dumpfile("test_wb_adapter_32_8.lxt"); 101 | $dumpvars(0, test_wb_adapter_32_8); 102 | end 103 | 104 | wb_adapter #( 105 | .ADDR_WIDTH(ADDR_WIDTH), 106 | .WBM_DATA_WIDTH(WBM_DATA_WIDTH), 107 | .WBM_SELECT_WIDTH(WBM_SELECT_WIDTH), 108 | .WBS_DATA_WIDTH(WBS_DATA_WIDTH), 109 | .WBS_SELECT_WIDTH(WBS_SELECT_WIDTH) 110 | ) 111 | UUT ( 112 | .clk(clk), 113 | .rst(rst), 114 | .wbm_adr_i(wbm_adr_i), 115 | .wbm_dat_i(wbm_dat_i), 116 | .wbm_dat_o(wbm_dat_o), 117 | .wbm_we_i(wbm_we_i), 118 | .wbm_sel_i(wbm_sel_i), 119 | .wbm_stb_i(wbm_stb_i), 120 | .wbm_ack_o(wbm_ack_o), 121 | .wbm_err_o(wbm_err_o), 122 | .wbm_rty_o(wbm_rty_o), 123 | .wbm_cyc_i(wbm_cyc_i), 124 | .wbs_adr_o(wbs_adr_o), 125 | .wbs_dat_i(wbs_dat_i), 126 | .wbs_dat_o(wbs_dat_o), 127 | .wbs_we_o(wbs_we_o), 128 | .wbs_sel_o(wbs_sel_o), 129 | .wbs_stb_o(wbs_stb_o), 130 | .wbs_ack_i(wbs_ack_i), 131 | .wbs_err_i(wbs_err_i), 132 | .wbs_rty_i(wbs_rty_i), 133 | .wbs_cyc_o(wbs_cyc_o) 134 | ); 135 | 136 | endmodule 137 | -------------------------------------------------------------------------------- /tb/test_wb_adapter_8_32.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | 4 | Copyright (c) 2015-2016 Alex Forencich 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | 24 | """ 25 | 26 | from myhdl import * 27 | import os 28 | 29 | import wb 30 | 31 | module = 'wb_adapter' 32 | testbench = 'test_%s_8_32' % module 33 | 34 | srcs = [] 35 | 36 | srcs.append("../rtl/%s.v" % module) 37 | srcs.append("../rtl/priority_encoder.v") 38 | srcs.append("%s.v" % testbench) 39 | 40 | src = ' '.join(srcs) 41 | 42 | build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) 43 | 44 | def bench(): 45 | 46 | # Parameters 47 | ADDR_WIDTH = 32 48 | WBM_DATA_WIDTH = 8 49 | WBM_SELECT_WIDTH = 1 50 | WBS_DATA_WIDTH = 32 51 | WBS_SELECT_WIDTH = 4 52 | 53 | # Inputs 54 | clk = Signal(bool(0)) 55 | rst = Signal(bool(0)) 56 | current_test = Signal(intbv(0)[8:]) 57 | 58 | wbm_adr_i = Signal(intbv(0)[ADDR_WIDTH:]) 59 | wbm_dat_i = Signal(intbv(0)[WBM_DATA_WIDTH:]) 60 | wbm_we_i = Signal(bool(0)) 61 | wbm_sel_i = Signal(intbv(0)[WBM_SELECT_WIDTH:]) 62 | wbm_stb_i = Signal(bool(0)) 63 | wbm_cyc_i = Signal(bool(0)) 64 | wbs_dat_i = Signal(intbv(0)[WBS_DATA_WIDTH:]) 65 | wbs_ack_i = Signal(bool(0)) 66 | wbs_err_i = Signal(bool(0)) 67 | wbs_rty_i = Signal(bool(0)) 68 | 69 | # Outputs 70 | wbm_dat_o = Signal(intbv(0)[WBM_DATA_WIDTH:]) 71 | wbm_ack_o = Signal(bool(0)) 72 | wbm_err_o = Signal(bool(0)) 73 | wbm_rty_o = Signal(bool(0)) 74 | wbs_adr_o = Signal(intbv(0)[ADDR_WIDTH:]) 75 | wbs_dat_o = Signal(intbv(0)[WBS_DATA_WIDTH:]) 76 | wbs_we_o = Signal(bool(0)) 77 | wbs_sel_o = Signal(intbv(0)[WBS_SELECT_WIDTH:]) 78 | wbs_stb_o = Signal(bool(0)) 79 | wbs_cyc_o = Signal(bool(0)) 80 | 81 | # WB master 82 | wbm_inst = wb.WBMaster() 83 | 84 | wbm_logic = wbm_inst.create_logic( 85 | clk, 86 | adr_o=wbm_adr_i, 87 | dat_i=wbm_dat_o, 88 | dat_o=wbm_dat_i, 89 | we_o=wbm_we_i, 90 | sel_o=wbm_sel_i, 91 | stb_o=wbm_stb_i, 92 | ack_i=wbm_ack_o, 93 | cyc_o=wbm_cyc_i, 94 | name='master' 95 | ) 96 | 97 | # WB RAM model 98 | wb_ram_inst = wb.WBRam(2**16) 99 | 100 | wb_ram_port0 = wb_ram_inst.create_port( 101 | clk, 102 | adr_i=wbs_adr_o, 103 | dat_i=wbs_dat_o, 104 | dat_o=wbs_dat_i, 105 | we_i=wbs_we_o, 106 | sel_i=wbs_sel_o, 107 | stb_i=wbs_stb_o, 108 | ack_o=wbs_ack_i, 109 | cyc_i=wbs_cyc_o, 110 | latency=1, 111 | asynchronous=False, 112 | name='slave' 113 | ) 114 | 115 | # DUT 116 | if os.system(build_cmd): 117 | raise Exception("Error running build command") 118 | 119 | dut = Cosimulation( 120 | "vvp -m myhdl %s.vvp -lxt2" % testbench, 121 | clk=clk, 122 | rst=rst, 123 | current_test=current_test, 124 | wbm_adr_i=wbm_adr_i, 125 | wbm_dat_i=wbm_dat_i, 126 | wbm_dat_o=wbm_dat_o, 127 | wbm_we_i=wbm_we_i, 128 | wbm_sel_i=wbm_sel_i, 129 | wbm_stb_i=wbm_stb_i, 130 | wbm_ack_o=wbm_ack_o, 131 | wbm_err_o=wbm_err_o, 132 | wbm_rty_o=wbm_rty_o, 133 | wbm_cyc_i=wbm_cyc_i, 134 | wbs_adr_o=wbs_adr_o, 135 | wbs_dat_i=wbs_dat_i, 136 | wbs_dat_o=wbs_dat_o, 137 | wbs_we_o=wbs_we_o, 138 | wbs_sel_o=wbs_sel_o, 139 | wbs_stb_o=wbs_stb_o, 140 | wbs_ack_i=wbs_ack_i, 141 | wbs_err_i=wbs_err_i, 142 | wbs_rty_i=wbs_rty_i, 143 | wbs_cyc_o=wbs_cyc_o 144 | ) 145 | 146 | @always(delay(4)) 147 | def clkgen(): 148 | clk.next = not clk 149 | 150 | @instance 151 | def check(): 152 | yield delay(100) 153 | yield clk.posedge 154 | rst.next = 1 155 | yield clk.posedge 156 | rst.next = 0 157 | yield clk.posedge 158 | yield delay(100) 159 | yield clk.posedge 160 | 161 | yield clk.posedge 162 | print("test 1: write") 163 | current_test.next = 1 164 | 165 | wbm_inst.init_write(4, b'\x11\x22\x33\x44') 166 | 167 | yield wbm_inst.wait() 168 | yield clk.posedge 169 | 170 | data = wb_ram_inst.read_mem(0, 32) 171 | for i in range(0, len(data), 16): 172 | print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16])))) 173 | 174 | assert wb_ram_inst.read_mem(4,4) == b'\x11\x22\x33\x44' 175 | 176 | yield delay(100) 177 | 178 | yield clk.posedge 179 | print("test 2: read") 180 | current_test.next = 2 181 | 182 | wbm_inst.init_read(4, 4) 183 | 184 | yield wbm_inst.wait() 185 | yield clk.posedge 186 | 187 | data = wbm_inst.get_read_data() 188 | assert data[0] == 4 189 | assert data[1] == b'\x11\x22\x33\x44' 190 | 191 | yield delay(100) 192 | 193 | yield clk.posedge 194 | print("test 3: various writes") 195 | current_test.next = 3 196 | 197 | for length in range(1,8): 198 | for offset in range(4,8): 199 | wb_ram_inst.write_mem(256*(16*offset+length), b'\xAA'*16) 200 | wbm_inst.init_write(256*(16*offset+length)+offset, b'\x11\x22\x33\x44\x55\x66\x77\x88'[0:length]) 201 | 202 | yield wbm_inst.wait() 203 | yield clk.posedge 204 | 205 | data = wb_ram_inst.read_mem(256*(16*offset+length), 32) 206 | for i in range(0, len(data), 16): 207 | print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16])))) 208 | 209 | assert wb_ram_inst.read_mem(256*(16*offset+length)+offset, length) == b'\x11\x22\x33\x44\x55\x66\x77\x88'[0:length] 210 | assert wb_ram_inst.read_mem(256*(16*offset+length)+offset-1, 1) == b'\xAA' 211 | assert wb_ram_inst.read_mem(256*(16*offset+length)+offset+length, 1) == b'\xAA' 212 | 213 | yield delay(100) 214 | 215 | yield clk.posedge 216 | print("test 4: various reads") 217 | current_test.next = 4 218 | 219 | for length in range(1,8): 220 | for offset in range(4,8): 221 | wbm_inst.init_read(256*(16*offset+length)+offset, length) 222 | 223 | yield wbm_inst.wait() 224 | yield clk.posedge 225 | 226 | data = wbm_inst.get_read_data() 227 | assert data[0] == 256*(16*offset+length)+offset 228 | assert data[1] == b'\x11\x22\x33\x44\x55\x66\x77\x88'[0:length] 229 | 230 | yield delay(100) 231 | 232 | raise StopSimulation 233 | 234 | return instances() 235 | 236 | def test_bench(): 237 | sim = Simulation(bench()) 238 | sim.run() 239 | 240 | if __name__ == '__main__': 241 | print("Running test...") 242 | test_bench() 243 | -------------------------------------------------------------------------------- /tb/test_wb_adapter_8_32.v: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2015-2016 Alex Forencich 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | */ 24 | 25 | // Language: Verilog 2001 26 | 27 | `timescale 1ns / 1ps 28 | 29 | /* 30 | * Testbench for wb_adapter 31 | */ 32 | module test_wb_adapter_8_32; 33 | 34 | // Parameters 35 | parameter ADDR_WIDTH = 32; 36 | parameter WBM_DATA_WIDTH = 8; 37 | parameter WBM_SELECT_WIDTH = 1; 38 | parameter WBS_DATA_WIDTH = 32; 39 | parameter WBS_SELECT_WIDTH = 4; 40 | 41 | // Inputs 42 | reg clk = 0; 43 | reg rst = 0; 44 | reg [7:0] current_test = 0; 45 | 46 | reg [ADDR_WIDTH-1:0] wbm_adr_i = 0; 47 | reg [WBM_DATA_WIDTH-1:0] wbm_dat_i = 0; 48 | reg wbm_we_i = 0; 49 | reg [WBM_SELECT_WIDTH-1:0] wbm_sel_i = 0; 50 | reg wbm_stb_i = 0; 51 | reg wbm_cyc_i = 0; 52 | reg [WBS_DATA_WIDTH-1:0] wbs_dat_i = 0; 53 | reg wbs_ack_i = 0; 54 | reg wbs_err_i = 0; 55 | reg wbs_rty_i = 0; 56 | 57 | // Outputs 58 | wire [WBM_DATA_WIDTH-1:0] wbm_dat_o; 59 | wire wbm_ack_o; 60 | wire wbm_err_o; 61 | wire wbm_rty_o; 62 | wire [ADDR_WIDTH-1:0] wbs_adr_o; 63 | wire [WBS_DATA_WIDTH-1:0] wbs_dat_o; 64 | wire wbs_we_o; 65 | wire [WBS_SELECT_WIDTH-1:0] wbs_sel_o; 66 | wire wbs_stb_o; 67 | wire wbs_cyc_o; 68 | 69 | initial begin 70 | // myhdl integration 71 | $from_myhdl( 72 | clk, 73 | rst, 74 | current_test, 75 | wbm_adr_i, 76 | wbm_dat_i, 77 | wbm_we_i, 78 | wbm_sel_i, 79 | wbm_stb_i, 80 | wbm_cyc_i, 81 | wbs_dat_i, 82 | wbs_ack_i, 83 | wbs_err_i, 84 | wbs_rty_i 85 | ); 86 | $to_myhdl( 87 | wbm_dat_o, 88 | wbm_ack_o, 89 | wbm_err_o, 90 | wbm_rty_o, 91 | wbs_adr_o, 92 | wbs_dat_o, 93 | wbs_we_o, 94 | wbs_sel_o, 95 | wbs_stb_o, 96 | wbs_cyc_o 97 | ); 98 | 99 | // dump file 100 | $dumpfile("test_wb_adapter_8_32.lxt"); 101 | $dumpvars(0, test_wb_adapter_8_32); 102 | end 103 | 104 | wb_adapter #( 105 | .ADDR_WIDTH(ADDR_WIDTH), 106 | .WBM_DATA_WIDTH(WBM_DATA_WIDTH), 107 | .WBM_SELECT_WIDTH(WBM_SELECT_WIDTH), 108 | .WBS_DATA_WIDTH(WBS_DATA_WIDTH), 109 | .WBS_SELECT_WIDTH(WBS_SELECT_WIDTH) 110 | ) 111 | UUT ( 112 | .clk(clk), 113 | .rst(rst), 114 | .wbm_adr_i(wbm_adr_i), 115 | .wbm_dat_i(wbm_dat_i), 116 | .wbm_dat_o(wbm_dat_o), 117 | .wbm_we_i(wbm_we_i), 118 | .wbm_sel_i(wbm_sel_i), 119 | .wbm_stb_i(wbm_stb_i), 120 | .wbm_ack_o(wbm_ack_o), 121 | .wbm_err_o(wbm_err_o), 122 | .wbm_rty_o(wbm_rty_o), 123 | .wbm_cyc_i(wbm_cyc_i), 124 | .wbs_adr_o(wbs_adr_o), 125 | .wbs_dat_i(wbs_dat_i), 126 | .wbs_dat_o(wbs_dat_o), 127 | .wbs_we_o(wbs_we_o), 128 | .wbs_sel_o(wbs_sel_o), 129 | .wbs_stb_o(wbs_stb_o), 130 | .wbs_ack_i(wbs_ack_i), 131 | .wbs_err_i(wbs_err_i), 132 | .wbs_rty_i(wbs_rty_i), 133 | .wbs_cyc_o(wbs_cyc_o) 134 | ); 135 | 136 | endmodule 137 | -------------------------------------------------------------------------------- /tb/test_wb_arbiter_2.v: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2015-2016 Alex Forencich 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | */ 24 | 25 | // Language: Verilog 2001 26 | 27 | `timescale 1ns / 1ps 28 | 29 | /* 30 | * Testbench for wb_arbiter_2 31 | */ 32 | module test_wb_arbiter_2; 33 | 34 | // Parameters 35 | parameter DATA_WIDTH = 32; 36 | parameter ADDR_WIDTH = 32; 37 | parameter SELECT_WIDTH = (DATA_WIDTH/8); 38 | parameter ARB_TYPE_ROUND_ROBIN = 0; 39 | parameter ARB_LSB_HIGH_PRIORITY = 1; 40 | 41 | // Inputs 42 | reg clk = 0; 43 | reg rst = 0; 44 | reg [7:0] current_test = 0; 45 | 46 | reg [ADDR_WIDTH-1:0] wbm0_adr_i = 0; 47 | reg [DATA_WIDTH-1:0] wbm0_dat_i = 0; 48 | reg wbm0_we_i = 0; 49 | reg [SELECT_WIDTH-1:0] wbm0_sel_i = 0; 50 | reg wbm0_stb_i = 0; 51 | reg wbm0_cyc_i = 0; 52 | reg [ADDR_WIDTH-1:0] wbm1_adr_i = 0; 53 | reg [DATA_WIDTH-1:0] wbm1_dat_i = 0; 54 | reg wbm1_we_i = 0; 55 | reg [SELECT_WIDTH-1:0] wbm1_sel_i = 0; 56 | reg wbm1_stb_i = 0; 57 | reg wbm1_cyc_i = 0; 58 | reg [DATA_WIDTH-1:0] wbs_dat_i = 0; 59 | reg wbs_ack_i = 0; 60 | reg wbs_err_i = 0; 61 | reg wbs_rty_i = 0; 62 | 63 | // Outputs 64 | wire [DATA_WIDTH-1:0] wbm0_dat_o; 65 | wire wbm0_ack_o; 66 | wire wbm0_err_o; 67 | wire wbm0_rty_o; 68 | wire [DATA_WIDTH-1:0] wbm1_dat_o; 69 | wire wbm1_ack_o; 70 | wire wbm1_err_o; 71 | wire wbm1_rty_o; 72 | wire [ADDR_WIDTH-1:0] wbs_adr_o; 73 | wire [DATA_WIDTH-1:0] wbs_dat_o; 74 | wire wbs_we_o; 75 | wire [SELECT_WIDTH-1:0] wbs_sel_o; 76 | wire wbs_stb_o; 77 | wire wbs_cyc_o; 78 | 79 | initial begin 80 | // myhdl integration 81 | $from_myhdl( 82 | clk, 83 | rst, 84 | current_test, 85 | wbm0_adr_i, 86 | wbm0_dat_i, 87 | wbm0_we_i, 88 | wbm0_sel_i, 89 | wbm0_stb_i, 90 | wbm0_cyc_i, 91 | wbm1_adr_i, 92 | wbm1_dat_i, 93 | wbm1_we_i, 94 | wbm1_sel_i, 95 | wbm1_stb_i, 96 | wbm1_cyc_i, 97 | wbs_dat_i, 98 | wbs_ack_i, 99 | wbs_err_i, 100 | wbs_rty_i 101 | ); 102 | $to_myhdl( 103 | wbm0_dat_o, 104 | wbm0_ack_o, 105 | wbm0_err_o, 106 | wbm0_rty_o, 107 | wbm1_dat_o, 108 | wbm1_ack_o, 109 | wbm1_err_o, 110 | wbm1_rty_o, 111 | wbs_adr_o, 112 | wbs_dat_o, 113 | wbs_we_o, 114 | wbs_sel_o, 115 | wbs_stb_o, 116 | wbs_cyc_o 117 | ); 118 | 119 | // dump file 120 | $dumpfile("test_wb_arbiter_2.lxt"); 121 | $dumpvars(0, test_wb_arbiter_2); 122 | end 123 | 124 | wb_arbiter_2 #( 125 | .DATA_WIDTH(DATA_WIDTH), 126 | .ADDR_WIDTH(ADDR_WIDTH), 127 | .SELECT_WIDTH(SELECT_WIDTH), 128 | .ARB_TYPE_ROUND_ROBIN(ARB_TYPE_ROUND_ROBIN), 129 | .ARB_LSB_HIGH_PRIORITY(ARB_LSB_HIGH_PRIORITY) 130 | ) 131 | UUT ( 132 | .clk(clk), 133 | .rst(rst), 134 | .wbm0_adr_i(wbm0_adr_i), 135 | .wbm0_dat_i(wbm0_dat_i), 136 | .wbm0_dat_o(wbm0_dat_o), 137 | .wbm0_we_i(wbm0_we_i), 138 | .wbm0_sel_i(wbm0_sel_i), 139 | .wbm0_stb_i(wbm0_stb_i), 140 | .wbm0_ack_o(wbm0_ack_o), 141 | .wbm0_err_o(wbm0_err_o), 142 | .wbm0_rty_o(wbm0_rty_o), 143 | .wbm0_cyc_i(wbm0_cyc_i), 144 | .wbm1_adr_i(wbm1_adr_i), 145 | .wbm1_dat_i(wbm1_dat_i), 146 | .wbm1_dat_o(wbm1_dat_o), 147 | .wbm1_we_i(wbm1_we_i), 148 | .wbm1_sel_i(wbm1_sel_i), 149 | .wbm1_stb_i(wbm1_stb_i), 150 | .wbm1_ack_o(wbm1_ack_o), 151 | .wbm1_err_o(wbm1_err_o), 152 | .wbm1_rty_o(wbm1_rty_o), 153 | .wbm1_cyc_i(wbm1_cyc_i), 154 | .wbs_adr_o(wbs_adr_o), 155 | .wbs_dat_i(wbs_dat_i), 156 | .wbs_dat_o(wbs_dat_o), 157 | .wbs_we_o(wbs_we_o), 158 | .wbs_sel_o(wbs_sel_o), 159 | .wbs_stb_o(wbs_stb_o), 160 | .wbs_ack_i(wbs_ack_i), 161 | .wbs_err_i(wbs_err_i), 162 | .wbs_rty_i(wbs_rty_i), 163 | .wbs_cyc_o(wbs_cyc_o) 164 | ); 165 | 166 | endmodule 167 | -------------------------------------------------------------------------------- /tb/test_wb_async_reg.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | 4 | Copyright (c) 2015-2016 Alex Forencich 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | 24 | """ 25 | 26 | from myhdl import * 27 | import os 28 | 29 | import wb 30 | 31 | module = 'wb_async_reg' 32 | testbench = 'test_%s' % module 33 | 34 | srcs = [] 35 | 36 | srcs.append("../rtl/%s.v" % module) 37 | srcs.append("%s.v" % testbench) 38 | 39 | src = ' '.join(srcs) 40 | 41 | build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) 42 | 43 | def bench(): 44 | 45 | # Parameters 46 | DATA_WIDTH = 32 47 | ADDR_WIDTH = 32 48 | SELECT_WIDTH = 4 49 | 50 | # Inputs 51 | wbm_clk = Signal(bool(0)) 52 | wbm_rst = Signal(bool(0)) 53 | wbs_clk = Signal(bool(0)) 54 | wbs_rst = Signal(bool(0)) 55 | current_test = Signal(intbv(0)[8:]) 56 | 57 | wbm_adr_i = Signal(intbv(0)[ADDR_WIDTH:]) 58 | wbm_dat_i = Signal(intbv(0)[DATA_WIDTH:]) 59 | wbm_we_i = Signal(bool(0)) 60 | wbm_sel_i = Signal(intbv(0)[SELECT_WIDTH:]) 61 | wbm_stb_i = Signal(bool(0)) 62 | wbm_cyc_i = Signal(bool(0)) 63 | wbs_dat_i = Signal(intbv(0)[DATA_WIDTH:]) 64 | wbs_ack_i = Signal(bool(0)) 65 | wbs_err_i = Signal(bool(0)) 66 | wbs_rty_i = Signal(bool(0)) 67 | 68 | # Outputs 69 | wbm_dat_o = Signal(intbv(0)[DATA_WIDTH:]) 70 | wbm_ack_o = Signal(bool(0)) 71 | wbm_err_o = Signal(bool(0)) 72 | wbm_rty_o = Signal(bool(0)) 73 | wbs_adr_o = Signal(intbv(0)[ADDR_WIDTH:]) 74 | wbs_dat_o = Signal(intbv(0)[DATA_WIDTH:]) 75 | wbs_we_o = Signal(bool(0)) 76 | wbs_sel_o = Signal(intbv(0)[SELECT_WIDTH:]) 77 | wbs_stb_o = Signal(bool(0)) 78 | wbs_cyc_o = Signal(bool(0)) 79 | 80 | # WB master 81 | wbm_inst = wb.WBMaster() 82 | 83 | wbm_logic = wbm_inst.create_logic( 84 | wbm_clk, 85 | adr_o=wbm_adr_i, 86 | dat_i=wbm_dat_o, 87 | dat_o=wbm_dat_i, 88 | we_o=wbm_we_i, 89 | sel_o=wbm_sel_i, 90 | stb_o=wbm_stb_i, 91 | ack_i=wbm_ack_o, 92 | cyc_o=wbm_cyc_i, 93 | name='master' 94 | ) 95 | 96 | # WB RAM model 97 | wb_ram_inst = wb.WBRam(2**16) 98 | 99 | wb_ram_port0 = wb_ram_inst.create_port( 100 | wbs_clk, 101 | adr_i=wbs_adr_o, 102 | dat_i=wbs_dat_o, 103 | dat_o=wbs_dat_i, 104 | we_i=wbs_we_o, 105 | sel_i=wbs_sel_o, 106 | stb_i=wbs_stb_o, 107 | ack_o=wbs_ack_i, 108 | cyc_i=wbs_cyc_o, 109 | latency=1, 110 | asynchronous=False, 111 | name='slave' 112 | ) 113 | 114 | # DUT 115 | if os.system(build_cmd): 116 | raise Exception("Error running build command") 117 | 118 | dut = Cosimulation( 119 | "vvp -m myhdl %s.vvp -lxt2" % testbench, 120 | wbm_clk=wbm_clk, 121 | wbm_rst=wbm_rst, 122 | wbs_clk=wbs_clk, 123 | wbs_rst=wbs_rst, 124 | current_test=current_test, 125 | wbm_adr_i=wbm_adr_i, 126 | wbm_dat_i=wbm_dat_i, 127 | wbm_dat_o=wbm_dat_o, 128 | wbm_we_i=wbm_we_i, 129 | wbm_sel_i=wbm_sel_i, 130 | wbm_stb_i=wbm_stb_i, 131 | wbm_ack_o=wbm_ack_o, 132 | wbm_err_o=wbm_err_o, 133 | wbm_rty_o=wbm_rty_o, 134 | wbm_cyc_i=wbm_cyc_i, 135 | wbs_adr_o=wbs_adr_o, 136 | wbs_dat_i=wbs_dat_i, 137 | wbs_dat_o=wbs_dat_o, 138 | wbs_we_o=wbs_we_o, 139 | wbs_sel_o=wbs_sel_o, 140 | wbs_stb_o=wbs_stb_o, 141 | wbs_ack_i=wbs_ack_i, 142 | wbs_err_i=wbs_err_i, 143 | wbs_rty_i=wbs_rty_i, 144 | wbs_cyc_o=wbs_cyc_o 145 | ) 146 | 147 | @always(delay(4)) 148 | def wbm_clkgen(): 149 | wbm_clk.next = not wbm_clk 150 | 151 | @always(delay(5)) 152 | def wbs_clkgen(): 153 | wbs_clk.next = not wbs_clk 154 | 155 | @instance 156 | def check(): 157 | yield delay(100) 158 | yield wbm_clk.posedge 159 | wbm_rst.next = 1 160 | wbs_rst.next = 1 161 | yield wbm_clk.posedge 162 | yield wbm_clk.posedge 163 | yield wbm_clk.posedge 164 | wbm_rst.next = 0 165 | wbs_rst.next = 0 166 | yield wbm_clk.posedge 167 | yield delay(100) 168 | yield wbm_clk.posedge 169 | 170 | yield wbm_clk.posedge 171 | print("test 1: write") 172 | current_test.next = 1 173 | 174 | wbm_inst.init_write(4, b'\x11\x22\x33\x44') 175 | 176 | yield wbm_inst.wait() 177 | yield wbm_clk.posedge 178 | 179 | data = wb_ram_inst.read_mem(0, 32) 180 | for i in range(0, len(data), 16): 181 | print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16])))) 182 | 183 | assert wb_ram_inst.read_mem(4,4) == b'\x11\x22\x33\x44' 184 | 185 | yield delay(100) 186 | 187 | yield wbm_clk.posedge 188 | print("test 2: read") 189 | current_test.next = 2 190 | 191 | wbm_inst.init_read(4, 4) 192 | 193 | yield wbm_inst.wait() 194 | yield wbm_clk.posedge 195 | 196 | data = wbm_inst.get_read_data() 197 | assert data[0] == 4 198 | assert data[1] == b'\x11\x22\x33\x44' 199 | 200 | yield delay(100) 201 | 202 | yield wbm_clk.posedge 203 | print("test 3: various writes") 204 | current_test.next = 3 205 | 206 | for length in range(1,8): 207 | for offset in range(4,8): 208 | wb_ram_inst.write_mem(256*(16*offset+length), b'\xAA'*32) 209 | wbm_inst.init_write(256*(16*offset+length)+offset, b'\x11\x22\x33\x44\x55\x66\x77\x88'[0:length]) 210 | 211 | yield wbm_inst.wait() 212 | yield wbm_clk.posedge 213 | 214 | data = wb_ram_inst.read_mem(256*(16*offset+length), 32) 215 | for i in range(0, len(data), 16): 216 | print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16])))) 217 | 218 | assert wb_ram_inst.read_mem(256*(16*offset+length)+offset, length) == b'\x11\x22\x33\x44\x55\x66\x77\x88'[0:length] 219 | assert wb_ram_inst.read_mem(256*(16*offset+length)+offset-1, 1) == b'\xAA' 220 | assert wb_ram_inst.read_mem(256*(16*offset+length)+offset+length, 1) == b'\xAA' 221 | 222 | yield delay(100) 223 | 224 | yield wbm_clk.posedge 225 | print("test 4: various reads") 226 | current_test.next = 4 227 | 228 | for length in range(1,8): 229 | for offset in range(4,8): 230 | wbm_inst.init_read(256*(16*offset+length)+offset, length) 231 | 232 | yield wbm_inst.wait() 233 | yield wbm_clk.posedge 234 | 235 | data = wbm_inst.get_read_data() 236 | assert data[0] == 256*(16*offset+length)+offset 237 | assert data[1] == b'\x11\x22\x33\x44\x55\x66\x77\x88'[0:length] 238 | 239 | yield delay(100) 240 | 241 | raise StopSimulation 242 | 243 | return instances() 244 | 245 | def test_bench(): 246 | sim = Simulation(bench()) 247 | sim.run() 248 | 249 | if __name__ == '__main__': 250 | print("Running test...") 251 | test_bench() 252 | -------------------------------------------------------------------------------- /tb/test_wb_async_reg.v: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2015-2016 Alex Forencich 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | */ 24 | 25 | // Language: Verilog 2001 26 | 27 | `timescale 1ns / 1ps 28 | 29 | /* 30 | * Testbench for wb_async_reg 31 | */ 32 | module test_wb_async_reg; 33 | 34 | // Parameters 35 | parameter DATA_WIDTH = 32; 36 | parameter ADDR_WIDTH = 32; 37 | parameter SELECT_WIDTH = 4; 38 | 39 | // Inputs 40 | reg wbm_clk = 0; 41 | reg wbm_rst = 0; 42 | reg wbs_clk = 0; 43 | reg wbs_rst = 0; 44 | reg [7:0] current_test = 0; 45 | 46 | reg [ADDR_WIDTH-1:0] wbm_adr_i = 0; 47 | reg [DATA_WIDTH-1:0] wbm_dat_i = 0; 48 | reg wbm_we_i = 0; 49 | reg [SELECT_WIDTH-1:0] wbm_sel_i = 0; 50 | reg wbm_stb_i = 0; 51 | reg wbm_cyc_i = 0; 52 | reg [DATA_WIDTH-1:0] wbs_dat_i = 0; 53 | reg wbs_ack_i = 0; 54 | reg wbs_err_i = 0; 55 | reg wbs_rty_i = 0; 56 | 57 | // Outputs 58 | wire [DATA_WIDTH-1:0] wbm_dat_o; 59 | wire wbm_ack_o; 60 | wire wbm_err_o; 61 | wire wbm_rty_o; 62 | wire [ADDR_WIDTH-1:0] wbs_adr_o; 63 | wire [DATA_WIDTH-1:0] wbs_dat_o; 64 | wire wbs_we_o; 65 | wire [SELECT_WIDTH-1:0] wbs_sel_o; 66 | wire wbs_stb_o; 67 | wire wbs_cyc_o; 68 | 69 | initial begin 70 | // myhdl integration 71 | $from_myhdl( 72 | wbm_clk, 73 | wbm_rst, 74 | wbs_clk, 75 | wbs_rst, 76 | current_test, 77 | wbm_adr_i, 78 | wbm_dat_i, 79 | wbm_we_i, 80 | wbm_sel_i, 81 | wbm_stb_i, 82 | wbm_cyc_i, 83 | wbs_dat_i, 84 | wbs_ack_i, 85 | wbs_err_i, 86 | wbs_rty_i 87 | ); 88 | $to_myhdl( 89 | wbm_dat_o, 90 | wbm_ack_o, 91 | wbm_err_o, 92 | wbm_rty_o, 93 | wbs_adr_o, 94 | wbs_dat_o, 95 | wbs_we_o, 96 | wbs_sel_o, 97 | wbs_stb_o, 98 | wbs_cyc_o 99 | ); 100 | 101 | // dump file 102 | $dumpfile("test_wb_async_reg.lxt"); 103 | $dumpvars(0, test_wb_async_reg); 104 | end 105 | 106 | wb_async_reg #( 107 | .DATA_WIDTH(DATA_WIDTH), 108 | .ADDR_WIDTH(ADDR_WIDTH), 109 | .SELECT_WIDTH(SELECT_WIDTH) 110 | ) 111 | UUT ( 112 | .wbm_clk(wbm_clk), 113 | .wbm_rst(wbm_rst), 114 | .wbm_adr_i(wbm_adr_i), 115 | .wbm_dat_i(wbm_dat_i), 116 | .wbm_dat_o(wbm_dat_o), 117 | .wbm_we_i(wbm_we_i), 118 | .wbm_sel_i(wbm_sel_i), 119 | .wbm_stb_i(wbm_stb_i), 120 | .wbm_ack_o(wbm_ack_o), 121 | .wbm_err_o(wbm_err_o), 122 | .wbm_rty_o(wbm_rty_o), 123 | .wbm_cyc_i(wbm_cyc_i), 124 | .wbs_clk(wbs_clk), 125 | .wbs_rst(wbs_rst), 126 | .wbs_adr_o(wbs_adr_o), 127 | .wbs_dat_i(wbs_dat_i), 128 | .wbs_dat_o(wbs_dat_o), 129 | .wbs_we_o(wbs_we_o), 130 | .wbs_sel_o(wbs_sel_o), 131 | .wbs_stb_o(wbs_stb_o), 132 | .wbs_ack_i(wbs_ack_i), 133 | .wbs_err_i(wbs_err_i), 134 | .wbs_rty_i(wbs_rty_i), 135 | .wbs_cyc_o(wbs_cyc_o) 136 | ); 137 | 138 | endmodule 139 | -------------------------------------------------------------------------------- /tb/test_wb_dp_ram.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | 4 | Copyright (c) 2015-2016 Alex Forencich 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | 24 | """ 25 | 26 | from myhdl import * 27 | import os 28 | 29 | import wb 30 | 31 | module = 'wb_dp_ram' 32 | testbench = 'test_%s' % module 33 | 34 | srcs = [] 35 | 36 | srcs.append("../rtl/%s.v" % module) 37 | srcs.append("%s.v" % testbench) 38 | 39 | src = ' '.join(srcs) 40 | 41 | build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) 42 | 43 | def bench(): 44 | 45 | # Parameters 46 | DATA_WIDTH = 32 47 | ADDR_WIDTH = 32 48 | SELECT_WIDTH = 4 49 | 50 | # Inputs 51 | a_clk = Signal(bool(0)) 52 | a_rst = Signal(bool(0)) 53 | b_clk = Signal(bool(0)) 54 | b_rst = Signal(bool(0)) 55 | current_test = Signal(intbv(0)[8:]) 56 | 57 | a_adr_i = Signal(intbv(0)[ADDR_WIDTH:]) 58 | a_dat_i = Signal(intbv(0)[DATA_WIDTH:]) 59 | a_we_i = Signal(bool(0)) 60 | a_sel_i = Signal(intbv(0)[SELECT_WIDTH:]) 61 | a_stb_i = Signal(bool(0)) 62 | a_cyc_i = Signal(bool(0)) 63 | b_adr_i = Signal(intbv(0)[ADDR_WIDTH:]) 64 | b_dat_i = Signal(intbv(0)[DATA_WIDTH:]) 65 | b_we_i = Signal(bool(0)) 66 | b_sel_i = Signal(intbv(0)[SELECT_WIDTH:]) 67 | b_stb_i = Signal(bool(0)) 68 | b_cyc_i = Signal(bool(0)) 69 | 70 | # Outputs 71 | a_dat_o = Signal(intbv(0)[DATA_WIDTH:]) 72 | a_ack_o = Signal(bool(0)) 73 | b_dat_o = Signal(intbv(0)[DATA_WIDTH:]) 74 | b_ack_o = Signal(bool(0)) 75 | 76 | # WB master A 77 | wbm_inst_a = wb.WBMaster() 78 | 79 | wbm_logic_a = wbm_inst_a.create_logic( 80 | a_clk, 81 | adr_o=a_adr_i, 82 | dat_i=a_dat_o, 83 | dat_o=a_dat_i, 84 | we_o=a_we_i, 85 | sel_o=a_sel_i, 86 | stb_o=a_stb_i, 87 | ack_i=a_ack_o, 88 | cyc_o=a_cyc_i, 89 | name='master_a' 90 | ) 91 | 92 | # WB master B 93 | wbm_inst_b = wb.WBMaster() 94 | 95 | wbm_logic_b = wbm_inst_b.create_logic( 96 | b_clk, 97 | adr_o=b_adr_i, 98 | dat_i=b_dat_o, 99 | dat_o=b_dat_i, 100 | we_o=b_we_i, 101 | sel_o=b_sel_i, 102 | stb_o=b_stb_i, 103 | ack_i=b_ack_o, 104 | cyc_o=b_cyc_i, 105 | name='master_' 106 | ) 107 | 108 | # DUT 109 | if os.system(build_cmd): 110 | raise Exception("Error running build command") 111 | 112 | dut = Cosimulation( 113 | "vvp -m myhdl %s.vvp -lxt2" % testbench, 114 | a_clk=a_clk, 115 | a_rst=a_rst, 116 | b_clk=b_clk, 117 | b_rst=b_rst, 118 | current_test=current_test, 119 | a_adr_i=a_adr_i, 120 | a_dat_i=a_dat_i, 121 | a_dat_o=a_dat_o, 122 | a_we_i=a_we_i, 123 | a_sel_i=a_sel_i, 124 | a_stb_i=a_stb_i, 125 | a_ack_o=a_ack_o, 126 | a_cyc_i=a_cyc_i, 127 | b_adr_i=b_adr_i, 128 | b_dat_i=b_dat_i, 129 | b_dat_o=b_dat_o, 130 | b_we_i=b_we_i, 131 | b_sel_i=b_sel_i, 132 | b_stb_i=b_stb_i, 133 | b_ack_o=b_ack_o, 134 | b_cyc_i=b_cyc_i 135 | ) 136 | 137 | @always(delay(4)) 138 | def a_clkgen(): 139 | a_clk.next = not a_clk 140 | 141 | @always(delay(5)) 142 | def b_clkgen(): 143 | b_clk.next = not b_clk 144 | 145 | @instance 146 | def check(): 147 | yield delay(100) 148 | yield a_clk.posedge 149 | a_rst.next = 1 150 | b_rst.next = 1 151 | yield a_clk.posedge 152 | yield a_clk.posedge 153 | yield a_clk.posedge 154 | a_rst.next = 0 155 | b_rst.next = 0 156 | yield a_clk.posedge 157 | yield delay(100) 158 | yield a_clk.posedge 159 | 160 | yield a_clk.posedge 161 | print("test 1: read and write (port A)") 162 | current_test.next = 1 163 | 164 | wbm_inst_a.init_write(4, b'\x11\x22\x33\x44') 165 | 166 | yield wbm_inst_a.wait() 167 | yield a_clk.posedge 168 | 169 | wbm_inst_a.init_read(4, 4) 170 | 171 | yield wbm_inst_a.wait() 172 | yield a_clk.posedge 173 | 174 | data = wbm_inst_a.get_read_data() 175 | assert data[0] == 4 176 | assert data[1] == b'\x11\x22\x33\x44' 177 | 178 | yield delay(100) 179 | 180 | yield a_clk.posedge 181 | print("test 2: read and write (port B)") 182 | current_test.next = 2 183 | 184 | wbm_inst_b.init_write(4, b'\x11\x22\x33\x44') 185 | 186 | yield wbm_inst_b.wait() 187 | yield b_clk.posedge 188 | 189 | wbm_inst_b.init_read(4, 4) 190 | 191 | yield wbm_inst_b.wait() 192 | yield b_clk.posedge 193 | 194 | data = wbm_inst_b.get_read_data() 195 | assert data[0] == 4 196 | assert data[1] == b'\x11\x22\x33\x44' 197 | 198 | yield delay(100) 199 | 200 | yield a_clk.posedge 201 | print("test 3: various reads and writes (port A)") 202 | current_test.next = 3 203 | 204 | for length in range(1,8): 205 | for offset in range(4): 206 | wbm_inst_a.init_write(256*(16*offset+length)+offset, b'\x11\x22\x33\x44\x55\x66\x77\x88'[0:length]) 207 | 208 | yield wbm_inst_a.wait() 209 | yield a_clk.posedge 210 | 211 | for length in range(1,8): 212 | for offset in range(4): 213 | wbm_inst_a.init_read(256*(16*offset+length)+offset, length) 214 | 215 | yield wbm_inst_a.wait() 216 | yield a_clk.posedge 217 | 218 | data = wbm_inst_a.get_read_data() 219 | assert data[0] == 256*(16*offset+length)+offset 220 | assert data[1] == b'\x11\x22\x33\x44\x55\x66\x77\x88'[0:length] 221 | 222 | yield delay(100) 223 | 224 | yield a_clk.posedge 225 | print("test 4: various reads and writes (port B)") 226 | current_test.next = 4 227 | 228 | for length in range(1,8): 229 | for offset in range(4): 230 | wbm_inst_b.init_write(256*(16*offset+length)+offset, b'\x11\x22\x33\x44\x55\x66\x77\x88'[0:length]) 231 | 232 | yield wbm_inst_b.wait() 233 | yield b_clk.posedge 234 | 235 | for length in range(1,8): 236 | for offset in range(4): 237 | wbm_inst_b.init_read(256*(16*offset+length)+offset, length) 238 | 239 | yield wbm_inst_b.wait() 240 | yield b_clk.posedge 241 | 242 | data = wbm_inst_b.get_read_data() 243 | assert data[0] == 256*(16*offset+length)+offset 244 | assert data[1] == b'\x11\x22\x33\x44\x55\x66\x77\x88'[0:length] 245 | 246 | yield delay(100) 247 | 248 | yield a_clk.posedge 249 | print("test 5: simultaneous read and write") 250 | current_test.next = 5 251 | 252 | wbm_inst_a.init_write(8, b'\xAA\xAA\xAA\xAA') 253 | wbm_inst_b.init_write(12, b'\xBB\xBB\xBB\xBB') 254 | 255 | yield wbm_inst_a.wait() 256 | yield wbm_inst_b.wait() 257 | yield a_clk.posedge 258 | 259 | wbm_inst_a.init_read(12, 4) 260 | wbm_inst_b.init_read(8, 4) 261 | 262 | yield wbm_inst_a.wait() 263 | yield wbm_inst_b.wait() 264 | yield a_clk.posedge 265 | 266 | data = wbm_inst_a.get_read_data() 267 | assert data[0] == 12 268 | assert data[1] == b'\xBB\xBB\xBB\xBB' 269 | data = wbm_inst_b.get_read_data() 270 | assert data[0] == 8 271 | assert data[1] == b'\xAA\xAA\xAA\xAA' 272 | 273 | yield delay(100) 274 | 275 | raise StopSimulation 276 | 277 | return instances() 278 | 279 | def test_bench(): 280 | sim = Simulation(bench()) 281 | sim.run() 282 | 283 | if __name__ == '__main__': 284 | print("Running test...") 285 | test_bench() 286 | -------------------------------------------------------------------------------- /tb/test_wb_dp_ram.v: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2015-2016 Alex Forencich 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | */ 24 | 25 | // Language: Verilog 2001 26 | 27 | `timescale 1ns / 1ps 28 | 29 | /* 30 | * Testbench for wb_dp_ram 31 | */ 32 | module test_wb_dp_ram; 33 | 34 | // Parameters 35 | parameter DATA_WIDTH = 32; 36 | parameter ADDR_WIDTH = 16; 37 | parameter SELECT_WIDTH = 4; 38 | 39 | // Inputs 40 | reg a_clk = 0; 41 | reg a_rst = 0; 42 | reg b_clk = 0; 43 | reg b_rst = 0; 44 | reg [7:0] current_test = 0; 45 | 46 | reg [ADDR_WIDTH-1:0] a_adr_i = 0; 47 | reg [DATA_WIDTH-1:0] a_dat_i = 0; 48 | reg a_we_i = 0; 49 | reg [SELECT_WIDTH-1:0] a_sel_i = 0; 50 | reg a_stb_i = 0; 51 | reg a_cyc_i = 0; 52 | reg [ADDR_WIDTH-1:0] b_adr_i = 0; 53 | reg [DATA_WIDTH-1:0] b_dat_i = 0; 54 | reg b_we_i = 0; 55 | reg [SELECT_WIDTH-1:0] b_sel_i = 0; 56 | reg b_stb_i = 0; 57 | reg b_cyc_i = 0; 58 | 59 | // Outputs 60 | wire [DATA_WIDTH-1:0] a_dat_o; 61 | wire a_ack_o; 62 | wire [DATA_WIDTH-1:0] b_dat_o; 63 | wire b_ack_o; 64 | 65 | initial begin 66 | // myhdl integration 67 | $from_myhdl( 68 | a_clk, 69 | a_rst, 70 | b_clk, 71 | b_rst, 72 | current_test, 73 | a_adr_i, 74 | a_dat_i, 75 | a_we_i, 76 | a_sel_i, 77 | a_stb_i, 78 | a_cyc_i, 79 | b_adr_i, 80 | b_dat_i, 81 | b_we_i, 82 | b_sel_i, 83 | b_stb_i, 84 | b_cyc_i 85 | ); 86 | $to_myhdl( 87 | a_dat_o, 88 | a_ack_o, 89 | b_dat_o, 90 | b_ack_o 91 | ); 92 | 93 | // dump file 94 | $dumpfile("test_wb_dp_ram.lxt"); 95 | $dumpvars(0, test_wb_dp_ram); 96 | end 97 | 98 | wb_dp_ram #( 99 | .DATA_WIDTH(DATA_WIDTH), 100 | .ADDR_WIDTH(ADDR_WIDTH), 101 | .SELECT_WIDTH(SELECT_WIDTH) 102 | ) 103 | UUT ( 104 | .a_clk(a_clk), 105 | .a_adr_i(a_adr_i), 106 | .a_dat_i(a_dat_i), 107 | .a_dat_o(a_dat_o), 108 | .a_we_i(a_we_i), 109 | .a_sel_i(a_sel_i), 110 | .a_stb_i(a_stb_i), 111 | .a_ack_o(a_ack_o), 112 | .a_cyc_i(a_cyc_i), 113 | .b_clk(b_clk), 114 | .b_adr_i(b_adr_i), 115 | .b_dat_i(b_dat_i), 116 | .b_dat_o(b_dat_o), 117 | .b_we_i(b_we_i), 118 | .b_sel_i(b_sel_i), 119 | .b_stb_i(b_stb_i), 120 | .b_ack_o(b_ack_o), 121 | .b_cyc_i(b_cyc_i) 122 | ); 123 | 124 | endmodule 125 | -------------------------------------------------------------------------------- /tb/test_wb_mux_2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | 4 | Copyright (c) 2015-2016 Alex Forencich 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | 24 | """ 25 | 26 | from myhdl import * 27 | import os 28 | 29 | import wb 30 | 31 | module = 'wb_mux_2' 32 | testbench = 'test_%s' % module 33 | 34 | srcs = [] 35 | 36 | srcs.append("../rtl/%s.v" % module) 37 | srcs.append("%s.v" % testbench) 38 | 39 | src = ' '.join(srcs) 40 | 41 | build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) 42 | 43 | def bench(): 44 | 45 | # Parameters 46 | DATA_WIDTH = 32 47 | ADDR_WIDTH = 32 48 | SELECT_WIDTH = 4 49 | 50 | # Inputs 51 | clk = Signal(bool(0)) 52 | rst = Signal(bool(0)) 53 | current_test = Signal(intbv(0)[8:]) 54 | 55 | wbm_adr_i = Signal(intbv(0)[ADDR_WIDTH:]) 56 | wbm_dat_i = Signal(intbv(0)[DATA_WIDTH:]) 57 | wbm_we_i = Signal(bool(0)) 58 | wbm_sel_i = Signal(intbv(0)[SELECT_WIDTH:]) 59 | wbm_stb_i = Signal(bool(0)) 60 | wbm_cyc_i = Signal(bool(0)) 61 | wbs0_dat_i = Signal(intbv(0)[DATA_WIDTH:]) 62 | wbs0_ack_i = Signal(bool(0)) 63 | wbs0_err_i = Signal(bool(0)) 64 | wbs0_rty_i = Signal(bool(0)) 65 | wbs0_addr = Signal(intbv(0)[ADDR_WIDTH:]) 66 | wbs0_addr_msk = Signal(intbv(0)[ADDR_WIDTH:]) 67 | wbs1_dat_i = Signal(intbv(0)[DATA_WIDTH:]) 68 | wbs1_ack_i = Signal(bool(0)) 69 | wbs1_err_i = Signal(bool(0)) 70 | wbs1_rty_i = Signal(bool(0)) 71 | wbs1_addr = Signal(intbv(0)[ADDR_WIDTH:]) 72 | wbs1_addr_msk = Signal(intbv(0)[ADDR_WIDTH:]) 73 | 74 | # Outputs 75 | wbm_dat_o = Signal(intbv(0)[DATA_WIDTH:]) 76 | wbm_ack_o = Signal(bool(0)) 77 | wbm_err_o = Signal(bool(0)) 78 | wbm_rty_o = Signal(bool(0)) 79 | wbs0_adr_o = Signal(intbv(0)[ADDR_WIDTH:]) 80 | wbs0_dat_o = Signal(intbv(0)[DATA_WIDTH:]) 81 | wbs0_we_o = Signal(bool(0)) 82 | wbs0_sel_o = Signal(intbv(0)[SELECT_WIDTH:]) 83 | wbs0_stb_o = Signal(bool(0)) 84 | wbs0_cyc_o = Signal(bool(0)) 85 | wbs1_adr_o = Signal(intbv(0)[ADDR_WIDTH:]) 86 | wbs1_dat_o = Signal(intbv(0)[DATA_WIDTH:]) 87 | wbs1_we_o = Signal(bool(0)) 88 | wbs1_sel_o = Signal(intbv(0)[SELECT_WIDTH:]) 89 | wbs1_stb_o = Signal(bool(0)) 90 | wbs1_cyc_o = Signal(bool(0)) 91 | 92 | # WB master 93 | wbm_inst = wb.WBMaster() 94 | 95 | wbm_logic = wbm_inst.create_logic( 96 | clk, 97 | adr_o=wbm_adr_i, 98 | dat_i=wbm_dat_o, 99 | dat_o=wbm_dat_i, 100 | we_o=wbm_we_i, 101 | sel_o=wbm_sel_i, 102 | stb_o=wbm_stb_i, 103 | ack_i=wbm_ack_o, 104 | cyc_o=wbm_cyc_i, 105 | name='master' 106 | ) 107 | 108 | # WB RAM model 109 | wb_ram0_inst = wb.WBRam(2**16) 110 | 111 | wb_ram0_port0 = wb_ram0_inst.create_port( 112 | clk, 113 | adr_i=wbs0_adr_o, 114 | dat_i=wbs0_dat_o, 115 | dat_o=wbs0_dat_i, 116 | we_i=wbs0_we_o, 117 | sel_i=wbs0_sel_o, 118 | stb_i=wbs0_stb_o, 119 | ack_o=wbs0_ack_i, 120 | cyc_i=wbs0_cyc_o, 121 | latency=1, 122 | asynchronous=False, 123 | name='slave0' 124 | ) 125 | 126 | # WB RAM model 127 | wb_ram1_inst = wb.WBRam(2**16) 128 | 129 | wb_ram1_port0 = wb_ram1_inst.create_port( 130 | clk, 131 | adr_i=wbs1_adr_o, 132 | dat_i=wbs1_dat_o, 133 | dat_o=wbs1_dat_i, 134 | we_i=wbs1_we_o, 135 | sel_i=wbs1_sel_o, 136 | stb_i=wbs1_stb_o, 137 | ack_o=wbs1_ack_i, 138 | cyc_i=wbs1_cyc_o, 139 | latency=1, 140 | asynchronous=False, 141 | name='slave1' 142 | ) 143 | 144 | # DUT 145 | if os.system(build_cmd): 146 | raise Exception("Error running build command") 147 | 148 | dut = Cosimulation( 149 | "vvp -m myhdl %s.vvp -lxt2" % testbench, 150 | clk=clk, 151 | rst=rst, 152 | current_test=current_test, 153 | wbm_adr_i=wbm_adr_i, 154 | wbm_dat_i=wbm_dat_i, 155 | wbm_dat_o=wbm_dat_o, 156 | wbm_we_i=wbm_we_i, 157 | wbm_sel_i=wbm_sel_i, 158 | wbm_stb_i=wbm_stb_i, 159 | wbm_ack_o=wbm_ack_o, 160 | wbm_err_o=wbm_err_o, 161 | wbm_rty_o=wbm_rty_o, 162 | wbm_cyc_i=wbm_cyc_i, 163 | wbs0_adr_o=wbs0_adr_o, 164 | wbs0_dat_i=wbs0_dat_i, 165 | wbs0_dat_o=wbs0_dat_o, 166 | wbs0_we_o=wbs0_we_o, 167 | wbs0_sel_o=wbs0_sel_o, 168 | wbs0_stb_o=wbs0_stb_o, 169 | wbs0_ack_i=wbs0_ack_i, 170 | wbs0_err_i=wbs0_err_i, 171 | wbs0_rty_i=wbs0_rty_i, 172 | wbs0_cyc_o=wbs0_cyc_o, 173 | wbs0_addr=wbs0_addr, 174 | wbs0_addr_msk=wbs0_addr_msk, 175 | wbs1_adr_o=wbs1_adr_o, 176 | wbs1_dat_i=wbs1_dat_i, 177 | wbs1_dat_o=wbs1_dat_o, 178 | wbs1_we_o=wbs1_we_o, 179 | wbs1_sel_o=wbs1_sel_o, 180 | wbs1_stb_o=wbs1_stb_o, 181 | wbs1_ack_i=wbs1_ack_i, 182 | wbs1_err_i=wbs1_err_i, 183 | wbs1_rty_i=wbs1_rty_i, 184 | wbs1_cyc_o=wbs1_cyc_o, 185 | wbs1_addr=wbs1_addr, 186 | wbs1_addr_msk=wbs1_addr_msk 187 | ) 188 | 189 | @always(delay(4)) 190 | def clkgen(): 191 | clk.next = not clk 192 | 193 | @instance 194 | def check(): 195 | yield delay(100) 196 | yield clk.posedge 197 | rst.next = 1 198 | yield clk.posedge 199 | rst.next = 0 200 | yield clk.posedge 201 | yield delay(100) 202 | yield clk.posedge 203 | 204 | wbs0_addr.next = 0x00000000 205 | wbs0_addr_msk.next = 0xFFFF0000 206 | 207 | wbs1_addr.next = 0x00010000 208 | wbs1_addr_msk.next = 0xFFFF0000 209 | 210 | yield clk.posedge 211 | print("test 1: write to slave 0") 212 | current_test.next = 1 213 | 214 | wbm_inst.init_write(0x00000004, b'\x11\x22\x33\x44') 215 | 216 | yield wbm_inst.wait() 217 | yield clk.posedge 218 | 219 | data = wb_ram0_inst.read_mem(0, 32) 220 | for i in range(0, len(data), 16): 221 | print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16])))) 222 | 223 | assert wb_ram0_inst.read_mem(4,4) == b'\x11\x22\x33\x44' 224 | 225 | yield delay(100) 226 | 227 | yield clk.posedge 228 | print("test 2: read from slave 0") 229 | current_test.next = 2 230 | 231 | wbm_inst.init_read(0x00000004, 4) 232 | 233 | yield wbm_inst.wait() 234 | yield clk.posedge 235 | 236 | data = wbm_inst.get_read_data() 237 | assert data[0] == 0x00000004 238 | assert data[1] == b'\x11\x22\x33\x44' 239 | 240 | yield delay(100) 241 | 242 | yield clk.posedge 243 | print("test 3: write to slave 1") 244 | current_test.next = 3 245 | 246 | wbm_inst.init_write(0x00010004, b'\x11\x22\x33\x44') 247 | 248 | yield wbm_inst.wait() 249 | yield clk.posedge 250 | 251 | data = wb_ram1_inst.read_mem(0, 32) 252 | for i in range(0, len(data), 16): 253 | print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16])))) 254 | 255 | assert wb_ram1_inst.read_mem(4,4) == b'\x11\x22\x33\x44' 256 | 257 | yield delay(100) 258 | 259 | yield clk.posedge 260 | print("test 4: read from slave 1") 261 | current_test.next = 4 262 | 263 | wbm_inst.init_read(0x00010004, 4) 264 | 265 | yield wbm_inst.wait() 266 | yield clk.posedge 267 | 268 | data = wbm_inst.get_read_data() 269 | assert data[0] == 0x00010004 270 | assert data[1] == b'\x11\x22\x33\x44' 271 | 272 | yield delay(100) 273 | 274 | raise StopSimulation 275 | 276 | return instances() 277 | 278 | def test_bench(): 279 | sim = Simulation(bench()) 280 | sim.run() 281 | 282 | if __name__ == '__main__': 283 | print("Running test...") 284 | test_bench() 285 | -------------------------------------------------------------------------------- /tb/test_wb_mux_2.v: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2015-2016 Alex Forencich 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | */ 24 | 25 | // Language: Verilog 2001 26 | 27 | `timescale 1ns / 1ps 28 | 29 | /* 30 | * Testbench for wb_mux_2 31 | */ 32 | module test_wb_mux_2; 33 | 34 | // Parameters 35 | parameter DATA_WIDTH = 32; 36 | parameter ADDR_WIDTH = 32; 37 | parameter SELECT_WIDTH = 4; 38 | 39 | // Inputs 40 | reg clk = 0; 41 | reg rst = 0; 42 | reg [7:0] current_test = 0; 43 | 44 | reg [ADDR_WIDTH-1:0] wbm_adr_i = 0; 45 | reg [DATA_WIDTH-1:0] wbm_dat_i = 0; 46 | reg wbm_we_i = 0; 47 | reg [SELECT_WIDTH-1:0] wbm_sel_i = 0; 48 | reg wbm_stb_i = 0; 49 | reg wbm_cyc_i = 0; 50 | reg [DATA_WIDTH-1:0] wbs0_dat_i = 0; 51 | reg wbs0_ack_i = 0; 52 | reg wbs0_err_i = 0; 53 | reg wbs0_rty_i = 0; 54 | reg [ADDR_WIDTH-1:0] wbs0_addr = 0; 55 | reg [ADDR_WIDTH-1:0] wbs0_addr_msk = 0; 56 | reg [DATA_WIDTH-1:0] wbs1_dat_i = 0; 57 | reg wbs1_ack_i = 0; 58 | reg wbs1_err_i = 0; 59 | reg wbs1_rty_i = 0; 60 | reg [ADDR_WIDTH-1:0] wbs1_addr = 0; 61 | reg [ADDR_WIDTH-1:0] wbs1_addr_msk = 0; 62 | 63 | // Outputs 64 | wire [DATA_WIDTH-1:0] wbm_dat_o; 65 | wire wbm_ack_o; 66 | wire wbm_err_o; 67 | wire wbm_rty_o; 68 | wire [ADDR_WIDTH-1:0] wbs0_adr_o; 69 | wire [DATA_WIDTH-1:0] wbs0_dat_o; 70 | wire wbs0_we_o; 71 | wire [SELECT_WIDTH-1:0] wbs0_sel_o; 72 | wire wbs0_stb_o; 73 | wire wbs0_cyc_o; 74 | wire [ADDR_WIDTH-1:0] wbs1_adr_o; 75 | wire [DATA_WIDTH-1:0] wbs1_dat_o; 76 | wire wbs1_we_o; 77 | wire [SELECT_WIDTH-1:0] wbs1_sel_o; 78 | wire wbs1_stb_o; 79 | wire wbs1_cyc_o; 80 | 81 | initial begin 82 | // myhdl integration 83 | $from_myhdl(clk, 84 | rst, 85 | current_test, 86 | wbm_adr_i, 87 | wbm_dat_i, 88 | wbm_we_i, 89 | wbm_sel_i, 90 | wbm_stb_i, 91 | wbm_cyc_i, 92 | wbs0_dat_i, 93 | wbs0_ack_i, 94 | wbs0_err_i, 95 | wbs0_rty_i, 96 | wbs0_addr, 97 | wbs0_addr_msk, 98 | wbs1_dat_i, 99 | wbs1_ack_i, 100 | wbs1_err_i, 101 | wbs1_rty_i, 102 | wbs1_addr, 103 | wbs1_addr_msk); 104 | $to_myhdl(wbm_dat_o, 105 | wbm_ack_o, 106 | wbm_err_o, 107 | wbm_rty_o, 108 | wbs0_adr_o, 109 | wbs0_dat_o, 110 | wbs0_we_o, 111 | wbs0_sel_o, 112 | wbs0_stb_o, 113 | wbs0_cyc_o, 114 | wbs1_adr_o, 115 | wbs1_dat_o, 116 | wbs1_we_o, 117 | wbs1_sel_o, 118 | wbs1_stb_o, 119 | wbs1_cyc_o); 120 | 121 | // dump file 122 | $dumpfile("test_wb_mux_2.lxt"); 123 | $dumpvars(0, test_wb_mux_2); 124 | end 125 | 126 | wb_mux_2 #( 127 | .DATA_WIDTH(DATA_WIDTH), 128 | .ADDR_WIDTH(ADDR_WIDTH), 129 | .SELECT_WIDTH(SELECT_WIDTH) 130 | ) 131 | UUT ( 132 | .clk(clk), 133 | .rst(rst), 134 | .wbm_adr_i(wbm_adr_i), 135 | .wbm_dat_i(wbm_dat_i), 136 | .wbm_dat_o(wbm_dat_o), 137 | .wbm_we_i(wbm_we_i), 138 | .wbm_sel_i(wbm_sel_i), 139 | .wbm_stb_i(wbm_stb_i), 140 | .wbm_ack_o(wbm_ack_o), 141 | .wbm_err_o(wbm_err_o), 142 | .wbm_rty_o(wbm_rty_o), 143 | .wbm_cyc_i(wbm_cyc_i), 144 | .wbs0_adr_o(wbs0_adr_o), 145 | .wbs0_dat_i(wbs0_dat_i), 146 | .wbs0_dat_o(wbs0_dat_o), 147 | .wbs0_we_o(wbs0_we_o), 148 | .wbs0_sel_o(wbs0_sel_o), 149 | .wbs0_stb_o(wbs0_stb_o), 150 | .wbs0_ack_i(wbs0_ack_i), 151 | .wbs0_err_i(wbs0_err_i), 152 | .wbs0_rty_i(wbs0_rty_i), 153 | .wbs0_cyc_o(wbs0_cyc_o), 154 | .wbs0_addr(wbs0_addr), 155 | .wbs0_addr_msk(wbs0_addr_msk), 156 | .wbs1_adr_o(wbs1_adr_o), 157 | .wbs1_dat_i(wbs1_dat_i), 158 | .wbs1_dat_o(wbs1_dat_o), 159 | .wbs1_we_o(wbs1_we_o), 160 | .wbs1_sel_o(wbs1_sel_o), 161 | .wbs1_stb_o(wbs1_stb_o), 162 | .wbs1_ack_i(wbs1_ack_i), 163 | .wbs1_err_i(wbs1_err_i), 164 | .wbs1_rty_i(wbs1_rty_i), 165 | .wbs1_cyc_o(wbs1_cyc_o), 166 | .wbs1_addr(wbs1_addr), 167 | .wbs1_addr_msk(wbs1_addr_msk) 168 | ); 169 | 170 | endmodule 171 | -------------------------------------------------------------------------------- /tb/test_wb_ram.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | 4 | Copyright (c) 2015-2016 Alex Forencich 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | 24 | """ 25 | 26 | from myhdl import * 27 | import os 28 | 29 | import wb 30 | 31 | module = 'wb_ram' 32 | testbench = 'test_%s' % module 33 | 34 | srcs = [] 35 | 36 | srcs.append("../rtl/%s.v" % module) 37 | srcs.append("%s.v" % testbench) 38 | 39 | src = ' '.join(srcs) 40 | 41 | build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) 42 | 43 | def bench(): 44 | 45 | # Parameters 46 | DATA_WIDTH = 32 47 | ADDR_WIDTH = 16 48 | SELECT_WIDTH = 4 49 | 50 | # Inputs 51 | clk = Signal(bool(0)) 52 | rst = Signal(bool(0)) 53 | current_test = Signal(intbv(0)[8:]) 54 | 55 | adr_i = Signal(intbv(0)[ADDR_WIDTH:]) 56 | dat_i = Signal(intbv(0)[DATA_WIDTH:]) 57 | we_i = Signal(bool(0)) 58 | sel_i = Signal(intbv(0)[SELECT_WIDTH:]) 59 | stb_i = Signal(bool(0)) 60 | cyc_i = Signal(bool(0)) 61 | 62 | # Outputs 63 | dat_o = Signal(intbv(0)[DATA_WIDTH:]) 64 | ack_o = Signal(bool(0)) 65 | 66 | # WB master 67 | wbm_inst = wb.WBMaster() 68 | 69 | wbm_logic = wbm_inst.create_logic( 70 | clk, 71 | adr_o=adr_i, 72 | dat_i=dat_o, 73 | dat_o=dat_i, 74 | we_o=we_i, 75 | sel_o=sel_i, 76 | stb_o=stb_i, 77 | ack_i=ack_o, 78 | cyc_o=cyc_i, 79 | name='master' 80 | ) 81 | 82 | # DUT 83 | if os.system(build_cmd): 84 | raise Exception("Error running build command") 85 | 86 | dut = Cosimulation( 87 | "vvp -m myhdl %s.vvp -lxt2" % testbench, 88 | clk=clk, 89 | rst=rst, 90 | current_test=current_test, 91 | adr_i=adr_i, 92 | dat_i=dat_i, 93 | dat_o=dat_o, 94 | we_i=we_i, 95 | sel_i=sel_i, 96 | stb_i=stb_i, 97 | ack_o=ack_o, 98 | cyc_i=cyc_i 99 | ) 100 | 101 | @always(delay(4)) 102 | def clkgen(): 103 | clk.next = not clk 104 | 105 | @instance 106 | def check(): 107 | yield delay(100) 108 | yield clk.posedge 109 | rst.next = 1 110 | yield clk.posedge 111 | rst.next = 0 112 | yield clk.posedge 113 | yield delay(100) 114 | yield clk.posedge 115 | 116 | yield clk.posedge 117 | print("test 1: read and write") 118 | current_test.next = 1 119 | 120 | wbm_inst.init_write(4, b'\x11\x22\x33\x44') 121 | 122 | yield wbm_inst.wait() 123 | yield clk.posedge 124 | 125 | wbm_inst.init_read(4, 4) 126 | 127 | yield wbm_inst.wait() 128 | yield clk.posedge 129 | 130 | data = wbm_inst.get_read_data() 131 | assert data[0] == 4 132 | assert data[1] == b'\x11\x22\x33\x44' 133 | 134 | yield delay(100) 135 | 136 | yield clk.posedge 137 | print("test 2: various reads and writes") 138 | current_test.next = 2 139 | 140 | for length in range(1,8): 141 | for offset in range(4): 142 | wbm_inst.init_write(256*(16*offset+length)+offset, b'\x11\x22\x33\x44\x55\x66\x77\x88'[0:length]) 143 | 144 | yield wbm_inst.wait() 145 | yield clk.posedge 146 | 147 | for length in range(1,8): 148 | for offset in range(4): 149 | wbm_inst.init_read(256*(16*offset+length)+offset, length) 150 | 151 | yield wbm_inst.wait() 152 | yield clk.posedge 153 | 154 | data = wbm_inst.get_read_data() 155 | assert data[0] == 256*(16*offset+length)+offset 156 | assert data[1] == b'\x11\x22\x33\x44\x55\x66\x77\x88'[0:length] 157 | 158 | yield delay(100) 159 | 160 | raise StopSimulation 161 | 162 | return instances() 163 | 164 | def test_bench(): 165 | sim = Simulation(bench()) 166 | sim.run() 167 | 168 | if __name__ == '__main__': 169 | print("Running test...") 170 | test_bench() 171 | -------------------------------------------------------------------------------- /tb/test_wb_ram.v: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2015-2016 Alex Forencich 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | */ 24 | 25 | // Language: Verilog 2001 26 | 27 | `timescale 1ns / 1ps 28 | 29 | /* 30 | * Testbench for wb_ram 31 | */ 32 | module test_wb_ram; 33 | 34 | // Parameters 35 | parameter DATA_WIDTH = 32; 36 | parameter ADDR_WIDTH = 16; 37 | parameter SELECT_WIDTH = 4; 38 | 39 | // Inputs 40 | reg clk = 0; 41 | reg rst = 0; 42 | reg [7:0] current_test = 0; 43 | 44 | reg [ADDR_WIDTH-1:0] adr_i = 0; 45 | reg [DATA_WIDTH-1:0] dat_i = 0; 46 | reg we_i = 0; 47 | reg [SELECT_WIDTH-1:0] sel_i = 0; 48 | reg stb_i = 0; 49 | reg cyc_i = 0; 50 | 51 | // Outputs 52 | wire [DATA_WIDTH-1:0] dat_o; 53 | wire ack_o; 54 | 55 | initial begin 56 | // myhdl integration 57 | $from_myhdl( 58 | clk, 59 | rst, 60 | current_test, 61 | adr_i, 62 | dat_i, 63 | we_i, 64 | sel_i, 65 | stb_i, 66 | cyc_i 67 | ); 68 | $to_myhdl( 69 | dat_o, 70 | ack_o 71 | ); 72 | 73 | // dump file 74 | $dumpfile("test_wb_ram.lxt"); 75 | $dumpvars(0, test_wb_ram); 76 | end 77 | 78 | wb_ram #( 79 | .DATA_WIDTH(DATA_WIDTH), 80 | .ADDR_WIDTH(ADDR_WIDTH), 81 | .SELECT_WIDTH(SELECT_WIDTH) 82 | ) 83 | UUT ( 84 | .clk(clk), 85 | .adr_i(adr_i), 86 | .dat_i(dat_i), 87 | .dat_o(dat_o), 88 | .we_i(we_i), 89 | .sel_i(sel_i), 90 | .stb_i(stb_i), 91 | .ack_o(ack_o), 92 | .cyc_i(cyc_i) 93 | ); 94 | 95 | endmodule 96 | -------------------------------------------------------------------------------- /tb/test_wb_ram_model.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | 4 | Copyright (c) 2015-2016 Alex Forencich 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | 24 | """ 25 | 26 | from myhdl import * 27 | import os 28 | 29 | import wb 30 | 31 | def bench(): 32 | 33 | # Inputs 34 | clk = Signal(bool(0)) 35 | rst = Signal(bool(0)) 36 | current_test = Signal(intbv(0)[8:]) 37 | 38 | port0_adr_i = Signal(intbv(0)[32:]) 39 | port0_dat_i = Signal(intbv(0)[32:]) 40 | port0_we_i = Signal(bool(0)) 41 | port0_sel_i = Signal(intbv(0)[4:]) 42 | port0_stb_i = Signal(bool(0)) 43 | port0_cyc_i = Signal(bool(0)) 44 | 45 | # Outputs 46 | port0_dat_o = Signal(intbv(0)[32:]) 47 | port0_ack_o = Signal(bool(0)) 48 | 49 | # WB RAM model 50 | wb_ram_inst = wb.WBRam(2**16) 51 | 52 | wb_ram_port0 = wb_ram_inst.create_port( 53 | clk, 54 | adr_i=port0_adr_i, 55 | dat_i=port0_dat_i, 56 | dat_o=port0_dat_o, 57 | we_i=port0_we_i, 58 | sel_i=port0_sel_i, 59 | stb_i=port0_stb_i, 60 | ack_o=port0_ack_o, 61 | cyc_i=port0_cyc_i, 62 | latency=1, 63 | asynchronous=False, 64 | name='port0' 65 | ) 66 | 67 | @always(delay(4)) 68 | def clkgen(): 69 | clk.next = not clk 70 | 71 | @instance 72 | def check(): 73 | yield delay(100) 74 | yield clk.posedge 75 | rst.next = 1 76 | yield clk.posedge 77 | rst.next = 0 78 | yield clk.posedge 79 | yield delay(100) 80 | yield clk.posedge 81 | 82 | yield clk.posedge 83 | print("test 1: baseline") 84 | current_test.next = 1 85 | 86 | data = wb_ram_inst.read_mem(0, 32) 87 | for i in range(0, len(data), 16): 88 | print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16])))) 89 | 90 | yield delay(100) 91 | 92 | yield clk.posedge 93 | print("test 2: direct write") 94 | current_test.next = 2 95 | 96 | wb_ram_inst.write_mem(0, b'test') 97 | 98 | data = wb_ram_inst.read_mem(0, 32) 99 | for i in range(0, len(data), 16): 100 | print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16])))) 101 | 102 | assert wb_ram_inst.read_mem(0,4) == b'test' 103 | 104 | yield delay(100) 105 | 106 | yield clk.posedge 107 | print("test 2: write via port0") 108 | current_test.next = 2 109 | 110 | yield clk.posedge 111 | port0_adr_i.next = 4 112 | port0_dat_i.next = 0x44332211 113 | port0_sel_i.next = 0xF 114 | port0_we_i.next = 1 115 | 116 | port0_cyc_i.next = 1 117 | port0_stb_i.next = 1 118 | 119 | yield port0_ack_o.posedge 120 | yield clk.posedge 121 | port0_we_i.next = 0 122 | port0_cyc_i.next = 0 123 | port0_stb_i.next = 0 124 | 125 | yield clk.posedge 126 | yield clk.posedge 127 | 128 | data = wb_ram_inst.read_mem(0, 32) 129 | for i in range(0, len(data), 16): 130 | print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16])))) 131 | 132 | assert wb_ram_inst.read_mem(4,4) == b'\x11\x22\x33\x44' 133 | 134 | yield delay(100) 135 | 136 | yield clk.posedge 137 | print("test 3: read via port0") 138 | current_test.next = 3 139 | 140 | yield clk.posedge 141 | port0_adr_i.next = 4 142 | port0_we_i.next = 0 143 | 144 | port0_cyc_i.next = 1 145 | port0_stb_i.next = 1 146 | 147 | yield port0_ack_o.posedge 148 | yield clk.posedge 149 | port0_we_i.next = 0 150 | port0_cyc_i.next = 0 151 | port0_stb_i.next = 0 152 | 153 | assert port0_dat_o == 0x44332211 154 | 155 | yield delay(100) 156 | 157 | yield clk.posedge 158 | print("test 4: various writes") 159 | current_test.next = 4 160 | 161 | for length in range(1,8): 162 | for offset in range(4): 163 | yield clk.posedge 164 | sel_start = ((2**(4)-1) << offset % 4) & (2**(4)-1) 165 | sel_end = ((2**(4)-1) >> (4 - (((offset + int(length/1) - 1) % 4) + 1))) 166 | cycles = int((length + 4-1 + (offset % 4)) / 4) 167 | i = 1 168 | 169 | port0_cyc_i.next = 1 170 | 171 | port0_stb_i.next = 1 172 | port0_we_i.next = 1 173 | port0_adr_i.next = 256*(16*offset+length) 174 | val = 0 175 | for j in range(4): 176 | if j >= offset % 4 and (cycles > 1 or j < (((offset + int(length/1) - 1) % 4) + 1)): 177 | val |= (0x11 * i) << j*8 178 | i += 1 179 | port0_dat_i.next = val 180 | if cycles == 1: 181 | port0_sel_i.next = sel_start & sel_end 182 | else: 183 | port0_sel_i.next = sel_start 184 | 185 | yield clk.posedge 186 | while not port0_ack_o: 187 | yield clk.posedge 188 | 189 | port0_we_i.next = 0 190 | port0_stb_i.next = 0 191 | 192 | for k in range(1,cycles-1): 193 | yield clk.posedge 194 | port0_stb_i.next = 1 195 | port0_we_i.next = 1 196 | port0_adr_i.next = 256*(16*offset+length)+4*k 197 | val = 0 198 | for j in range(4): 199 | val |= (0x11 * i) << j*8 200 | i += 1 201 | port0_dat_i.next = val 202 | port0_sel_i.next = 2**(4)-1 203 | 204 | yield clk.posedge 205 | while not port0_ack_o: 206 | yield clk.posedge 207 | 208 | port0_we_i.next = 0 209 | port0_stb_i.next = 0 210 | 211 | if cycles > 1: 212 | yield clk.posedge 213 | port0_stb_i.next = 1 214 | port0_we_i.next = 1 215 | port0_adr_i.next = 256*(16*offset+length)+4*(cycles-1) 216 | val = 0 217 | for j in range(4): 218 | if j < (((offset + int(length/1) - 1) % 4) + 1): 219 | val |= (0x11 * i) << j*8 220 | i += 1 221 | port0_dat_i.next = val 222 | port0_sel_i.next = sel_end 223 | 224 | yield clk.posedge 225 | while not port0_ack_o: 226 | yield clk.posedge 227 | 228 | port0_we_i.next = 0 229 | port0_stb_i.next = 0 230 | 231 | port0_we_i.next = 0 232 | port0_stb_i.next = 0 233 | 234 | port0_cyc_i.next = 0 235 | 236 | yield clk.posedge 237 | yield clk.posedge 238 | 239 | data = wb_ram_inst.read_mem(256*(16*offset+length), 32) 240 | for i in range(0, len(data), 16): 241 | print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16])))) 242 | 243 | assert wb_ram_inst.read_mem(256*(16*offset+length)+offset,length) == b'\x11\x22\x33\x44\x55\x66\x77\x88'[0:length] 244 | 245 | yield delay(100) 246 | 247 | raise StopSimulation 248 | 249 | return instances() 250 | 251 | def test_bench(): 252 | os.chdir(os.path.dirname(os.path.abspath(__file__))) 253 | sim = Simulation(bench()) 254 | sim.run() 255 | 256 | if __name__ == '__main__': 257 | print("Running test...") 258 | test_bench() 259 | 260 | -------------------------------------------------------------------------------- /tb/test_wb_reg.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | 4 | Copyright (c) 2015-2016 Alex Forencich 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | 24 | """ 25 | 26 | from myhdl import * 27 | import os 28 | 29 | import wb 30 | 31 | module = 'wb_reg' 32 | testbench = 'test_%s' % module 33 | 34 | srcs = [] 35 | 36 | srcs.append("../rtl/%s.v" % module) 37 | srcs.append("%s.v" % testbench) 38 | 39 | src = ' '.join(srcs) 40 | 41 | build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) 42 | 43 | def bench(): 44 | 45 | # Parameters 46 | DATA_WIDTH = 32 47 | ADDR_WIDTH = 32 48 | SELECT_WIDTH = 4 49 | 50 | # Inputs 51 | clk = Signal(bool(0)) 52 | rst = Signal(bool(0)) 53 | current_test = Signal(intbv(0)[8:]) 54 | 55 | wbm_adr_i = Signal(intbv(0)[ADDR_WIDTH:]) 56 | wbm_dat_i = Signal(intbv(0)[DATA_WIDTH:]) 57 | wbm_we_i = Signal(bool(0)) 58 | wbm_sel_i = Signal(intbv(0)[SELECT_WIDTH:]) 59 | wbm_stb_i = Signal(bool(0)) 60 | wbm_cyc_i = Signal(bool(0)) 61 | wbs_dat_i = Signal(intbv(0)[DATA_WIDTH:]) 62 | wbs_ack_i = Signal(bool(0)) 63 | wbs_err_i = Signal(bool(0)) 64 | wbs_rty_i = Signal(bool(0)) 65 | 66 | # Outputs 67 | wbm_dat_o = Signal(intbv(0)[DATA_WIDTH:]) 68 | wbm_ack_o = Signal(bool(0)) 69 | wbm_err_o = Signal(bool(0)) 70 | wbm_rty_o = Signal(bool(0)) 71 | wbs_adr_o = Signal(intbv(0)[ADDR_WIDTH:]) 72 | wbs_dat_o = Signal(intbv(0)[DATA_WIDTH:]) 73 | wbs_we_o = Signal(bool(0)) 74 | wbs_sel_o = Signal(intbv(0)[SELECT_WIDTH:]) 75 | wbs_stb_o = Signal(bool(0)) 76 | wbs_cyc_o = Signal(bool(0)) 77 | 78 | # WB master 79 | wbm_inst = wb.WBMaster() 80 | 81 | wbm_logic = wbm_inst.create_logic( 82 | clk, 83 | adr_o=wbm_adr_i, 84 | dat_i=wbm_dat_o, 85 | dat_o=wbm_dat_i, 86 | we_o=wbm_we_i, 87 | sel_o=wbm_sel_i, 88 | stb_o=wbm_stb_i, 89 | ack_i=wbm_ack_o, 90 | cyc_o=wbm_cyc_i, 91 | name='master' 92 | ) 93 | 94 | # WB RAM model 95 | wb_ram_inst = wb.WBRam(2**16) 96 | 97 | wb_ram_port0 = wb_ram_inst.create_port( 98 | clk, 99 | adr_i=wbs_adr_o, 100 | dat_i=wbs_dat_o, 101 | dat_o=wbs_dat_i, 102 | we_i=wbs_we_o, 103 | sel_i=wbs_sel_o, 104 | stb_i=wbs_stb_o, 105 | ack_o=wbs_ack_i, 106 | cyc_i=wbs_cyc_o, 107 | latency=1, 108 | asynchronous=False, 109 | name='slave' 110 | ) 111 | 112 | # DUT 113 | if os.system(build_cmd): 114 | raise Exception("Error running build command") 115 | 116 | dut = Cosimulation( 117 | "vvp -m myhdl %s.vvp -lxt2" % testbench, 118 | clk=clk, 119 | rst=rst, 120 | current_test=current_test, 121 | wbm_adr_i=wbm_adr_i, 122 | wbm_dat_i=wbm_dat_i, 123 | wbm_dat_o=wbm_dat_o, 124 | wbm_we_i=wbm_we_i, 125 | wbm_sel_i=wbm_sel_i, 126 | wbm_stb_i=wbm_stb_i, 127 | wbm_ack_o=wbm_ack_o, 128 | wbm_err_o=wbm_err_o, 129 | wbm_rty_o=wbm_rty_o, 130 | wbm_cyc_i=wbm_cyc_i, 131 | wbs_adr_o=wbs_adr_o, 132 | wbs_dat_i=wbs_dat_i, 133 | wbs_dat_o=wbs_dat_o, 134 | wbs_we_o=wbs_we_o, 135 | wbs_sel_o=wbs_sel_o, 136 | wbs_stb_o=wbs_stb_o, 137 | wbs_ack_i=wbs_ack_i, 138 | wbs_err_i=wbs_err_i, 139 | wbs_rty_i=wbs_rty_i, 140 | wbs_cyc_o=wbs_cyc_o 141 | ) 142 | 143 | @always(delay(4)) 144 | def clkgen(): 145 | clk.next = not clk 146 | 147 | @instance 148 | def check(): 149 | yield delay(100) 150 | yield clk.posedge 151 | rst.next = 1 152 | yield clk.posedge 153 | rst.next = 0 154 | yield clk.posedge 155 | yield delay(100) 156 | yield clk.posedge 157 | 158 | yield clk.posedge 159 | print("test 1: write") 160 | current_test.next = 1 161 | 162 | wbm_inst.init_write(4, b'\x11\x22\x33\x44') 163 | 164 | yield wbm_inst.wait() 165 | yield clk.posedge 166 | 167 | data = wb_ram_inst.read_mem(0, 32) 168 | for i in range(0, len(data), 16): 169 | print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16])))) 170 | 171 | assert wb_ram_inst.read_mem(4,4) == b'\x11\x22\x33\x44' 172 | 173 | yield delay(100) 174 | 175 | yield clk.posedge 176 | print("test 2: read") 177 | current_test.next = 2 178 | 179 | wbm_inst.init_read(4, 4) 180 | 181 | yield wbm_inst.wait() 182 | yield clk.posedge 183 | 184 | data = wbm_inst.get_read_data() 185 | assert data[0] == 4 186 | assert data[1] == b'\x11\x22\x33\x44' 187 | 188 | yield delay(100) 189 | 190 | yield clk.posedge 191 | print("test 3: various writes") 192 | current_test.next = 3 193 | 194 | for length in range(1,8): 195 | for offset in range(4,8): 196 | wb_ram_inst.write_mem(256*(16*offset+length), b'\xAA'*32) 197 | wbm_inst.init_write(256*(16*offset+length)+offset, b'\x11\x22\x33\x44\x55\x66\x77\x88'[0:length]) 198 | 199 | yield wbm_inst.wait() 200 | yield clk.posedge 201 | 202 | data = wb_ram_inst.read_mem(256*(16*offset+length), 32) 203 | for i in range(0, len(data), 16): 204 | print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16])))) 205 | 206 | assert wb_ram_inst.read_mem(256*(16*offset+length)+offset, length) == b'\x11\x22\x33\x44\x55\x66\x77\x88'[0:length] 207 | assert wb_ram_inst.read_mem(256*(16*offset+length)+offset-1, 1) == b'\xAA' 208 | assert wb_ram_inst.read_mem(256*(16*offset+length)+offset+length, 1) == b'\xAA' 209 | 210 | yield delay(100) 211 | 212 | yield clk.posedge 213 | print("test 4: various reads") 214 | current_test.next = 4 215 | 216 | for length in range(1,8): 217 | for offset in range(4,8): 218 | wbm_inst.init_read(256*(16*offset+length)+offset, length) 219 | 220 | yield wbm_inst.wait() 221 | yield clk.posedge 222 | 223 | data = wbm_inst.get_read_data() 224 | assert data[0] == 256*(16*offset+length)+offset 225 | assert data[1] == b'\x11\x22\x33\x44\x55\x66\x77\x88'[0:length] 226 | 227 | yield delay(100) 228 | 229 | raise StopSimulation 230 | 231 | return instances() 232 | 233 | def test_bench(): 234 | sim = Simulation(bench()) 235 | sim.run() 236 | 237 | if __name__ == '__main__': 238 | print("Running test...") 239 | test_bench() 240 | -------------------------------------------------------------------------------- /tb/test_wb_reg.v: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2015-2016 Alex Forencich 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | */ 24 | 25 | // Language: Verilog 2001 26 | 27 | `timescale 1ns / 1ps 28 | 29 | /* 30 | * Testbench for wb_reg 31 | */ 32 | module test_wb_reg; 33 | 34 | // Parameters 35 | parameter DATA_WIDTH = 32; 36 | parameter ADDR_WIDTH = 32; 37 | parameter SELECT_WIDTH = 4; 38 | 39 | // Inputs 40 | reg clk = 0; 41 | reg rst = 0; 42 | reg [7:0] current_test = 0; 43 | 44 | reg [ADDR_WIDTH-1:0] wbm_adr_i = 0; 45 | reg [DATA_WIDTH-1:0] wbm_dat_i = 0; 46 | reg wbm_we_i = 0; 47 | reg [SELECT_WIDTH-1:0] wbm_sel_i = 0; 48 | reg wbm_stb_i = 0; 49 | reg wbm_cyc_i = 0; 50 | reg [DATA_WIDTH-1:0] wbs_dat_i = 0; 51 | reg wbs_ack_i = 0; 52 | reg wbs_err_i = 0; 53 | reg wbs_rty_i = 0; 54 | 55 | // Outputs 56 | wire [DATA_WIDTH-1:0] wbm_dat_o; 57 | wire wbm_ack_o; 58 | wire wbm_err_o; 59 | wire wbm_rty_o; 60 | wire [ADDR_WIDTH-1:0] wbs_adr_o; 61 | wire [DATA_WIDTH-1:0] wbs_dat_o; 62 | wire wbs_we_o; 63 | wire [SELECT_WIDTH-1:0] wbs_sel_o; 64 | wire wbs_stb_o; 65 | wire wbs_cyc_o; 66 | 67 | initial begin 68 | // myhdl integration 69 | $from_myhdl( 70 | clk, 71 | rst, 72 | current_test, 73 | wbm_adr_i, 74 | wbm_dat_i, 75 | wbm_we_i, 76 | wbm_sel_i, 77 | wbm_stb_i, 78 | wbm_cyc_i, 79 | wbs_dat_i, 80 | wbs_ack_i, 81 | wbs_err_i, 82 | wbs_rty_i 83 | ); 84 | $to_myhdl( 85 | wbm_dat_o, 86 | wbm_ack_o, 87 | wbm_err_o, 88 | wbm_rty_o, 89 | wbs_adr_o, 90 | wbs_dat_o, 91 | wbs_we_o, 92 | wbs_sel_o, 93 | wbs_stb_o, 94 | wbs_cyc_o 95 | ); 96 | 97 | // dump file 98 | $dumpfile("test_wb_reg.lxt"); 99 | $dumpvars(0, test_wb_reg); 100 | end 101 | 102 | wb_reg #( 103 | .DATA_WIDTH(DATA_WIDTH), 104 | .ADDR_WIDTH(ADDR_WIDTH), 105 | .SELECT_WIDTH(SELECT_WIDTH) 106 | ) 107 | UUT ( 108 | .clk(clk), 109 | .rst(rst), 110 | .wbm_adr_i(wbm_adr_i), 111 | .wbm_dat_i(wbm_dat_i), 112 | .wbm_dat_o(wbm_dat_o), 113 | .wbm_we_i(wbm_we_i), 114 | .wbm_sel_i(wbm_sel_i), 115 | .wbm_stb_i(wbm_stb_i), 116 | .wbm_ack_o(wbm_ack_o), 117 | .wbm_err_o(wbm_err_o), 118 | .wbm_rty_o(wbm_rty_o), 119 | .wbm_cyc_i(wbm_cyc_i), 120 | .wbs_adr_o(wbs_adr_o), 121 | .wbs_dat_i(wbs_dat_i), 122 | .wbs_dat_o(wbs_dat_o), 123 | .wbs_we_o(wbs_we_o), 124 | .wbs_sel_o(wbs_sel_o), 125 | .wbs_stb_o(wbs_stb_o), 126 | .wbs_ack_i(wbs_ack_i), 127 | .wbs_err_i(wbs_err_i), 128 | .wbs_rty_i(wbs_rty_i), 129 | .wbs_cyc_o(wbs_cyc_o) 130 | ); 131 | 132 | endmodule 133 | --------------------------------------------------------------------------------