aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel V. Shatov (Meister) <meisterpaul1@yandex.ru>2018-07-05 21:45:32 +0300
committerPavel V. Shatov (Meister) <meisterpaul1@yandex.ru>2018-07-05 21:45:32 +0300
commit63b846cc8039b8de6dd58295e550e384d19f4b46 (patch)
tree1b1aa0dac208ce4b014e01c78b9b16d0d071d134
parent1ab18ea4258a4e614422d66905776d8d8302b841 (diff)
Added testbench to mimic STM32's FMC side.
-rw-r--r--src/tb/tb_fmc.v265
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
+//------------------------------------------------------------------------------