diff options
author | Pavel V. Shatov (Meister) <meisterpaul1@yandex.ru> | 2018-07-05 21:45:32 +0300 |
---|---|---|
committer | Pavel V. Shatov (Meister) <meisterpaul1@yandex.ru> | 2018-07-05 21:45:32 +0300 |
commit | 63b846cc8039b8de6dd58295e550e384d19f4b46 (patch) | |
tree | 1b1aa0dac208ce4b014e01c78b9b16d0d071d134 | |
parent | 1ab18ea4258a4e614422d66905776d8d8302b841 (diff) |
Added testbench to mimic STM32's FMC side.
-rw-r--r-- | src/tb/tb_fmc.v | 265 |
1 files changed, 265 insertions, 0 deletions
diff --git a/src/tb/tb_fmc.v b/src/tb/tb_fmc.v new file mode 100644 index 0000000..20b602c --- /dev/null +++ b/src/tb/tb_fmc.v @@ -0,0 +1,265 @@ +//------------------------------------------------------------------------------ +// +// tb_fmc.v +// ----------------------------------------------------------------------------- +// Testbench for fixed latency FMC arbiter. +// +// Authors: Pavel Shatov +// +// Copyright (c) 2018, NORDUnet A/S +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// - Neither the name of the NORDUnet nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +`timescale 1ns / 1ps +//------------------------------------------------------------------------------ + +module tb_fmc; + + + // + // Clock (100 MHz) + // + localparam CLOCK_PERIOD = 10.0; + localparam HALF_CLOCK_PERIOD = 0.5 * CLOCK_PERIOD; + + reg clk_fmc = 1'b0; + //reg clk_45 = 1'b0; + //reg clk_90 = 1'b0; + + initial begin + forever #HALF_CLOCK_PERIOD clk_fmc = ~clk_fmc; + end + + wire clk_45 = clk_fmc; + wire clk_90 = clk_fmc; + + //initial begin + //#1.25; + //forever #HALF_CLOCK_PERIOD clk_45 = ~clk_45; + //end + + //initial begin + //#2.5; + //forever #HALF_CLOCK_PERIOD clk_90 = ~clk_90; + //end + + + // + // FMC Arbiter - FPGA Side + // + wire [23: 0] sys_fmc_addr; + wire sys_fmc_wren; + wire sys_fmc_rden; + wire [31: 0] sys_fmc_dout; + reg [31: 0] sys_fmc_din; + + reg [23: 0] fmc_a = {24{1'bX}}; + reg [31: 0] fmc_d_drive; + wire [31: 0] fmc_d_bidir; + reg fmc_ne1 = 1'b1; + reg fmc_noe = 1'b1; + reg fmc_nwe = 1'b1; + reg fmc_nl = 1'b1; + wire fmc_nwait_dummy; + + assign fmc_d_bidir = fmc_noe ? fmc_d_drive : 32'hZZZZZZZZ; + + fmc_arbiter #(.NUM_ADDR_BITS(24)) + uut + ( + // fmc bus + .fmc_a (fmc_a), + .fmc_d (fmc_d_bidir), + .fmc_ne1 (fmc_ne1), + .fmc_nl (fmc_nl), + .fmc_nwe (fmc_nwe), + .fmc_noe (fmc_noe), + .fmc_nwait (fmc_nwait_dummy), + + // system clock + .sys_clk (clk_45), + .fmc_clk_aux (clk_90), + + // user bus + .sys_addr (sys_fmc_addr), + .sys_wr_en (sys_fmc_wren), + .sys_data_out (sys_fmc_dout), + .sys_rd_en (sys_fmc_rden), + .sys_data_in (sys_fmc_din) + ); + + + // + // Helper Tasks + // + task wait_ticks; + input integer num_ticks; + integer cnt; + begin + for (cnt=0; cnt<num_ticks; cnt=cnt+1) + #CLOCK_PERIOD; + end + endtask + + task wait_half_tick; + begin + #HALF_CLOCK_PERIOD; + end + endtask + + task fmc_write; + input [23: 0] addr; + input [31: 0] data; + begin + fmc_ne1 = 1'b0; // select + fmc_nl = 1'b0; // set latch flag + fmc_a = addr; // set address + fmc_nwe = 1'b0; // set write-enable + wait_ticks(1); // mimic latency + + fmc_nl = 1'b1; // clear latch flag + fmc_a = {24{1'bX}}; // clear address + + wait_ticks(3); // mimic latency + + fmc_d_drive = data; // set data + + wait_ticks(1); // mimic latency + + fmc_ne1 = 1'b1; // deselect + fmc_nwe = 1'b1; // clear write-enable + fmc_d_drive = 32'hXXXXXXXX; // clear data + + wait_ticks(1); // pause + end + endtask + + task fmc_read; + input [23: 0] addr; + output [31: 0] data; + begin + fmc_ne1 = 1'b0; // select + fmc_nl = 1'b0; // set latch flag + fmc_a = addr; // set address + + wait_ticks(1); // mimic latency + + fmc_nl = 1'b1; // clear latch flag + fmc_a = {24{1'bX}}; // clear address + + wait_ticks(1); // mimic latency + + fmc_noe = 1'b0; // tri-state bus + + wait_ticks(3); // mimic latency + wait_half_tick(); // mimic latency + data = fmc_d_bidir; // sample data + wait_half_tick(); // mimic latency + + wait_ticks(2); // mimic bus turnaround + + fmc_ne1 = 1'b1; // deselect + fmc_noe = 1'b1; // drive bus + + wait_ticks(1); // pause + end + endtask + + + // + // Script + // + reg [31:0] data; + initial begin + + wait_ticks(200); + + fmc_write(24'h223344, 32'hCCAA5533); + fmc_write(24'h667788, 32'hEDCBEDCB); + fmc_write(24'h223344, 32'hCCAA5533); + fmc_write(24'h667788, 32'hEDCBEDCB); + + fmc_read(24'h223344, data); + fmc_read(24'h667788, data); + fmc_read(24'h223344, data); + fmc_read(24'h667788, data); + + fmc_write(24'h223344, 32'hCCAA5533); + fmc_write(24'h667788, 32'hEDCBEDCB); + fmc_write(24'h223344, 32'hCCAA5533); + fmc_write(24'h667788, 32'hEDCBEDCB); + + fmc_read(24'h223344, data); + fmc_read(24'h667788, data); + fmc_read(24'h223344, data); + fmc_read(24'h667788, data); + + end + + + + // + // Demo Registers + // + reg [31: 0] reg_test_a; + reg [31: 0] reg_test_b; + reg [31: 0] reg_test_c; + + always @(posedge clk_45) + // + if (sys_fmc_wren) + // + case (sys_fmc_addr) + 24'h000000: reg_test_a <= sys_fmc_dout; + 24'hFFFFFF: reg_test_c <= sys_fmc_dout; + default: reg_test_b <= sys_fmc_dout; + endcase + + always @(posedge clk_45) + // + if (sys_fmc_rden) + // + case (sys_fmc_addr) + 24'h000000: sys_fmc_din <= reg_test_a; + 24'hFFFFFF: sys_fmc_din <= reg_test_c; + default: sys_fmc_din <= reg_test_b; + endcase + // + else + // + sys_fmc_din <= 32'hXXXXXXXX; + + +endmodule + + +//------------------------------------------------------------------------------ +// End-of-File +//------------------------------------------------------------------------------ |