[Cryptech-Commits] [core/comm/fmc] 03/04: New testbench with two clocks.

git at cryptech.is git at cryptech.is
Tue Feb 11 13:05:21 UTC 2020


This is an automated email from the git hooks/post-receive script.

meisterpaul1 at yandex.ru pushed a commit to branch master
in repository core/comm/fmc.

commit 80b3adbe1994a95a18a29188b09345164061b46f
Author: Pavel V. Shatov (Meister) <meisterpaul1 at yandex.ru>
AuthorDate: Tue Jan 21 15:26:36 2020 +0300

    New testbench with two clocks.
---
 src/tb/tb_fmc.v | 522 +++++++++++++++++++++++++++++++++-----------------------
 1 file changed, 307 insertions(+), 215 deletions(-)

diff --git a/src/tb/tb_fmc.v b/src/tb/tb_fmc.v
index 20b602c..ba436b9 100644
--- a/src/tb/tb_fmc.v
+++ b/src/tb/tb_fmc.v
@@ -6,7 +6,7 @@
 //
 // Authors: Pavel Shatov
 //
-// Copyright (c) 2018, NORDUnet A/S
+// Copyright (c) 2018-2019, NORDUnet A/S
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are met:
@@ -43,220 +43,312 @@
 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;
-			
-		
+    //
+    // Settings
+    //
+    localparam NUM_TESTS = 100;
+    
+    
+    localparam integer STM32_FMC_LATENCY = 4;
+
+    //
+    // Clock
+    //
+    
+    /* actual hardware uses 45 MHz, we use 50 for convenience */
+    
+    localparam FMC_CLOCK_PERIOD         = 20.0;
+    localparam FMC_CLOCK_PERIOD_HALF    = 0.5 * FMC_CLOCK_PERIOD;
+    localparam FMC_CLOCK_PERIOD_QUARTER = 0.5 * FMC_CLOCK_PERIOD_HALF;
+
+    reg fmc_clk = 1'b0;
+
+    initial forever #FMC_CLOCK_PERIOD_HALF fmc_clk = ~fmc_clk;
+
+
+    //
+    // Clock Manager
+    //    
+    wire io_clk;    
+    wire sys_clk;
+    wire sys_rst_n;
+    wire core_clk;
+    
+    alpha_clkmgr clkmgr_inst
+    (
+        .fmc_clk     (fmc_clk),
+
+        .io_clk      (io_clk),
+        .sys_clk     (sys_clk),
+        .sys_rst_n   (sys_rst_n),
+        .core_clk    (core_clk)
+    );
+
+
+    //
+    // 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;
+
+
+    //
+    // FMC Arbiter - STM32 Side
+    //
+    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, i/o clock
+        .io_clk  (io_clk),
+        .sys_clk (sys_clk),
+
+        // 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)
+    );
+
+
+    //
+    // "Random" Number Generator
+    //
+    reg [7:0] lfsr8;
+    
+    task lfsr8_next;
+        lfsr8 = {lfsr8[6:0], lfsr8[8-1] ^ lfsr8[6-1] ^ lfsr8[5-1] ^ lfsr8[4-1]};
+    endtask
+
+    task lfsr8_seed;
+        input [7:0] lfsr8_in;
+        lfsr8 = lfsr8_in;
+    endtask
+    
+
+    //
+    // Helper Tasks
+    //
+    
+    //----------------------
+    task  wait_quarter_tick;
+    //----------------------
+        #FMC_CLOCK_PERIOD_QUARTER;
+    endtask
+
+    //------------------
+    task wait_half_tick;
+    //------------------
+        begin
+            wait_quarter_tick;
+            wait_quarter_tick;
+        end
+    endtask
+
+    //------------------
+    task wait_full_tick;
+    //------------------
+        begin
+            wait_half_tick;
+            wait_half_tick;
+        end
+    endtask
+
+    //----------------
+    task wait_n_ticks;
+    //----------------
+        input integer n;
+        integer i;
+        for (i=0; i<n; i=i+1)
+            wait_full_tick;
+    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_full_tick();                   // mimic latency
+
+            fmc_nl = 1'b1;                      // clear latch flag
+            fmc_a = {24{1'bX}};                 // clear address
+            wait_n_ticks(STM32_FMC_LATENCY);    // mimic latency
+
+            fmc_d_drive = data;                 // set data            
+
+            wait_half_tick();                   // mimic latency
+            wait_quarter_tick();
+
+            fmc_ne1 = 1'b1;                     // deselect
+            fmc_nwe = 1'b1;                     // clear write-enable
+            fmc_d_drive = 32'hXXXXXXXX;         // clear data
+
+            wait_quarter_tick();                // finish clock period
+            wait_full_tick();                   // 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_full_tick();                   // mimic latency
+
+            fmc_nl = 1'b1;                      // clear latch flag
+            fmc_a = {24{1'bX}};                 // clear address
+            wait_full_tick();                   // mimic latency
+            fmc_noe = 1'b0;                     // tri-state bus
+            wait_n_ticks(STM32_FMC_LATENCY-1);  // mimic latency
+
+            wait_half_tick();                   // mimic latency
+            data = fmc_d_bidir;                 // sample data
+            wait_half_tick();                   // mimic latency
+            
+            wait_full_tick();                   // mimic latency
+            
+            wait_half_tick();                   // mimic latency
+            wait_quarter_tick();
+
+            fmc_ne1 = 1'b1;                     // deselect
+            fmc_noe = 1'b1;                     // drive bus
+
+            wait_quarter_tick();                // finish clock period
+            wait_full_tick();                   // pause
+        end
+    endtask
+    
+    //----------------
+    task gen_rnd_addr;
+    //----------------
+        output [31:0] addr;
+        reg [7:0] a, b, c;
+        begin
+            lfsr8_next; a = lfsr8;
+            lfsr8_next; b = lfsr8;
+            lfsr8_next; c = lfsr8;
+            addr = {a, b, c};
+        end
+    endtask
+    
+    //----------------
+    task gen_rnd_data;
+    //----------------
+        output [31:0] data;
+        reg [7:0] a, b, c, d;
+        begin
+            lfsr8_next; a = lfsr8;
+            lfsr8_next; b = lfsr8;
+            lfsr8_next; c = lfsr8;
+            lfsr8_next; d = lfsr8;
+            data = {a, b, c, d};
+        end
+    endtask
+
+
+    //
+    // Script
+    //
+    reg [23:0] addr;
+    reg [31:0] data_wr;
+    reg [31:0] data_rd;
+    integer i;
+    initial begin
+
+        // let all signals initialize
+        wait_full_tick;
+
+        // wait for reset to complete
+        while (!sys_rst_n) begin
+            wait_full_tick;
+        end
+        
+        // wait some more time
+        wait_n_ticks(10);        
+
+        // write test
+        
+        lfsr8_seed(8'hA5);
+        $display("Writing data...");
+        
+        for (i=0; i<NUM_TESTS; i=i+1) begin
+            gen_rnd_addr(addr);
+            gen_rnd_data(data_wr);
+            fmc_write(addr, data_wr);
+            $display("Write %0d/%0d: @0x%x: 0x%x", i+1, NUM_TESTS, addr, data_wr);
+        end
+        
+        lfsr8_seed(8'hA5);
+        $display("Reading data...");
+        
+        for (i=0; i<NUM_TESTS; i=i+1) begin
+            gen_rnd_addr(addr);
+            gen_rnd_data(data_wr);
+            fmc_read(addr, data_rd);
+            $display("Read %0d/%0d: @0x%x: 0x%x | 0x%x", i+1, NUM_TESTS, addr, data_rd, data_wr);
+            if (data_rd !== data_wr) begin
+                $display("ERROR");
+                $finish;
+            end
+        end
+        
+        $display("All tests passed. [OK]");
+        $finish;
+
+    end
+
+
+    //
+    // User-Side Memory
+    //
+    reg [31:0] mem[0:2**24-1];
+    
+    // write handler
+    always @(posedge sys_clk)
+        //
+        if (sys_fmc_wren)
+            mem[sys_fmc_addr] <= sys_fmc_dout;
+            
+    // read handler
+    always @(posedge sys_clk)
+        //
+        if (sys_fmc_rden)
+            sys_fmc_din <= mem[sys_fmc_addr];
+    
+        
 endmodule
 
 



More information about the Commits mailing list