From b3ca952a39d57223575d36a1fa2793ee977c818f Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Tue, 21 Feb 2012 17:38:40 +0100 Subject: [PATCH] s6ddrphy: read path OK in simulation --- tb/s6ddrphy/gtkwave.sav | 45 +++++++++++++++++++++++ tb/s6ddrphy/tb_s6ddrphy.v | 72 ++++++++++++++++++++++++++++++------- verilog/s6ddrphy/s6ddrphy.v | 44 ++++++++++++++--------- 3 files changed, 131 insertions(+), 30 deletions(-) create mode 100644 tb/s6ddrphy/gtkwave.sav diff --git a/tb/s6ddrphy/gtkwave.sav b/tb/s6ddrphy/gtkwave.sav new file mode 100644 index 000000000..ec6349735 --- /dev/null +++ b/tb/s6ddrphy/gtkwave.sav @@ -0,0 +1,45 @@ +[timestart] 0 +[size] 1741 771 +[pos] -1 -1 +*-14.000000 0 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +[treeopen] tb_s6ddrphy. +[treeopen] tb_s6ddrphy.dut. +[treeopen] tb_s6ddrphy.dut.gen_dq[0]. +@28 +tb_s6ddrphy.dut.sys_clk +tb_s6ddrphy.dut.clk2x_270 +tb_s6ddrphy.dut.clk4x_wr +tb_s6ddrphy.dut.clk4x_wr_strb +@22 +tb_s6ddrphy.dut.dfi_address_p0[12:0] +tb_s6ddrphy.dut.dfi_address_p1[12:0] +@200 +- +@22 +tb_s6ddrphy.dut.sd_a[12:0] +@28 +tb_s6ddrphy.dut.sd_clk_out_p +@22 +tb_s6ddrphy.dut.sd_dm[3:0] +tb_s6ddrphy.dut.sd_dq[31:0] +tb_s6ddrphy.dut.sd_dqs[3:0] +@200 +- +@28 +tb_s6ddrphy.dut.dfi_wrdata_en_p1 +@22 +tb_s6ddrphy.dut.dfi_wrdata_mask_p0[7:0] +tb_s6ddrphy.dut.dfi_wrdata_mask_p1[7:0] +tb_s6ddrphy.dut.dfi_wrdata_p0[63:0] +tb_s6ddrphy.dut.dfi_wrdata_p1[63:0] +@200 +- +@29 +tb_s6ddrphy.dut.dfi_rddata_en_p0 +@22 +tb_s6ddrphy.dut.dfi_rddata_w0[63:0] +tb_s6ddrphy.dut.dfi_rddata_w1[63:0] +@28 +tb_s6ddrphy.dut.dfi_rddata_valid_w0 +[pattern_trace] 1 +[pattern_trace] 0 diff --git a/tb/s6ddrphy/tb_s6ddrphy.v b/tb/s6ddrphy/tb_s6ddrphy.v index f9341bf9f..d3203e32b 100644 --- a/tb/s6ddrphy/tb_s6ddrphy.v +++ b/tb/s6ddrphy/tb_s6ddrphy.v @@ -58,6 +58,13 @@ reg dfi_wrdata_en_p1 = 0; reg [7:0] dfi_wrdata_mask_p1 = 0; reg [63:0] dfi_wrdata_p1 = 0; +reg dfi_rddata_en_p0 = 0; +reg dfi_rddata_en_p1 = 0; + +wire [31:0] sd_dq; +reg [31:0] dq_tb = 32'hzzzzzzzz; +assign sd_dq = dq_tb; + s6ddrphy #( .NUM_AD(13), .NUM_BA(2), @@ -83,37 +90,76 @@ s6ddrphy #( .dfi_wrdata_en_p1(dfi_wrdata_en_p1), .dfi_wrdata_mask_p1(dfi_wrdata_mask_p1), .dfi_wrdata_p1(dfi_wrdata_p1), - .sd_dq(), + .sd_dq(sd_dq), .sd_dm(), - .sd_dqs() + .sd_dqs(), + + .dfi_rddata_en_p0(dfi_rddata_en_p0), + .dfi_rddata_en_p1(dfi_rddata_en_p1), + .dfi_rddata_w0(), + .dfi_rddata_w1(), + .dfi_rddata_valid_w0(), + .dfi_rddata_valid_w1() ); +`define TEST_SIMPLE_CMD +`define TEST_WRITE +`define TEST_READ + initial begin $dumpfile("s6ddrphy.vcd"); $dumpvars(3, dut); + +`ifdef TEST_SIMPLE_CMD #13; - - /*dfi_address_p0 <= 13'h1aba; + dfi_address_p0 <= 13'h1aba; dfi_address_p1 <= 13'h1234; #12; dfi_address_p0 <= 0; dfi_address_p1 <= 0; - #60;*/ - - dfi_address_p0 <= 13'h0dea; + #59; +`endif + +`ifdef TEST_WRITE + #13; dfi_address_p1 <= 13'h0dbe; + #12; + dfi_address_p1 <= 0; + dfi_wrdata_en_p1 <= 1; + dfi_wrdata_mask_p0 <= 8'h12; + dfi_wrdata_mask_p1 <= 8'h34; dfi_wrdata_p0 <= 64'hcafebabeabadface; dfi_wrdata_p1 <= 64'h0123456789abcdef; - dfi_wrdata_en_p0 <= 1'b1; - dfi_wrdata_en_p1 <= 1'b1; #12; - dfi_address_p0 <= 0; - dfi_address_p1 <= 0; + dfi_wrdata_en_p1 <= 0; + dfi_wrdata_mask_p0 <= 0; + dfi_wrdata_mask_p1 <= 0; dfi_wrdata_p0 <= 64'd0; dfi_wrdata_p1 <= 64'd0; - dfi_wrdata_en_p0 <= 1'b0; - dfi_wrdata_en_p1 <= 1'b0; + #59; +`endif + +`ifdef TEST_READ + #13; + dfi_address_p0 <= 13'h1234; + #12; + dfi_address_p0 <= 0; + dfi_rddata_en_p0 <= 1; + #12; + dfi_rddata_en_p0 <= 0; + #15.5; + dq_tb <= 32'h12345678; + #3; + dq_tb <= 32'hdeadbeef; + #3; + dq_tb <= 32'hcafebabe; + #3; + dq_tb <= 32'habadface; + #3; + dq_tb <= 32'hzzzzzzzz; #60; +`endif + $finish; end diff --git a/verilog/s6ddrphy/s6ddrphy.v b/verilog/s6ddrphy/s6ddrphy.v index 54a23e44b..26fdefe02 100644 --- a/verilog/s6ddrphy/s6ddrphy.v +++ b/verilog/s6ddrphy/s6ddrphy.v @@ -1,6 +1,21 @@ /* - * 1:2 DDR PHY for Spartan-6 + * 1:2 frequency-ratio DDR PHY for Spartan-6 * + ************* DATAPATH SIGNALS *********** + * Assert dfi_wrdata_en and present the data + * on dfi_wrdata_mask/dfi_wrdata one cycle after + * a write command. + * + * Assert dfi_rddata_en one cycle after a read + * command. The data will come back on dfi_rddata + * 3 cycles later, along with the assertion of + * dfi_rddata_valid. + * + * This PHY only supports CAS Latency 3. + * Read commands must be sent on phase 0. + * Write commands must be sent on phase 1. + * + ************* DETAILED TIMING ************ * Command path: * posedge sys_clk + 1 * posedge clk2x_270 + 0.375 @@ -17,8 +32,6 @@ * posedge clk2x_270 + 0.375 * negedge clk2x_270 [oddr] + 0.125 * DQS OE latency 1.5 cycles - * - * Data read path: */ module s6ddrphy #( parameter NUM_AD = 0, @@ -309,7 +322,7 @@ generate .CLK1(1'b0), .IOCE(clk4x_rd_strb), .RST(1'b0), - .CLKDIV(clk), + .CLKDIV(sys_clk), .SHIFTIN(), .BITSLIP(1'b0), .FABRICOUT(), @@ -377,25 +390,22 @@ endgenerate * DQ/DQS/DM control */ -reg r_dfi_wrdata_en_p0; reg r_dfi_wrdata_en_p1; - -always @(posedge sys_clk) begin - r_dfi_wrdata_en_p0 <= dfi_wrdata_en_p0; +always @(posedge sys_clk) r_dfi_wrdata_en_p1 <= dfi_wrdata_en_p1; -end -reg r2_dfi_wrdata_en_p0; reg r2_dfi_wrdata_en_p1; - -always @(posedge clk2x_270) begin - r2_dfi_wrdata_en_p0 <= r_dfi_wrdata_en_p0; +always @(posedge clk2x_270) r2_dfi_wrdata_en_p1 <= r_dfi_wrdata_en_p1; -end -assign drive_dqs = r2_dfi_wrdata_en_p0 | r2_dfi_wrdata_en_p1; -assign drive_dq = dfi_wrdata_en_p0 | dfi_wrdata_en_p1; +assign drive_dqs = r2_dfi_wrdata_en_p1; +assign drive_dq = dfi_wrdata_en_p1; -// TODO: dfi_rddata_valid_w0/1? +wire rddata_valid; +reg [3:0] rddata_sr; +assign dfi_rddata_valid_w0 = rddata_sr[0]; +assign dfi_rddata_valid_w1 = rddata_sr[0]; +always @(posedge sys_clk) + rddata_sr <= {dfi_rddata_en_p0, rddata_sr[3:1]}; endmodule