OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /openrisc/trunk/orpsocv2
    from Rev 411 to Rev 412
    Reverse comparison

Rev 411 → Rev 412

/rtl/verilog/or1200/or1200_ic_fsm.v
102,7 → 102,8
reg hitmiss_eval;
reg load;
reg cache_inhibit;
 
reg waiting_for_first_fill_ack; // JPB
//
// Generate of ICRAM write enables
//
144,6 → 145,8
load <= 1'b0;
cnt <= 3'b000;
cache_inhibit <= 1'b0;
waiting_for_first_fill_ack <= 0; // JPB
end
else
case (state) // synopsys parallel_case
154,12 → 157,13
hitmiss_eval <= 1'b1;
load <= 1'b1;
cache_inhibit <= icqmem_ci_i;
waiting_for_first_fill_ack <= 0; // JPB
end
else begin // idle
hitmiss_eval <= 1'b0;
load <= 1'b0;
cache_inhibit <= 1'b0;
end
end
`OR1200_ICFSM_CFETCH: begin // fetch
if (icqmem_cycstb_i & icqmem_ci_i)
178,6 → 182,7
hitmiss_eval <= 1'b0;
load <= 1'b0;
cache_inhibit <= 1'b0;
waiting_for_first_fill_ack <= 0;
end // if ((!ic_en) ||...
// fetch missed, finish current external fetch and refill
else if (tagcomp_miss & biudata_valid) begin
186,6 → 191,7
hitmiss_eval <= 1'b0;
cnt <= `OR1200_ICLS-2;
cache_inhibit <= 1'b0;
waiting_for_first_fill_ack <= 0; // JPB
end
// fetch aborted (usually caused by exception)
else if (!icqmem_cycstb_i) begin
193,14 → 199,23
hitmiss_eval <= 1'b0;
load <= 1'b0;
cache_inhibit <= 1'b0;
waiting_for_first_fill_ack <= 0; // JPB
end
// fetch hit, finish immediately
else if (!tagcomp_miss & !icqmem_ci_i) begin
else if (!tagcomp_miss & !icqmem_ci_i &
!waiting_for_first_fill_ack) begin
state <= `OR1200_ICFSM_IDLE; // JPB
load <= 1'b0; // JPB
hitmiss_eval <= 1'b0; // JPB
saved_addr_r <= start_addr;
cache_inhibit <= 1'b0;
end
else // fetch in-progress
hitmiss_eval <= 1'b0;
 
if (hitmiss_eval & tagcomp_miss) // JPB
waiting_for_first_fill_ack <= 1;
end
`OR1200_ICFSM_LREFILL3 : begin
// abort because IC has just been turned off
rtl/verilog/ram_wb/ram_wb_sc_sw.v Property changes : Deleted: svn:executable ## -1 +0,0 ## -* \ No newline at end of property Index: rtl/verilog/ram_wb/ram_wb_b3.v =================================================================== --- rtl/verilog/ram_wb/ram_wb_b3.v (nonexistent) +++ rtl/verilog/ram_wb/ram_wb_b3.v (revision 412) @@ -0,0 +1,189 @@ +//`define NONBLOCK_ASSIGN <= #1 +`define NONBLOCK_ASSIGN <= + +module ram_wb_b3( + wb_adr_i, wb_bte_i, wb_cti_i, wb_cyc_i, wb_dat_i, wb_sel_i, + wb_stb_i, wb_we_i, + + wb_ack_o, wb_err_o, wb_rty_o, wb_dat_o, + + wb_clk_i, wb_rst_i); + + parameter dw = 32; + parameter aw = 32; + + input [aw-1:0] wb_adr_i; + input [1:0] wb_bte_i; + input [2:0] wb_cti_i; + input wb_cyc_i; + input [dw-1:0] wb_dat_i; + input [3:0] wb_sel_i; + input wb_stb_i; + input wb_we_i; + + output wb_ack_o; + output wb_err_o; + output wb_rty_o; + output [dw-1:0] wb_dat_o; + + input wb_clk_i; + input wb_rst_i; + + // Memory parameters + //parameter mem_span = 32'h0000_0400; + parameter mem_span = 32'h0000_5000; +// parameter adr_width_for_span = 11; //(log2(mem_span)); + parameter adr_width_for_span = 15; //(log2(mem_span)); + parameter bytes_per_dw = (dw/8); + parameter adr_width_for_num_word_bytes = 2; //(log2(bytes_per_dw)) + parameter mem_words = (mem_span/bytes_per_dw); + + // synthesis attribute ram_style of mem is block + reg [dw-1:0] mem [ 0 : mem_words-1 ] /* synthesis ram_style = no_rw_check */; + + reg [(adr_width_for_span-2)-1:0] adr; + + wire [31:0] wr_data; + + // Register to indicate if the cycle is a Wishbone B3-registered feedback + // type access + reg wb_b3_trans; + wire wb_b3_trans_start, wb_b3_trans_stop; + + // Register to use for counting the addresses when doing burst accesses + reg [adr_width_for_span-1-2:0] burst_adr_counter; + reg [2:0] wb_cti_i_r; + reg [1:0] wb_bte_i_r; + wire using_burst_adr; + wire burst_access_wrong_wb_adr; + + + // Logic to detect if there's a burst access going on + assign wb_b3_trans_start = ((wb_cti_i == 3'b001)|(wb_cti_i == 3'b010)) & + wb_stb_i & !wb_b3_trans; + + assign wb_b3_trans_stop = (wb_cti_i == 3'b111) & + wb_stb_i & wb_b3_trans & wb_ack_o; + + always @(posedge wb_clk_i) + if (wb_rst_i) + wb_b3_trans `NONBLOCK_ASSIGN 0; + else if (wb_b3_trans_start) + wb_b3_trans `NONBLOCK_ASSIGN 1; + else if (wb_b3_trans_stop) + wb_b3_trans `NONBLOCK_ASSIGN 0; + + // Burst address generation logic + always @(/*AUTOSENSE*/wb_ack_o or wb_b3_trans or wb_b3_trans_start + or wb_bte_i_r or wb_cti_i_r or wb_adr_i or adr) + if (wb_b3_trans_start) + // Kick off burst_adr_counter, this assumes 4-byte words when getting + // address off incoming Wishbone bus address! + // So if dw is no longer 4 bytes, change this! + burst_adr_counter <= wb_adr_i[adr_width_for_span-1:2]; + else if ((wb_cti_i_r == 3'b010) & wb_ack_o & wb_b3_trans) + // Incrementing burst + begin + if (wb_bte_i_r == 2'b00) // Linear burst + burst_adr_counter <= adr + 1; + if (wb_bte_i_r == 2'b01) // 4-beat wrap burst + burst_adr_counter[1:0] <= adr[1:0] + 1; + if (wb_bte_i_r == 2'b10) // 8-beat wrap burst + burst_adr_counter[2:0] <= adr[2:0] + 1; + if (wb_bte_i_r == 2'b11) // 16-beat wrap burst + burst_adr_counter[3:0] <= adr[3:0] + 1; + end // if ((wb_cti_i_r == 3'b010) & wb_ack_o_r) + + + always @(posedge wb_clk_i) + wb_bte_i_r `NONBLOCK_ASSIGN wb_bte_i; + + // Register it locally + always @(posedge wb_clk_i) + wb_cti_i_r `NONBLOCK_ASSIGN wb_cti_i; + + assign using_burst_adr = wb_b3_trans; + + assign burst_access_wrong_wb_adr = (using_burst_adr & (adr != wb_adr_i[adr_width_for_span-1:2])); + + // Address registering logic + always@(posedge wb_clk_i) + if(wb_rst_i) + adr `NONBLOCK_ASSIGN 0; + else if (using_burst_adr) + adr `NONBLOCK_ASSIGN burst_adr_counter; + else if (wb_cyc_i & wb_stb_i) + adr `NONBLOCK_ASSIGN wb_adr_i[adr_width_for_span-1:2]; + + parameter memory_file = "sram.vmem"; + + initial + begin + $readmemh(memory_file, mem); + end + + assign wb_rty_o = 0; + + // mux for data to ram, RMW on part sel != 4'hf + assign wr_data[31:24] = wb_sel_i[3] ? wb_dat_i[31:24] : wb_dat_o[31:24]; + assign wr_data[23:16] = wb_sel_i[2] ? wb_dat_i[23:16] : wb_dat_o[23:16]; + assign wr_data[15: 8] = wb_sel_i[1] ? wb_dat_i[15: 8] : wb_dat_o[15: 8]; + assign wr_data[ 7: 0] = wb_sel_i[0] ? wb_dat_i[ 7: 0] : wb_dat_o[ 7: 0]; + + wire ram_we; + assign ram_we = wb_we_i & wb_ack_o; + + assign wb_dat_o = mem[adr]; + + // Write logic + always @ (posedge wb_clk_i) + begin + if (ram_we) + mem[adr] `NONBLOCK_ASSIGN wr_data; + end + + // Ack Logic + reg wb_ack_o_r; + + assign wb_ack_o = wb_ack_o_r & wb_stb_i; + + always @ (posedge wb_clk_i) + if (wb_rst_i) + wb_ack_o_r `NONBLOCK_ASSIGN 1'b0; + else if (wb_cyc_i) // We have bus + begin + if (wb_cti_i == 3'b000) + begin + // Classic cycle acks + if (wb_stb_i) + begin + if (!wb_ack_o_r) + wb_ack_o_r `NONBLOCK_ASSIGN 1; + else + wb_ack_o_r `NONBLOCK_ASSIGN 0; + end + end // if (wb_cti_i == 3'b000) + else if ((wb_cti_i == 3'b001) | (wb_cti_i == 3'b010)) + begin + // Increment/constant address bursts + if (wb_stb_i) + wb_ack_o_r `NONBLOCK_ASSIGN 1; + else + wb_ack_o_r `NONBLOCK_ASSIGN 0; + end + else if (wb_cti_i == 3'b111) + begin + // End of cycle + if (!wb_ack_o_r) + wb_ack_o_r `NONBLOCK_ASSIGN wb_stb_i; + else + wb_ack_o_r `NONBLOCK_ASSIGN 0; + end + end // if (wb_cyc_i) + else + wb_ack_o_r `NONBLOCK_ASSIGN 0; + + assign wb_err_o = wb_ack_o & (burst_access_wrong_wb_adr); // OR in other errors here + +endmodule // ram_wb_b3 +
rtl/verilog/ram_wb/ram_wb_b3.v Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: rtl/verilog/ram_wb/ram_wb.v =================================================================== --- rtl/verilog/ram_wb/ram_wb.v (revision 411) +++ rtl/verilog/ram_wb/ram_wb.v (revision 412) @@ -1,69 +1,153 @@ -module ram_wb ( dat_i, dat_o, adr_i, we_i, sel_i, cyc_i, stb_i, ack_o, cti_i, clk_i, rst_i); +module ram_wb + ( + // Inputs + wbm0_adr_i, wbm0_bte_i, wbm0_cti_i, wbm0_cyc_i, wbm0_dat_i, wbm0_sel_i, + wbm0_stb_i, wbm0_we_i, + // Outputs + wbm0_ack_o, wbm0_err_o, wbm0_rty_o, wbm0_dat_o, + + // Inputs + wbm1_adr_i, wbm1_bte_i, wbm1_cti_i, wbm1_cyc_i, wbm1_dat_i, wbm1_sel_i, + wbm1_stb_i, wbm1_we_i, + // Outputs + wbm1_ack_o, wbm1_err_o, wbm1_rty_o, wbm1_dat_o, - parameter dat_width = 32; - parameter adr_width = 12; - parameter mem_size = 262144; // Default is 1MB (262144 32-bit words) + // Clock, reset + wb_clk_i, wb_rst_i + ); + // Bus parameters + parameter dw = 32; + parameter aw = 32; + // Memory parameters + parameter mem_span = 32'h0000_0400; + parameter adr_width_for_span = 11; //(log2(mem_span)); + + + input [aw-1:0] wbm0_adr_i; + input [1:0] wbm0_bte_i; + input [2:0] wbm0_cti_i; + input wbm0_cyc_i; + input [dw-1:0] wbm0_dat_i; + input [3:0] wbm0_sel_i; + input wbm0_stb_i; + input wbm0_we_i; - // wishbone signals - input [31:0] dat_i; - output [31:0] dat_o; - input [adr_width-1:2] adr_i; - input we_i; - input [3:0] sel_i; - input cyc_i; - input stb_i; - output reg ack_o; - input [2:0] cti_i; + output wbm0_ack_o; + output wbm0_err_o; + output wbm0_rty_o; + output [dw-1:0] wbm0_dat_o; + + input [aw-1:0] wbm1_adr_i; + input [1:0] wbm1_bte_i; + input [2:0] wbm1_cti_i; + input wbm1_cyc_i; + input [dw-1:0] wbm1_dat_i; + input [3:0] wbm1_sel_i; + input wbm1_stb_i; + input wbm1_we_i; - // clock - input clk_i; - // async reset - input rst_i; + output wbm1_ack_o; + output wbm1_err_o; + output wbm1_rty_o; + output [dw-1:0] wbm1_dat_o; - wire [31:0] wr_data; + + input wb_clk_i; + input wb_rst_i; + + // Internal wires to actual RAM + wire [aw-1:0] wb_ram_adr_i; + wire [1:0] wb_ram_bte_i; + wire [2:0] wb_ram_cti_i; + wire wb_ram_cyc_i; + wire [dw-1:0] wb_ram_dat_i; + wire [3:0] wb_ram_sel_i; + wire wb_ram_stb_i; + wire wb_ram_we_i; - // mux for data to ram - assign wr_data[31:24] = sel_i[3] ? dat_i[31:24] : dat_o[31:24]; - assign wr_data[23:16] = sel_i[2] ? dat_i[23:16] : dat_o[23:16]; - assign wr_data[15: 8] = sel_i[1] ? dat_i[15: 8] : dat_o[15: 8]; - assign wr_data[ 7: 0] = sel_i[0] ? dat_i[ 7: 0] : dat_o[ 7: 0]; + wire wb_ram_ack_o; + wire wb_ram_err_o; + wire wb_ram_rty_o; + wire [dw-1:0] wb_ram_dat_o; + + reg [1:0] input_select, last_selected; + wire arb_for_wbm0, arb_for_wbm1; + // Wires allowing selection of new input + assign arb_for_wbm0 = (last_selected[1] | !wbm1_cyc_i) & !(|input_select); + assign arb_for_wbm1 = (last_selected[0] | !wbm0_cyc_i) & !(|input_select); - ram_wb_sc_sw - # + // Master select logic + always @(posedge wb_clk_i) + if (wb_rst_i) + input_select <= 0; + else if ((input_select[0] & !wbm0_cyc_i) | (input_select[1] & !wbm1_cyc_i)) + input_select <= 0; + else if (!(&input_select) & wbm0_cyc_i & arb_for_wbm0) + input_select <= 2'b01; + else if (!(&input_select) & wbm1_cyc_i & arb_for_wbm1) + input_select <= 2'b10; + + always @(posedge wb_clk_i) + if (wb_rst_i) + last_selected <= 0; + else if (!(&input_select) & wbm0_cyc_i & arb_for_wbm0) + last_selected <= 2'b01; + else if (!(&input_select) & wbm1_cyc_i & arb_for_wbm1) + last_selected <= 2'b10; + + // Mux input signals to RAM (default to wbm0) + assign wb_ram_adr_i = (input_select[1]) ? wbm1_adr_i : + (input_select[0]) ? wbm0_adr_i : 0; + assign wb_ram_bte_i = (input_select[1]) ? wbm1_bte_i : + (input_select[0]) ? wbm0_bte_i : 0; + assign wb_ram_cti_i = (input_select[1]) ? wbm1_cti_i : + (input_select[0]) ? wbm0_cti_i : 0; + assign wb_ram_cyc_i = (input_select[1]) ? wbm1_cyc_i : + (input_select[0]) ? wbm0_cyc_i : 0; + assign wb_ram_dat_i = (input_select[1]) ? wbm1_dat_i : + (input_select[0]) ? wbm0_dat_i : 0; + assign wb_ram_sel_i = (input_select[1]) ? wbm1_sel_i : + (input_select[0]) ? wbm0_sel_i : 0; + assign wb_ram_stb_i = (input_select[1]) ? wbm1_stb_i : + (input_select[0]) ? wbm0_stb_i : 0; + assign wb_ram_we_i = (input_select[1]) ? wbm1_we_i : + (input_select[0]) ? wbm0_we_i : 0; + + // Output from RAM, gate the ACK, ERR, RTY signals appropriately + assign wbm0_dat_o = wb_ram_dat_o; + assign wbm0_ack_o = wb_ram_ack_o & input_select[0]; + assign wbm0_err_o = wb_ram_err_o & input_select[0]; + assign wbm0_rty_o = wb_ram_rty_o & input_select[0]; + + assign wbm1_dat_o = wb_ram_dat_o; + assign wbm1_ack_o = wb_ram_ack_o & input_select[1]; + assign wbm1_err_o = wb_ram_err_o & input_select[1]; + assign wbm1_rty_o = wb_ram_rty_o & input_select[1]; + + ram_wb_b3 ram_wb_b3_0 ( - .dat_width(dat_width), - .adr_width(adr_width), - .mem_size(mem_size) - ) - ram0 - ( - .dat_i(wr_data), - .dat_o(dat_o), - .adr_i({2'b00, adr_i}), - .we_i(we_i & ack_o), - .clk(clk_i) - ); - - // ack_o - always @ (posedge clk_i or posedge rst_i) - if (rst_i) - ack_o <= 1'b0; - else - if (!ack_o) - begin - if (cyc_i & stb_i) - ack_o <= 1'b1; - end - else - ack_o <= 1'b0; + // Outputs + .wb_ack_o (wb_ram_ack_o), + .wb_err_o (wb_ram_err_o), + .wb_rty_o (wb_ram_rty_o), + .wb_dat_o (wb_ram_dat_o), + // Inputs + .wb_adr_i (wb_ram_adr_i), + .wb_bte_i (wb_ram_bte_i), + .wb_cti_i (wb_ram_cti_i), + .wb_cyc_i (wb_ram_cyc_i), + .wb_dat_i (wb_ram_dat_i), + .wb_sel_i (wb_ram_sel_i), + .wb_stb_i (wb_ram_stb_i), + .wb_we_i (wb_ram_we_i), + .wb_clk_i (wb_clk_i), + .wb_rst_i (wb_rst_i)); - // We did have acking logic which was sensitive to the - // burst signals, cti_i, but this proved to cause problems - // and we were never receiving back-to-back reads or writes - // anyway. This logic which only acks one transaction at a - // time appears to work well, despite not supporting burst - // transactions. - -endmodule - - \ No newline at end of file + defparam ram_wb_b3_0.aw = aw; + defparam ram_wb_b3_0.dw = dw; + defparam ram_wb_b3_0.mem_span = mem_span; + defparam ram_wb_b3_0.adr_width_for_span = adr_width_for_span; + +endmodule // ram_wb + +
/sw/tests/or1200/sim/or1200-except.S
448,55 → 448,55
6: l.addi r12,r12,1 /* Increment 2nd exception counter */
/* Test l.sw */
l.ori r5,r0,0x1 /* Word access, offset 1 */
l.j 7f
l.sw 0x0(r5), r0
l.ori r5,r0,0x1 /* Word access, offset 1 */
l.j 7f
l.sw 0x0(r5), r0
l.nop
7: l.addi r12,r12,1 /* Increment 2nd exception counter */
l.ori r5,r0,0x2 /* Word access, offset 2 */
l.j 8f
l.sw 0x0(r5), r0
7: l.addi r12,r12,1 /* Increment 2nd exception counter */
l.ori r5,r0,0x2 /* Word access, offset 2 */
l.j 8f
l.sw 0x0(r5), r0
l.nop
8: l.addi r12,r12,1 /* Increment 2nd exception counter */
l.ori r5,r0,0x3 /* Word access, offset 3 */
l.j 9f
l.sh 0x0(r5), r0
8: l.addi r12,r12,1 /* Increment 2nd exception counter */
l.ori r5,r0,0x3 /* Word access, offset 3 */
l.j 9f
l.sh 0x0(r5), r0
l.nop
9: l.addi r12,r12,1 /* Increment 2nd exception counter */
9: l.addi r12,r12,1 /* Increment 2nd exception counter */
 
/* Test l.lwz */
l.ori r5,r0,0x1 /* Word access, offset 1 */
l.j 10f
l.lwz r3,0x0(r5)
l.ori r5,r0,0x1 /* Word access, offset 1 */
l.j 10f
l.lwz r3,0x0(r5)
l.nop
10: l.addi r12,r12,1 /* Increment 2nd exception counter */
l.ori r5,r0,0x2 /* Word access, offset 2 */
l.j 11f
l.lwz r3,0x0(r5)
10: l.addi r12,r12,1 /* Increment 2nd exception counter */
l.ori r5,r0,0x2 /* Word access, offset 2 */
l.j 11f
l.lwz r3,0x0(r5)
l.nop
11: l.addi r12,r12,1 /* Increment 2nd exception counter */
l.ori r5,r0,0x3 /* Word access, offset 3 */
l.j 12f
l.lwz r3,0x0(r5)
11: l.addi r12,r12,1 /* Increment 2nd exception counter */
l.ori r5,r0,0x3 /* Word access, offset 3 */
l.j 12f
l.lwz r3,0x0(r5)
l.nop
12: l.addi r12,r12,1 /* Increment 2nd exception counter */
12: l.addi r12,r12,1 /* Increment 2nd exception counter */
#if OR1200_HAS_LWS==1
/* Test l.lws */
l.ori r5,r0,0x1 /* Word access, offset 1 */
l.j 13f
l.lws r3,0x0(r5)
l.ori r5,r0,0x1 /* Word access, offset 1 */
l.j 13f
l.lws r3,0x0(r5)
l.nop
13: l.addi r12,r12,1 /* Increment 2nd exception counter */
l.ori r5,r0,0x2 /* Word access, offset 2 */
l.j 14f
l.lws r3,0x0(r5)
13: l.addi r12,r12,1 /* Increment 2nd exception counter */
l.ori r5,r0,0x2 /* Word access, offset 2 */
l.j 14f
l.lws r3,0x0(r5)
l.nop
14: l.addi r12,r12,1 /* Increment 2nd exception counter */
l.ori r5,r0,0x3 /* Word access, offset 3 */
l.j 15f
l.lws r3,0x0(r5)
14: l.addi r12,r12,1 /* Increment 2nd exception counter */
l.ori r5,r0,0x3 /* Word access, offset 3 */
l.j 15f
l.lws r3,0x0(r5)
l.nop
15: l.addi r12,r12,1 /* Increment 2nd exception counter */
15: l.addi r12,r12,1 /* Increment 2nd exception counter */
#endif
/* Check 1st and 2nd exception counters are equal */
512,37 → 512,37
l.nop
l.nop
l.movhi r5, hi(0x44004800) /* Put "l.jr r9" instruction in r5 */
l.ori r5, r5, lo(0x44004800)
l.sw 0x0(r0), r5 /* Write "l.j r9" to address 0x0 in RAM */
l.ori r5, r5, lo(0x44004800)
l.sw 0x0(r0), r5 /* Write "l.j r9" to address 0x0 in RAM */
l.movhi r5, 0xff00 /* Put an illegal instruction in r5 */
l.sw 0x4(r0), r5 /* Write illegal instruction to RAM addr 0x4 */
l.sw 0x4(r0), r5 /* Write illegal instruction to RAM addr 0x4 */
l.mtspr r0,r0,SPR_ICBIR /* Invalidate line 0 of cache */
/* Call 0x4, illegal opcode instruction */
l.ori r6, r0, 0x4
l.jalr r6 /* Jump to address 0x4, will land on an illegal instruction */
l.addi r12,r12,1 /* Increment 2nd exception counter */
l.ori r6, r0, 0x4
l.jalr r6 /* Jump to address 0x4, landing on an illegal instruction */
l.addi r12,r12,1 /* Increment 2nd exception counter */
l.nop /* Should return here */
l.nop
l.nop /* Should return here */
 
/* Test in delay slot */
l.movhi r5, 0xff00 /* Put an illegal instruction in r5 */
l.sw 0x4(r0), r5 /* Write illegal instruction to RAM addr 0x4 */
l.mtspr r0,r0,SPR_ICBIR /* Invalidate line 0 of cache */
l.jalr r0 /* Jump to address 0, will be a jump back but with an illegal
l.sw 0x4(r0), r5 /* Write illegal instruction to RAM addr 0x4 */
l.mtspr r0,r0,SPR_ICBIR /* Invalidate line 0 of cache */
l.jalr r0 /* Jump to address 0, will be a jump back but with an illegal
dslot instruction which will befixed by handler */
l.addi r12,r12,1 /* Increment 2nd exception counter */
l.addi r12,r12,1 /* Increment 2nd exception counter */
l.nop /* Should return here */
 
/* Check 1st and 2nd exception counters are equal */
l.sfeq r11,r12 /* Should be equal */
l.bf 1f
l.bf 1f
l.nop
l.or r3, r12, r12
l.nop 2 /* Report expected exception count */
l.or r3, r11, r11
l.nop 2 /* Report actual exception count */
l.nop 1
l.or r3, r12, r12
l.nop 2 /* Report expected exception count */
l.or r3, r11, r11
l.nop 2 /* Report actual exception count */
l.nop 1
1: l.nop
l.nop
/boards/readme.txt File deleted
/boards/xilinx/ml501/bench/verilog/eth_stim.v File deleted \ No newline at end of file
/boards/xilinx/ml501/bench/verilog/ml501_testbench_defines.v File deleted \ No newline at end of file
/boards/xilinx/ml501/bench/verilog/ddr2_model.v
1,10 → 1,10
/****************************************************************************************
*
* File Name: ddr2.v
* File Name: ddr2_model.v
* Version: 5.80
* Model: BUS Functional
*
* Dependencies: ddr2_parameters.vh
* Dependencies: ddr2_parameters.v
*
* Description: Micron SDRAM DDR2 (Double Data Rate 2)
*
137,7 → 137,7
odt
);
 
`include "ddr2_model_parameters.vh"
`include "ddr2_model_parameters.v"
// text macros
`define DQ_PER_DQS DQ_BITS/DQS_BITS
/boards/xilinx/ml501/bench/verilog/include/eth_stim.v
0,0 → 1,1268
//////////////////////////////////////////////////////////////////////
//// ////
//// Ethernet MAC Stimulus ////
//// ////
//// Description ////
//// Ethernet MAC stimulus tasks. Taken from the project ////
//// testbench in the ethmac core. ////
//// ////
//// To Do: ////
//// ////
//// ////
//// Author(s): ////
//// - Tadej Markovic, tadej@opencores.org ////
//// - Igor Mohor, igorM@opencores.org ////
//// - Julius Baxter julius.baxter@orsoc.se ////
//// ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2009 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
`define TIME $display("Time: %0t", $time)
 
// Defines for ethernet test to trigger sending/receiving
// Is straight forward when using RTL design, but if using netlist then paths to
// the RX/TX enabled bits depend on synthesis tool, etc, but ones here appear to
// work with design put through Synplify, with hierarchy maintained.
`define ETH_TOP dut.ethmac0
`define ETH_BD_RAM_PATH `ETH_TOP.wishbone.bd_ram
`define ETH_MODER_PATH `ETH_TOP.ethreg1.MODER_0
 
`ifdef RTL_SIM
`ifdef ethmac_IS_GATELEVEL
`define ETH_MODER_TXEN_BIT `ETH_MODER_PATH.r_TxEn;
`define ETH_MODER_RXEN_BIT `ETH_MODER_PATH.r_RxEn;
`else
`define ETH_MODER_TXEN_BIT `ETH_MODER_PATH.DataOut[1];
`define ETH_MODER_RXEN_BIT `ETH_MODER_PATH.DataOut[0];
`endif
`endif
 
`ifdef GATE_SIM
`define ETH_MODER_TXEN_BIT `ETH_MODER_PATH.r_TxEn;
`define ETH_MODER_RXEN_BIT `ETH_MODER_PATH.r_RxEn;
`endif
 
reg [15:0] eth_stim_rx_packet_length;
reg [7:0] st_data;
reg [31:0] lfsr;
integer lfsr_last_byte;
 
// Is number of ethernet packets to send if doing the eth-rx test.
parameter eth_stim_num_rx_only_num_packets = 500; // Set to 0 for continuous RX
parameter eth_stim_num_rx_only_packet_size = 512;
parameter eth_stim_num_rx_only_packet_size_change = 2'b01; // 2'b01: Increment
parameter eth_stim_num_rx_only_packet_size_change_amount = 1;
parameter eth_stim_num_rx_only_IPG = 800000; // ns
 
// Do call/response test
reg eth_stim_do_rx_reponse_to_tx;
 
parameter num_tx_bds = 16;
parameter num_tx_bds_mask = 4'hf;
parameter num_rx_bds = 16;
parameter num_rx_bds_mask = 4'hf;
parameter max_eth_packet_size = 16'h0600;
 
// If running eth-rxtxbig test (sending and receiving maximum packets), then
// set this parameter to the max packet size, otherwise min packet size
//parameter rx_while_tx_min_packet_size = max_eth_packet_size;
parameter rx_while_tx_min_packet_size = 32;
 
// Use the smallest possible IPG
parameter eth_stim_use_min_IPG = 0;
parameter eth_stim_IPG_delay_max = 500_000; // Maximum 500uS ga
//parameter eth_stim_IPG_delay_max = 100_000_000; // Maximum 100mS between packets
parameter eth_stim_IPG_min_10mb = 9600; // 9.6 uS
parameter eth_stim_IPG_min_100mb = 800; // 860+~100 = 960 nS 100MBit min IPG
parameter eth_stim_check_rx_packet_contents = 1;
parameter eth_stim_check_tx_packet_contents = 1;
 
parameter eth_inject_errors = 0;
 
// When running simulations where you don't want to feed packets to the design
// like this...
parameter eth_stim_disable_rx_stim = 0;
 
// Delay between seeing that the buffer descriptor for an RX packet says it's
// been received and ending up in the memory.
// For 25MHz sdram controller, use following:
//parameter Td_rx_packet_check = (`BOARD_CLOCK_PERIOD * 2000);
// For 64MHz sdram controller, use following:
parameter Td_rx_packet_check = (`BOARD_CLOCK_PERIOD * 500);
 
 
 
integer expected_rxbd;// init to 0
integer expected_txbd;
 
wire ethmac_rxen;
wire ethmac_txen;
assign ethmac_rxen = eth_stim_disable_rx_stim ? 0 : `ETH_MODER_RXEN_BIT;
assign ethmac_txen = `ETH_MODER_TXEN_BIT;
 
integer eth_rx_num_packets_sent = 0;
integer eth_rx_num_packets_checked = 0;
integer num_tx_packets = 1;
 
integer rx_packet_lengths [0:1023]; // Array of packet lengths
 
 
integer speed_loop;
 
// When txen is (re)enabled, the tx bd pointer goes back to 0
always @(posedge ethmac_txen)
expected_txbd = 0;
reg eth_stim_waiting;
initial
begin
#1;
//lfsr = 32'h84218421; // Init pseudo lfsr
lfsr = 32'h00700001; // Init pseudo lfsr
lfsr_last_byte = 0;
eth_stim_waiting = 1;
expected_rxbd = num_tx_bds; // init this here
 
eth_stim_do_rx_reponse_to_tx = 0;
while (eth_stim_waiting) // Loop, waiting for enabling of MAC by software
begin
#100;
// If RX enable and not TX enable...
if(ethmac_rxen === 1'b1 & !(ethmac_txen===1'b1))
begin
if (eth_inject_errors)
begin
do_rx_only_stim(16, 64, 0, 0);
do_rx_only_stim(128, 64, 1'b1, 8);
do_rx_only_stim(256, 64, 1'b1, 4);
eth_stim_waiting = 0;
end
else
begin
//do_rx_only_stim(eth_stim_num_rx_only_num_packets,
//eth_stim_num_rx_only_packet_size, 0, 0);
 
// Call packet send loop directly. No error injection.
send_packet_loop(eth_stim_num_rx_only_num_packets,
eth_stim_num_rx_only_packet_size,
eth_stim_num_rx_only_packet_size_change,
eth_stim_num_rx_only_packet_size_change_amount,
eth_phy0.eth_speed, // Speed
eth_stim_num_rx_only_IPG, // IPG
48'h0012_3456_789a, 48'h0708_090A_0B0C, 1,
0, 0);
eth_stim_waiting = 0;
end
end // if (ethmac_rxen === 1'b1 & !(ethmac_txen===1'b1))
// If both RX and TX enabled
else if (ethmac_rxen === 1'b1 & ethmac_txen===1'b1)
begin
// Both enabled - let's wait for the first packet transmitted
// to see what stimulus we should provide
while (num_tx_packets==1)
#1000;
 
$display("* ethmac RX/TX test request: %x", eth_phy0.tx_mem[0]);
// Check the first received byte's value
case (eth_phy0.tx_mem[0])
0:
begin
// kickoff call/response here
eth_stim_do_rx_reponse_to_tx = 1;
end
default:
begin
do_rx_while_tx_stim(1400);
end
endcase // case (eth_phy0.tx_mem[0])
eth_stim_waiting = 0;
end
end // while (eth_stim_waiting)
end // initial begin
 
// Main Ethernet RX testing stimulus task.
// Sends a set of packets at both speeds
task do_rx_only_stim;
input [31:0] num_packets;
input [31:0] start_packet_size;
input inject_errors;
input [31:0] inject_errors_mod;
begin
for(speed_loop=1;speed_loop<3;speed_loop=speed_loop+1)
begin
send_packet_loop(num_packets, start_packet_size, 2'b01, 1,
speed_loop[0], 10000,
48'h0012_3456_789a, 48'h0708_090A_0B0C, 1,
inject_errors, inject_errors_mod);
end
end
endtask // do_rx_stim
 
// Generate RX packets while there's TX going on
// Sends a set of packets at both speeds
task do_rx_while_tx_stim;
input [31:0] num_packets;
reg [31:0] IPG; // Inter-packet gap
reg [31:0] packet_size;
integer j;
begin
for(j=0;j<num_packets;j=j+1)
begin
// Determine delay between RX packets:
if (eth_stim_use_min_IPG)
begin
// Assign based on whether we're in 100mbit or 10mbit mode
IPG = eth_phy0.eth_speed ? eth_stim_IPG_min_100mb :
eth_stim_IPG_min_10mb;
// Add a little bit of variability
// Add up to 15
IPG = IPG + ($random & 32'h000000f);
end
else
begin
IPG = $random;
while (IPG > eth_stim_IPG_delay_max)
IPG = IPG / 2;
end
$display("do_rx_while_tx IPG = %0d", IPG);
// Determine size of next packet:
if (rx_while_tx_min_packet_size == max_eth_packet_size)
// We want to transmit biggest packets possible, easy case
packet_size = max_eth_packet_size - 4;
else
begin
// Constrained random sized packets
packet_size = $random;
while (packet_size > (max_eth_packet_size-4))
packet_size = packet_size / 2;
// Now divide by least significant bits of j
packet_size = packet_size / {29'd0,j[1:0],1'b1};
if (packet_size < 60)
packet_size = packet_size + 60;
end
$display("do_rx_while_tx packet_size = %0d", packet_size);
send_packet_loop(1, packet_size, 2'b01, 1, eth_phy0.eth_speed,
IPG, 48'h0012_3456_789a,
48'h0708_090A_0B0C, 1, 1'b0, 0);
 
// If RX enable went low, wait for it go high again
if (ethmac_rxen===1'b0)
begin
while (ethmac_rxen===1'b0)
begin
@(posedge ethmac_rxen);
#10000;
end
// RX disabled and when re-enabled we reset the buffer descriptor number
expected_rxbd = num_tx_bds;
 
end
end // for (j=0;j<num_packets;j=j+1)
end
endtask // do_rx_stim
 
// Registers used in detecting transmitted packets
reg eth_stim_tx_loop_keep_polling;
reg [31:0] ethmac_txbd_lenstat, ethmac_last_txbd_lenstat;
reg eth_stim_detected_packet_tx;
 
// If in call-response mode, whenever we receive a TX packet, we generate
// one and send it back
always @(negedge eth_stim_detected_packet_tx)
begin
if (eth_stim_do_rx_reponse_to_tx & ethmac_rxen)
// Continue if we are enabled
do_rx_response_to_tx();
end
// Generate RX packet in rsponse to TX packet
task do_rx_response_to_tx;
//input unused;
reg [31:0] IPG; // Inter-packet gap
reg [31:0] packet_size;
integer j;
begin
 
// Get packet size test wants us to send
packet_size = {eth_phy0.tx_mem[0],eth_phy0.tx_mem[1],
eth_phy0.tx_mem[2],eth_phy0.tx_mem[3]};
 
IPG = {eth_phy0.tx_mem[4],eth_phy0.tx_mem[5],
eth_phy0.tx_mem[6],eth_phy0.tx_mem[7]};
$display("do_rx_response_to_tx IPG = %0d", IPG);
if (packet_size == 0)
begin
// Constrained random sized packets
packet_size = $random;
while (packet_size > (max_eth_packet_size-4))
packet_size = packet_size / 2;
if (packet_size < 60)
packet_size = packet_size + 60;
end
$display("do_rx_response_to_tx packet_size = %0d", packet_size);
send_packet_loop(1, packet_size, 2'b01, 1, eth_phy0.eth_speed,
IPG, 48'h0012_3456_789a,
48'h0708_090A_0B0C, 1, 1'b0, 0);
// If RX enable went low, wait for it go high again
if (ethmac_rxen===1'b0)
begin
while (ethmac_rxen===1'b0)
begin
@(posedge ethmac_rxen);
#10000;
end
// RX disabled and when re-enabled we reset the buffer
// descriptor number
expected_rxbd = num_tx_bds;
 
end
 
end
endtask // do_rx_response_to_tx
 
//
// always@() to check the TX buffer descriptors
//
always @(posedge ethmac_txen)
begin
ethmac_last_txbd_lenstat = 0;
eth_stim_tx_loop_keep_polling=1;
// Wait on the TxBD Ready bit
while(eth_stim_tx_loop_keep_polling)
begin
#10;
get_bd_lenstat(expected_txbd, ethmac_txbd_lenstat);
// Check if we've finished transmitting this BD
if (!ethmac_txbd_lenstat[15] & ethmac_last_txbd_lenstat[15])
// Falling edge of TX BD Ready
eth_stim_detected_packet_tx = 1;
 
ethmac_last_txbd_lenstat = ethmac_txbd_lenstat;
// If TX en goes low then exit
if (!ethmac_txen)
eth_stim_tx_loop_keep_polling = 0;
else if (eth_stim_detected_packet_tx)
begin
// Wait until the eth_phy has finished receiving it
while (eth_phy0.mtxen_i === 1'b1)
#10;
$display("(%t) Check TX packet: bd %d: 0x%h",$time,
expected_txbd, ethmac_txbd_lenstat);
 
// Check the TXBD, see if the packet transmitted OK
if (ethmac_txbd_lenstat[8] | ethmac_txbd_lenstat[3])
begin
// Error occured
`TIME;
$display("*E TX Error of packet %0d detected.",
num_tx_packets);
$display(" TX BD %0d = 0x%h", expected_txbd,
ethmac_txbd_lenstat);
if (ethmac_txbd_lenstat[8])
$display(" Underrun in MAC during TX");
if (ethmac_txbd_lenstat[3])
$display(" Retransmission limit hit");
$finish;
end
else
begin
// Packet was OK, let's compare the contents we
// received with those that were meant to be transmitted
if (eth_stim_check_tx_packet_contents)
begin
check_tx_packet(expected_txbd);
expected_txbd = (expected_txbd + 1) &
num_tx_bds_mask;
num_tx_packets = num_tx_packets + 1;
eth_stim_detected_packet_tx = 0;
end
end
end
end // while (eth_stim_tx_loop_keep_polling)
end // always @ (posedge ethmac_txen)
 
 
//
// Check packet TX'd by MAC was good
//
task check_tx_packet;
input [31:0] tx_bd_num;
reg [31:0] tx_bd_addr;
reg [7:0] phy_byte;
reg [31:0] txpnt_wb; // Pointer in array to where data should be
reg [24:0] txpnt_sdram; // Index in array of shorts for data in SDRAM
// part
reg [21:0] buffer;
reg [7:0] sdram_byte;
reg [31:0] tx_len_bd;
integer i;
integer failure;
begin
failure = 0;
get_bd_lenstat(tx_bd_num, tx_len_bd);
tx_len_bd = {15'd0,tx_len_bd[31:16]};
// Check, if length didn't have to be padded, that
// amount transmitted was correct
if ((tx_len_bd > 60)&(tx_len_bd != (eth_phy0.tx_len-4)))
begin
$display("*E TX packet sent length, %0d != length in TX BD, %0d",
eth_phy0.tx_len-4, tx_len_bd);
#100;
$finish;
end
get_bd_addr(tx_bd_num, tx_bd_addr);
// We're never going to be using more than about 256K of receive buffer
// so let's lop off the top bit of the address pointer - we only want
// the offset from the base of the memory bank
txpnt_wb = {14'd0,tx_bd_addr[17:0]};
txpnt_sdram = tx_bd_addr[24:0];
// Variable we'll use for index in the PHY's TX buffer
buffer = 0; // Start of TX data
`ifdef VERSATILE_SDRAM
for (i=0;i<tx_len_bd;i=i+1)
begin
//$display("Checking address in tx bd 0x%0h",txpnt_sdram);
sdram0.get_byte(txpnt_sdram,sdram_byte);
 
phy_byte = eth_phy0.tx_mem[buffer];
// Debugging output
//$display("txpnt_sdram = 0x%h, sdram_byte = 0x%h, buffer = 0x%h, phy_byte = 0x%h", txpnt_sdram, sdram_byte, buffer, phy_byte);
if (phy_byte !== sdram_byte)
begin
`TIME;
$display("*E Wrong byte (%d) of TX packet! ram = %h, phy = %h",buffer, sdram_byte, phy_byte);
failure = 1;
end
buffer = buffer + 1;
txpnt_sdram = txpnt_sdram+1;
end // for (i=0;i<tx_len_bd;i=i+1)
`else
$display("SET ME UP TO LOOK IN ANOTHER MEMORY!");
$display("RAM pointer for BD is 0x%h, bank offset we'll use is 0x%h",
tx_bd_addr, txpnt_wb);
$finish;
`endif // !`ifdef VERSATILE_SDRAM
if (failure)
begin
#100
`TIME;
$display("*E Error transmitting packet %0d (%0d bytes). Finishing simulation", num_tx_packets, tx_len_bd);
get_bd_lenstat(tx_bd_num, tx_len_bd);
$display(" TXBD lenstat: 0x%0h",tx_len_bd);
$display(" TXBD address: 0x%0h",tx_bd_addr);
$finish;
end
else
begin
#1 $display( "(%0t)(%m) TX packet %0d: %0d bytes in memory OK!",$time,num_tx_packets, tx_len_bd);
end
 
end
endtask // check_tx_packet
 
//
// Task to send a set of packets
//
task send_packet_loop;
input [31:0] num_packets;
input [31:0] length;
input [1:0] length_change; // 0 = none, 1 = incr, 2 = decrement
input [31:0] length_change_size; // Size to change by
input speed;
input [31:0] back_to_back_delay; // #delay setting between packets
input [47:0] dst_mac;
input [47:0] src_mac;
input random_fill;
input random_errors;
input [31:0] random_error_mod;
integer j;
reg error_this_time;
integer error_type; // 0 = rxerr, 1=bad preamble 2=bad crc 3=TODO
reg [31:0] rx_bd_lenstat;
begin
error_type = 0;
error_this_time = 0;
 
if (num_packets == 0)
// Loop forever when num_packets is 0
num_packets = 32'h7fffffff;
if (speed & !(eth_phy0.control_bit14_10[13] === 1'b1))
begin
// write to phy's control register for 100Mbps
eth_phy0.control_bit14_10 = 5'b01000; // bit 13 set - speed 100
// Swapping speeds, give some delay
#10000;
end
else if (!speed & !(eth_phy0.control_bit14_10[13] === 1'b0))
begin
eth_phy0.control_bit14_10 = 5'b00000; // bit 13 reset - speed 10
// Swapping speeds, give some delay
#10000;
end
 
eth_phy0.control_bit8_0 = 9'h1_00;
for(j=0;j<num_packets | length <32;j=j+1)
begin
eth_stim_rx_packet_length = length[15:0]; // Bytes
st_data = 8'h0F;
// setup RX packet in buffer - length is without CRC
set_rx_packet(0, eth_stim_rx_packet_length, 1'b0, dst_mac,
src_mac, 16'h0D0E, st_data, random_fill);
set_rx_addr_type(0, dst_mac, src_mac, 16'h0D0E);
 
// Error type 2 is cause CRC error
append_rx_crc(0, eth_stim_rx_packet_length, 1'b0,
(error_type==2));
if (error_this_time)
begin
if (error_type == 0)
// RX ERR assert during transmit
eth_phy0.send_rx_packet(64'h0055_5555_5555_5555, 4'h7,
8'hD5, 0,
eth_stim_rx_packet_length+4,
1'b0, 1'b1);
else if (error_type == 1)
// Incorrect preamble
eth_phy0.send_rx_packet(64'h0055_5f55_5555_5555, 4'h7,
8'hD5, 0,
eth_stim_rx_packet_length+4,
1'b0, 1'b0);
else
// Normal datapacket
eth_phy0.send_rx_packet(64'h0055_5555_5555_5555, 4'h7,
8'hD5, 0,
eth_stim_rx_packet_length+4,
1'b0, 1'b0);
end
else
eth_phy0.send_rx_packet(64'h0055_5555_5555_5555, 4'h7, 8'hD5,
0, eth_stim_rx_packet_length+4, 1'b0,
1'b0);
 
 
// if RX enable still set (might have gone low during this packet
if (ethmac_rxen)
begin
if (error_this_time)
// Put in dummy length, checking function will skip...
rx_packet_lengths[(eth_rx_num_packets_sent& 12'h3ff)]=32'heeeeeeee;
else
rx_packet_lengths[(eth_rx_num_packets_sent & 12'h3ff)] = length;
eth_rx_num_packets_sent = eth_rx_num_packets_sent + 1;
 
end // if (ethmac_rxen)
else
begin
// Force the loop to finish up
j = num_packets;
end
// Inter-packet gap
#back_to_back_delay;
// Update length
if (length_change == 2'b01)
length = length + length_change_size;
if ((length_change == 2'b10) &&
((length - length_change_size) > 32))
length = length - length_change_size;
 
// Increment error type
if (error_this_time)
error_type = error_type + 1;
if (error_type > 3)
error_type = 0;
 
// Check if we should put in an error this time
if (j%random_error_mod == 0)
error_this_time = 1;
else
error_this_time = 0;
eth_phy0.rx_err(0);
 
// Now wait to check if we have filled up all the RX BDs and
// the this packet would start writing over them. Only really an
// issue when doing minimum IPG tests.
while(((eth_rx_num_packets_sent+1) - eth_rx_num_packets_checked)
== num_rx_bds)
#100;
end // for (j=0;j<num_packets | length <32;j=j+1)
end
endtask // send_packet_loop
 
// Local buffer of "sent" data to the ethernet MAC, we will check against
// Size of our local buffer in bytes
parameter eth_rx_sent_circbuf_size = (16*1024);
parameter eth_rx_sent_circbuf_size_mask = eth_rx_sent_circbuf_size - 1;
integer eth_rx_sent_circbuf_fill_ptr = 0;
integer eth_rx_sent_circbuf_read_ptr = 0;
// The actual buffer
reg [7:0] eth_rx_sent_circbuf [0:eth_rx_sent_circbuf_size-1];
/*
TASKS for set and check RX packets:
-----------------------------------
set_rx_packet
(rxpnt[31:0], len[15:0], plus_nibble, d_addr[47:0], s_addr[47:0], type_len[15:0], start_data[7:0]);
check_rx_packet
(rxpnt_phy[31:0], rxpnt_wb[31:0], len[15:0], plus_nibble, successful_nibble, failure[31:0]);
*/
task set_rx_packet;
input [31:0] rxpnt; // pointer to place in in the phy rx buffer we'll start at
input [15:0] len;
input plus_dribble_nibble; // if length is longer for one nibble
input [47:0] eth_dest_addr;
input [47:0] eth_source_addr;
input [15:0] eth_type_len;
input [7:0] eth_start_data;
input random_fill;
integer i, sd;
reg [47:0] dest_addr;
reg [47:0] source_addr;
reg [15:0] type_len;
reg [21:0] buffer;
reg delta_t;
begin
buffer = rxpnt[21:0];
dest_addr = eth_dest_addr;
source_addr = eth_source_addr;
type_len = eth_type_len;
sd = eth_start_data;
delta_t = 0;
for(i = 0; i < len; i = i + 1)
begin
if (i < 6)
begin
eth_phy0.rx_mem[buffer] = dest_addr[47:40];
dest_addr = dest_addr << 8;
end
else if (i < 12)
begin
eth_phy0.rx_mem[buffer] = source_addr[47:40];
source_addr = source_addr << 8;
end
else if (i < 14)
begin
eth_phy0.rx_mem[buffer] = type_len[15:8];
type_len = type_len << 8;
end
else
begin
if (random_fill)
begin
if (lfsr_last_byte == 0)
eth_phy0.rx_mem[buffer] = lfsr[15:8];
if (lfsr_last_byte == 1)
eth_phy0.rx_mem[buffer] = lfsr[23:16];
if (lfsr_last_byte == 2)
eth_phy0.rx_mem[buffer] = lfsr[31:24];
if (lfsr_last_byte == 3)
begin
eth_phy0.rx_mem[buffer] = lfsr[7:0];
lfsr = {lfsr[30:0],(((lfsr[31] ^ lfsr[6]) ^
lfsr[5]) ^ lfsr[1])};
lfsr_last_byte = 0;
end
else
lfsr_last_byte = lfsr_last_byte + 1;
end // if (random_fill)
else
eth_phy0.rx_mem[buffer] = sd[7:0];
sd = sd + 1;
end // else: !if(i < 14)
 
// Update our local buffer
eth_rx_sent_circbuf[eth_rx_sent_circbuf_fill_ptr]
= eth_phy0.rx_mem[buffer];
eth_rx_sent_circbuf_fill_ptr = (eth_rx_sent_circbuf_fill_ptr+1)&
eth_rx_sent_circbuf_size_mask;
buffer = buffer + 1;
end // for (i = 0; i < len; i = i + 1)
delta_t = !delta_t;
if (plus_dribble_nibble)
eth_phy0.rx_mem[buffer] = {4'h0, 4'hD /*sd[3:0]*/};
delta_t = !delta_t;
end
endtask // set_rx_packet
 
 
 
 
task set_rx_addr_type;
input [31:0] rxpnt;
input [47:0] eth_dest_addr;
input [47:0] eth_source_addr;
input [15:0] eth_type_len;
integer i;
reg [47:0] dest_addr;
reg [47:0] source_addr;
reg [15:0] type_len;
reg [21:0] buffer;
reg delta_t;
begin
buffer = rxpnt[21:0];
dest_addr = eth_dest_addr;
source_addr = eth_source_addr;
type_len = eth_type_len;
delta_t = 0;
for(i = 0; i < 14; i = i + 1)
begin
if (i < 6)
begin
eth_phy0.rx_mem[buffer] = dest_addr[47:40];
dest_addr = dest_addr << 8;
end
else if (i < 12)
begin
eth_phy0.rx_mem[buffer] = source_addr[47:40];
source_addr = source_addr << 8;
end
else // if (i < 14)
begin
eth_phy0.rx_mem[buffer] = type_len[15:8];
type_len = type_len << 8;
end
buffer = buffer + 1;
end
delta_t = !delta_t;
end
endtask // set_rx_addr_type
 
 
// Check if we're using a synthesized version of eth module
`ifdef ethmac_IS_GATELEVEL
 
// Get the length/status register of the ethernet buffer descriptor
task get_bd_lenstat;
input [31:0] bd_num;// Number of ethernet BD to check
output [31:0] bd_lenstat;
`ifdef ACTEL
reg [8:0] tmp;
integer raddr;
`endif
begin
`ifdef ACTEL
// Pull from the Actel memory model
raddr = `ETH_BD_RAM_PATH.\mem_tile.I_1 .get_address((bd_num*2));
tmp = `ETH_BD_RAM_PATH.\mem_tile.I_1 .MEM_512_9[(raddr*2)];
bd_lenstat[8:0] = tmp[8:0];
tmp = `ETH_BD_RAM_PATH.\mem_tile.I_1 .MEM_512_9[(raddr*2)+1];
bd_lenstat[17:9] = tmp[8:0];
 
raddr = `ETH_BD_RAM_PATH.\mem_tile_0.I_1 .get_address((bd_num*2));
tmp = `ETH_BD_RAM_PATH.\mem_tile_0.I_1 .MEM_512_9[(raddr*2)];
bd_lenstat[26:18] = tmp[8:0];
tmp = `ETH_BD_RAM_PATH.\mem_tile_0.I_1 .MEM_512_9[(raddr*2)+1];
bd_lenstat[31:27] = tmp[4:0];
 
//$display("(%t) read eth bd lenstat %h",$time, bd_lenstat);
`endif
end
endtask // get_bd_lenstat
// Get the length/status register of the ethernet buffer descriptor
task get_bd_addr;
input [31:0] bd_num;// Number of the ethernet BD to check
output [31:0] bd_addr;
`ifdef ACTEL
reg [8:0] tmp;
integer raddr;
`endif
begin
`ifdef ACTEL
// Pull from the Actel memory model
raddr = `ETH_BD_RAM_PATH.\mem_tile.I_1 .get_address((bd_num*2)+1);
 
tmp = `ETH_BD_RAM_PATH.\mem_tile.I_1 .MEM_512_9[(raddr*2)];
bd_addr[8:0] = tmp[8:0];
 
tmp = `ETH_BD_RAM_PATH.\mem_tile.I_1 .MEM_512_9[(raddr*2)+1];
bd_addr[17:9] = tmp[8:0];
 
raddr = `ETH_BD_RAM_PATH.\mem_tile_0.I_1 .get_address((bd_num*2)+1);
 
tmp = `ETH_BD_RAM_PATH.\mem_tile_0.I_1 .MEM_512_9[(raddr*2)];
bd_addr[26:18] = tmp[8:0];
 
tmp = `ETH_BD_RAM_PATH.\mem_tile_0.I_1 .MEM_512_9[(raddr*2)+1];
bd_addr[31:27] = tmp[4:0];
 
//$display("(%t) read eth bd%d addr %h",$time,bd_num, bd_addr);
`endif
end
endtask // get_bd_addr
 
`else // !`ifdef ethmac_IS_GATELEVEL
// Get the length/status register of the ethernet buffer descriptor
task get_bd_lenstat;
input [31:0] bd_num;// Number of ethernet BD to check
output [31:0] bd_lenstat;
begin
bd_lenstat = `ETH_BD_RAM_PATH.mem[(bd_num*2)];
end
endtask // get_bd_lenstat
// Get the length/status register of the ethernet buffer descriptor
task get_bd_addr;
input [31:0] bd_num;// Number of the ethernet BD to check
output [31:0] bd_addr;
begin
bd_addr = `ETH_BD_RAM_PATH.mem[((bd_num*2)+1)];
//$display("(%t) read eth bd%d addr %h",$time,bd_num, bd_addr);
end
endtask // get_bd_addr
`endif
 
// Always block triggered by finishing of transmission of new packet from
// send_packet_loop
integer eth_rx_packet_length_to_check;
always @*
begin
// Loop here until:
// 1 - packets sent is not equal to packets checked (ie. some to check)
// 2 - we're explicitly disabled for some reason
// 3 - Receive has been disabled in the MAC
while((eth_rx_num_packets_sent == eth_rx_num_packets_checked) ||
!eth_stim_check_rx_packet_contents || !(ethmac_rxen===1'b1))
#1000;
 
eth_rx_packet_length_to_check
= rx_packet_lengths[(eth_rx_num_packets_checked & 12'h3ff)];
if ( eth_rx_packet_length_to_check !== 32'heeeeeeee)
check_rx_packet(expected_rxbd, 0, eth_rx_packet_length_to_check);
eth_rx_num_packets_checked = eth_rx_num_packets_checked + 1;
expected_rxbd = expected_rxbd + 1;
// Wrap
if (expected_rxbd == (num_tx_bds + num_rx_bds))
expected_rxbd = num_tx_bds;
end
task check_rx_packet;
input [31:0] rx_bd_num;
input [31:0] rxpnt_phy; // Pointer in array of data in PHY
input [31:0] len;
reg [31:0] rx_bd_lenstat;
reg [31:0] rx_bd_addr;
reg [7:0] phy_byte;
reg [31:0] rxpnt_wb; // Pointer in array to where data should be
reg [24:0] rxpnt_sdram; // byte address from CPU in RAM
reg [15:0] sdram_short;
reg [7:0] sdram_byte;
//reg [7:0] phy_rx_mem [0:2000];
integer i;
integer failure;
begin
 
failure = 0;
// Wait until the buffer descriptor indicates the packet has been
// received...
get_bd_lenstat(rx_bd_num, rx_bd_lenstat);
while (rx_bd_lenstat & 32'h00008000)// Check Empty bit
begin
#10;
get_bd_lenstat(rx_bd_num, rx_bd_lenstat);
//$display("(%t) check_rx_packet: poll bd %d: 0x%h",$time,
// rx_bd_num, rx_bd_lenstat);
end
 
// Delay some time - takes a bit for the Wishbone FSM to pipe out the
// packet over Wishbone and into whatever memory it's going into
#Td_rx_packet_check;
// Ok, buffer filled, let's get its offset in memory
get_bd_addr(rx_bd_num, rx_bd_addr);
 
$display("(%t) Check RX packet: bd %d: 0x%h, addr 0x%h",$time,
rx_bd_num, rx_bd_lenstat, rx_bd_addr);
 
// We're never going to be using more than about 256KB of receive buffer
// so let's lop off the top bit of the address pointer - we only want
// the offset from the base of the memory bank
rxpnt_wb = {14'd0,rx_bd_addr[17:0]};
rxpnt_sdram = rx_bd_addr[24:0];
`ifdef VERSATILE_SDRAM
// We'll look inside the SDRAM array
// Hard coded for the SDRAM buffer area to be from the halfway mark in
// memory (so starting in Bank2)
// We'll be passed the offset from the beginning of the buffer area
// in rxpnt_wb. This value will be in bytes.
//$display("RAM pointer for BD is 0x%h, SDRAM addr is 0x%h", rx_bd_addr, rxpnt_sdram);
 
 
for (i=0;i<len;i=i+1)
begin
 
sdram0.get_byte(rxpnt_sdram,sdram_byte);
 
phy_byte = eth_rx_sent_circbuf[eth_rx_sent_circbuf_read_ptr];//phy_rx_mem[buffer]; //eth_phy0.rx_mem[buffer];
 
if (phy_byte !== sdram_byte)
begin
// `TIME;
$display("*E Wrong byte (%5d) of RX packet %5d! phy = %h, ram = %h",
i, eth_rx_num_packets_checked, phy_byte, sdram_byte);
failure = 1;
end
 
eth_rx_sent_circbuf_read_ptr = (eth_rx_sent_circbuf_read_ptr+1)&
eth_rx_sent_circbuf_size_mask;
 
rxpnt_sdram = rxpnt_sdram+1;
end // for (i=0;i<len;i=i+2)
`else
 
$display("SET ME UP TO LOOK IN ANOTHER MEMORY!");
$display("RAM pointer for BD is 0x%h, bank offset we'll use is 0x%h",
rx_bd_addr, rxpnt_wb);
$finish;
`endif // !`ifdef VERSATILE_SDRAM
 
if (failure)
begin
#100
`TIME;
$display("*E Recieved packet %0d, length %0d bytes, had an error. Finishing simulation.", eth_rx_num_packets_checked, len);
$finish;
end
else
begin
#1 $display( "(%0t)(%m) RX packet %0d: %0d bytes in memory OK!",$time,eth_rx_num_packets_checked, len);
end
end
endtask // check_rx_packet
//////////////////////////////////////////////////////////////
// Ethernet CRC Basic tasks
//////////////////////////////////////////////////////////////
 
task append_rx_crc;
input [31:0] rxpnt_phy; // source
input [15:0] len; // length in bytes without CRC
input plus_dribble_nibble; // if length is longer for one nibble
input negated_crc; // if appended CRC is correct or not
reg [31:0] crc;
reg [7:0] tmp;
reg [31:0] addr_phy;
reg delta_t;
begin
addr_phy = rxpnt_phy + len;
delta_t = 0;
// calculate CRC from prepared packet
paralel_crc_phy_rx(rxpnt_phy, {16'h0, len}, plus_dribble_nibble, crc);
if (negated_crc)
crc = ~crc;
delta_t = !delta_t;
 
if (plus_dribble_nibble)
begin
tmp = eth_phy0.rx_mem[addr_phy];
eth_phy0.rx_mem[addr_phy] = {crc[27:24], tmp[3:0]};
eth_phy0.rx_mem[addr_phy + 1] = {crc[19:16], crc[31:28]};
eth_phy0.rx_mem[addr_phy + 2] = {crc[11:8], crc[23:20]};
eth_phy0.rx_mem[addr_phy + 3] = {crc[3:0], crc[15:12]};
eth_phy0.rx_mem[addr_phy + 4] = {4'h0, crc[7:4]};
end
else
begin
eth_phy0.rx_mem[addr_phy] = crc[31:24];
eth_phy0.rx_mem[addr_phy + 1] = crc[23:16];
eth_phy0.rx_mem[addr_phy + 2] = crc[15:8];
eth_phy0.rx_mem[addr_phy + 3] = crc[7:0];
end
end
endtask // append_rx_crc
 
task append_rx_crc_delayed;
input [31:0] rxpnt_phy; // source
input [15:0] len; // length in bytes without CRC
input plus_dribble_nibble; // if length is longer for one nibble
input negated_crc; // if appended CRC is correct or not
reg [31:0] crc;
reg [7:0] tmp;
reg [31:0] addr_phy;
reg delta_t;
begin
addr_phy = rxpnt_phy + len;
delta_t = 0;
// calculate CRC from prepared packet
paralel_crc_phy_rx(rxpnt_phy+4, {16'h0, len}-4, plus_dribble_nibble, crc);
if (negated_crc)
crc = ~crc;
delta_t = !delta_t;
 
if (plus_dribble_nibble)
begin
tmp = eth_phy0.rx_mem[addr_phy];
eth_phy0.rx_mem[addr_phy] = {crc[27:24], tmp[3:0]};
eth_phy0.rx_mem[addr_phy + 1] = {crc[19:16], crc[31:28]};
eth_phy0.rx_mem[addr_phy + 2] = {crc[11:8], crc[23:20]};
eth_phy0.rx_mem[addr_phy + 3] = {crc[3:0], crc[15:12]};
eth_phy0.rx_mem[addr_phy + 4] = {4'h0, crc[7:4]};
end
else
begin
eth_phy0.rx_mem[addr_phy] = crc[31:24];
eth_phy0.rx_mem[addr_phy + 1] = crc[23:16];
eth_phy0.rx_mem[addr_phy + 2] = crc[15:8];
eth_phy0.rx_mem[addr_phy + 3] = crc[7:0];
end
end
endtask // append_rx_crc_delayed
 
 
// paralel CRC calculating for PHY RX
task paralel_crc_phy_rx;
input [31:0] start_addr; // start address
input [31:0] len; // length of frame in Bytes without CRC length
input plus_dribble_nibble; // if length is longer for one nibble
output [31:0] crc_out;
reg [21:0] addr_cnt; // only 22 address lines
integer word_cnt;
integer nibble_cnt;
reg [31:0] load_reg;
reg delta_t;
reg [31:0] crc_next;
reg [31:0] crc;
reg crc_error;
reg [3:0] data_in;
integer i;
begin
#1 addr_cnt = start_addr[21:0];
word_cnt = 24; // 27; // start of the frame - nibble granularity (MSbit first)
crc = 32'hFFFF_FFFF; // INITIAL value
delta_t = 0;
// length must include 4 bytes of ZEROs, to generate CRC
// get number of nibbles from Byte length (2^1 = 2)
if (plus_dribble_nibble)
nibble_cnt = ((len + 4) << 1) + 1'b1; // one nibble longer
else
nibble_cnt = ((len + 4) << 1);
// because of MAGIC NUMBER nibbles are swapped [3:0] -> [0:3]
load_reg[31:24] = eth_phy0.rx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
load_reg[23:16] = eth_phy0.rx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
load_reg[15: 8] = eth_phy0.rx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
load_reg[ 7: 0] = eth_phy0.rx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
while (nibble_cnt > 0)
begin
// wait for delta time
delta_t = !delta_t;
// shift data in
 
if(nibble_cnt <= 8) // for additional 8 nibbles shift ZEROs in!
data_in[3:0] = 4'h0;
else
 
data_in[3:0] = {load_reg[word_cnt], load_reg[word_cnt+1], load_reg[word_cnt+2], load_reg[word_cnt+3]};
crc_next[0] = (data_in[0] ^ crc[28]);
crc_next[1] = (data_in[1] ^ data_in[0] ^ crc[28] ^ crc[29]);
crc_next[2] = (data_in[2] ^ data_in[1] ^ data_in[0] ^ crc[28] ^ crc[29] ^ crc[30]);
crc_next[3] = (data_in[3] ^ data_in[2] ^ data_in[1] ^ crc[29] ^ crc[30] ^ crc[31]);
crc_next[4] = (data_in[3] ^ data_in[2] ^ data_in[0] ^ crc[28] ^ crc[30] ^ crc[31]) ^ crc[0];
crc_next[5] = (data_in[3] ^ data_in[1] ^ data_in[0] ^ crc[28] ^ crc[29] ^ crc[31]) ^ crc[1];
crc_next[6] = (data_in[2] ^ data_in[1] ^ crc[29] ^ crc[30]) ^ crc[ 2];
crc_next[7] = (data_in[3] ^ data_in[2] ^ data_in[0] ^ crc[28] ^ crc[30] ^ crc[31]) ^ crc[3];
crc_next[8] = (data_in[3] ^ data_in[1] ^ data_in[0] ^ crc[28] ^ crc[29] ^ crc[31]) ^ crc[4];
crc_next[9] = (data_in[2] ^ data_in[1] ^ crc[29] ^ crc[30]) ^ crc[5];
crc_next[10] = (data_in[3] ^ data_in[2] ^ data_in[0] ^ crc[28] ^ crc[30] ^ crc[31]) ^ crc[6];
crc_next[11] = (data_in[3] ^ data_in[1] ^ data_in[0] ^ crc[28] ^ crc[29] ^ crc[31]) ^ crc[7];
crc_next[12] = (data_in[2] ^ data_in[1] ^ data_in[0] ^ crc[28] ^ crc[29] ^ crc[30]) ^ crc[8];
crc_next[13] = (data_in[3] ^ data_in[2] ^ data_in[1] ^ crc[29] ^ crc[30] ^ crc[31]) ^ crc[9];
crc_next[14] = (data_in[3] ^ data_in[2] ^ crc[30] ^ crc[31]) ^ crc[10];
crc_next[15] = (data_in[3] ^ crc[31]) ^ crc[11];
crc_next[16] = (data_in[0] ^ crc[28]) ^ crc[12];
crc_next[17] = (data_in[1] ^ crc[29]) ^ crc[13];
crc_next[18] = (data_in[2] ^ crc[30]) ^ crc[14];
crc_next[19] = (data_in[3] ^ crc[31]) ^ crc[15];
crc_next[20] = crc[16];
crc_next[21] = crc[17];
crc_next[22] = (data_in[0] ^ crc[28]) ^ crc[18];
crc_next[23] = (data_in[1] ^ data_in[0] ^ crc[29] ^ crc[28]) ^ crc[19];
crc_next[24] = (data_in[2] ^ data_in[1] ^ crc[30] ^ crc[29]) ^ crc[20];
crc_next[25] = (data_in[3] ^ data_in[2] ^ crc[31] ^ crc[30]) ^ crc[21];
crc_next[26] = (data_in[3] ^ data_in[0] ^ crc[31] ^ crc[28]) ^ crc[22];
crc_next[27] = (data_in[1] ^ crc[29]) ^ crc[23];
crc_next[28] = (data_in[2] ^ crc[30]) ^ crc[24];
crc_next[29] = (data_in[3] ^ crc[31]) ^ crc[25];
crc_next[30] = crc[26];
crc_next[31] = crc[27];
 
crc = crc_next;
crc_error = crc[31:0] != 32'hc704dd7b; // CRC not equal to magic number
case (nibble_cnt)
9: crc_out = {!crc[24], !crc[25], !crc[26], !crc[27], !crc[28], !crc[29], !crc[30], !crc[31],
!crc[16], !crc[17], !crc[18], !crc[19], !crc[20], !crc[21], !crc[22], !crc[23],
!crc[ 8], !crc[ 9], !crc[10], !crc[11], !crc[12], !crc[13], !crc[14], !crc[15],
!crc[ 0], !crc[ 1], !crc[ 2], !crc[ 3], !crc[ 4], !crc[ 5], !crc[ 6], !crc[ 7]};
default: crc_out = crc_out;
endcase
// wait for delta time
delta_t = !delta_t;
// increment address and load new data
if ((word_cnt+3) == 7)//4)
begin
// because of MAGIC NUMBER nibbles are swapped [3:0] -> [0:3]
load_reg[31:24] = eth_phy0.rx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
load_reg[23:16] = eth_phy0.rx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
load_reg[15: 8] = eth_phy0.rx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
load_reg[ 7: 0] = eth_phy0.rx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
end
// set new load bit position
if((word_cnt+3) == 31)
word_cnt = 16;
else if ((word_cnt+3) == 23)
word_cnt = 8;
else if ((word_cnt+3) == 15)
word_cnt = 0;
else if ((word_cnt+3) == 7)
word_cnt = 24;
else
word_cnt = word_cnt + 4;// - 4;
// decrement nibble counter
nibble_cnt = nibble_cnt - 1;
// wait for delta time
delta_t = !delta_t;
end // while
#1;
end
endtask // paralel_crc_phy_rx
 
 
/boards/xilinx/ml501/bench/verilog/include/eth_phy_defines.v
0,0 → 1,91
//////////////////////////////////////////////////////////////////////
//// ////
//// File name: eth_phy_defines.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Tadej Markovic, tadej@opencores.org ////
//// ////
//// All additional information is available in the README.txt ////
//// file. ////
//// ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2002, Authors ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.1 2002/09/13 11:57:20 mohor
// New testbench. Thanks to Tadej M - "The Spammer".
//
//
//
 
// Address of PHY device (LXT971A)
`define ETH_PHY_ADDR 5'h00 //Changed to 0 -jb
 
// LED/Configuration pins on PHY device - see the specification, page 26, table 8
// Initial set of bits 13, 12 and 8 of Control Register
`define LED_CFG1 1'b0
`define LED_CFG2 1'b1
`define LED_CFG3 1'b1
 
 
// Supported speeds and physical ports - see the specification, page 67, table 41
// Set bits 15 to 9 of Status Register
`define SUPPORTED_SPEED_AND_PORT 7'h3F
 
// Extended status register (address 15)
// Set bit 8 of Status Register
`define EXTENDED_STATUS 1'b0
 
// Default status bits - see the specification, page 67, table 41
// Set bits 6 to 0 of Status Register
`define DEFAULT_STATUS 7'h09
 
// PHY ID 1 number - see the specification, page 68, table 42
// Set bits of Phy Id Register 1
`define PHY_ID1 16'h0013
 
// PHY ID 2 number - see the specification, page 68, table 43
// Set bits 15 to 10 of Phy Id Register 2
`define PHY_ID2 6'h1E
 
// Manufacturer MODEL number - see the specification, page 68, table 43
// Set bits 9 to 4 of Phy Id Register 2
`define MAN_MODEL_NUM 6'h0E
 
// Manufacturer REVISION number - see the specification, page 68, table 43
// Set bits 3 to 0 of Phy Id Register 2
`define MAN_REVISION_NUM 4'h2
 
 
 
 
/boards/xilinx/ml501/bench/verilog/include/ddr2_model_parameters.v
0,0 → 1,391
/****************************************************************************************
*
* Disclaimer This software code and all associated documentation, comments or other
* of Warranty: information (collectively "Software") is provided "AS IS" without
* warranty of any kind. MICRON TECHNOLOGY, INC. ("MTI") EXPRESSLY
* DISCLAIMS ALL WARRANTIES EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO, NONINFRINGEMENT OF THIRD PARTY RIGHTS, AND ANY IMPLIED WARRANTIES
* OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. MTI DOES NOT
* WARRANT THAT THE SOFTWARE WILL MEET YOUR REQUIREMENTS, OR THAT THE
* OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE.
* FURTHERMORE, MTI DOES NOT MAKE ANY REPRESENTATIONS REGARDING THE USE OR
* THE RESULTS OF THE USE OF THE SOFTWARE IN TERMS OF ITS CORRECTNESS,
* ACCURACY, RELIABILITY, OR OTHERWISE. THE ENTIRE RISK ARISING OUT OF USE
* OR PERFORMANCE OF THE SOFTWARE REMAINS WITH YOU. IN NO EVENT SHALL MTI,
* ITS AFFILIATED COMPANIES OR THEIR SUPPLIERS BE LIABLE FOR ANY DIRECT,
* INDIRECT, CONSEQUENTIAL, INCIDENTAL, OR SPECIAL DAMAGES (INCLUDING,
* WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS INTERRUPTION,
* OR LOSS OF INFORMATION) ARISING OUT OF YOUR USE OF OR INABILITY TO USE
* THE SOFTWARE, EVEN IF MTI HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGES. Because some jurisdictions prohibit the exclusion or
* limitation of liability for consequential or incidental damages, the
* above limitation may not apply to you.
*
* Copyright 2003 Micron Technology, Inc. All rights reserved.
*
****************************************************************************************/
 
// Parameters current with 512Mb datasheet rev N
 
// Timing parameters based on Speed Grade
 
// SYMBOL UNITS DESCRIPTION
`define sg37E
`define x16
 
`ifdef sg37E
parameter TCK_MIN = 3750; // tCK ps Minimum Clock Cycle Time
parameter TJIT_PER = 125; // tJIT(per) ps Period JItter
parameter TJIT_DUTY = 125; // tJIT(duty) ps Half Period Jitter
parameter TJIT_CC = 250; // tJIT(cc) ps Cycle to Cycle jitter
parameter TERR_2PER = 175; // tERR(nper) ps Accumulated Error (2-cycle)
parameter TERR_3PER = 225; // tERR(nper) ps Accumulated Error (3-cycle)
parameter TERR_4PER = 250; // tERR(nper) ps Accumulated Error (4-cycle)
parameter TERR_5PER = 250; // tERR(nper) ps Accumulated Error (5-cycle)
parameter TERR_N1PER = 350; // tERR(nper) ps Accumulated Error (6-10-cycle)
parameter TERR_N2PER = 450; // tERR(nper) ps Accumulated Error (11-50-cycle)
parameter TQHS = 400; // tQHS ps Data hold skew factor
parameter TAC = 500; // tAC ps DQ output access time from CK/CK#
parameter TDS = 100; // tDS ps DQ and DM input setup time relative to DQS
parameter TDH = 225; // tDH ps DQ and DM input hold time relative to DQS
parameter TDQSCK = 450; // tDQSCK ps DQS output access time from CK/CK#
parameter TDQSQ = 300; // tDQSQ ps DQS-DQ skew, DQS to last DQ valid, per group, per access
parameter TIS = 250; // tIS ps Input Setup Time
parameter TIH = 375; // tIH ps Input Hold Time
parameter TRC = 55000; // tRC ps Active to Active/Auto Refresh command time
parameter TRCD = 15000; // tRCD ps Active to Read/Write command time
parameter TWTR = 7500; // tWTR ps Write to Read command delay
parameter TRP = 15000; // tRP ps Precharge command period
parameter TRPA = 15000; // tRPA ps Precharge All period
parameter TXARDS = 6; // tXARDS tCK Exit low power active power down to a read command
parameter TXARD = 2; // tXARD tCK Exit active power down to a read command
parameter TXP = 2; // tXP tCK Exit power down to a non-read command
parameter TANPD = 3; // tANPD tCK ODT to power-down entry latency
parameter TAXPD = 8; // tAXPD tCK ODT power-down exit latency
parameter CL_TIME = 15000; // CL ps Minimum CAS Latency
`else // ------ ----- -----------
`ifdef sg187E
parameter TCK_MIN = 1875; // tCK ps Minimum Clock Cycle Time
parameter TJIT_PER = 90; // tJIT(per) ps Period JItter
parameter TJIT_DUTY = 75; // tJIT(duty) ps Half Period Jitter
parameter TJIT_CC = 180; // tJIT(cc) ps Cycle to Cycle jitter
parameter TERR_2PER = 132; // tERR(nper) ps Accumulated Error (2-cycle)
parameter TERR_3PER = 157; // tERR(nper) ps Accumulated Error (3-cycle)
parameter TERR_4PER = 175; // tERR(nper) ps Accumulated Error (4-cycle)
parameter TERR_5PER = 188; // tERR(nper) ps Accumulated Error (5-cycle)
parameter TERR_N1PER = 250; // tERR(nper) ps Accumulated Error (6-10-cycle)
parameter TERR_N2PER = 425; // tERR(nper) ps Accumulated Error (11-50-cycle)
parameter TQHS = 250; // tQHS ps Data hold skew factor
parameter TAC = 350; // tAC ps DQ output access time from CK/CK#
parameter TDS = 0; // tDS ps DQ and DM input setup time relative to DQS
parameter TDH = 75; // tDH ps DQ and DM input hold time relative to DQS
parameter TDQSCK = 300; // tDQSCK ps DQS output access time from CK/CK#
parameter TDQSQ = 175; // tDQSQ ps DQS-DQ skew, DQS to last DQ valid, per group, per access
parameter TIS = 125; // tIS ps Input Setup Time
parameter TIH = 200; // tIH ps Input Hold Time
parameter TRC = 54000; // tRC ps Active to Active/Auto Refresh command time
parameter TRCD = 13125; // tRCD ps Active to Read/Write command time
parameter TWTR = 7500; // tWTR ps Write to Read command delay
parameter TRP = 13125; // tRP ps Precharge command period
parameter TRPA = 13125; // tRPA ps Precharge All period
parameter TXARDS = 10; // tXARDS tCK Exit low power active power down to a read command
parameter TXARD = 3; // tXARD tCK Exit active power down to a read command
parameter TXP = 3; // tXP tCK Exit power down to a non-read command
parameter TANPD = 4; // tANPD tCK ODT to power-down entry latency
parameter TAXPD = 11; // tAXPD tCK ODT power-down exit latency
parameter CL_TIME = 13125; // CL ps Minimum CAS Latency
`else `ifdef sg25E
parameter TCK_MIN = 2500; // tCK ps Minimum Clock Cycle Time
parameter TJIT_PER = 100; // tJIT(per) ps Period JItter
parameter TJIT_DUTY = 100; // tJIT(duty) ps Half Period Jitter
parameter TJIT_CC = 200; // tJIT(cc) ps Cycle to Cycle jitter
parameter TERR_2PER = 150; // tERR(nper) ps Accumulated Error (2-cycle)
parameter TERR_3PER = 175; // tERR(nper) ps Accumulated Error (3-cycle)
parameter TERR_4PER = 200; // tERR(nper) ps Accumulated Error (4-cycle)
parameter TERR_5PER = 200; // tERR(nper) ps Accumulated Error (5-cycle)
parameter TERR_N1PER = 300; // tERR(nper) ps Accumulated Error (6-10-cycle)
parameter TERR_N2PER = 450; // tERR(nper) ps Accumulated Error (11-50-cycle)
parameter TQHS = 300; // tQHS ps Data hold skew factor
parameter TAC = 400; // tAC ps DQ output access time from CK/CK#
parameter TDS = 50; // tDS ps DQ and DM input setup time relative to DQS
parameter TDH = 125; // tDH ps DQ and DM input hold time relative to DQS
parameter TDQSCK = 350; // tDQSCK ps DQS output access time from CK/CK#
parameter TDQSQ = 200; // tDQSQ ps DQS-DQ skew, DQS to last DQ valid, per group, per access
parameter TIS = 175; // tIS ps Input Setup Time
parameter TIH = 250; // tIH ps Input Hold Time
parameter TRC = 55000; // tRC ps Active to Active/Auto Refresh command time
parameter TRCD = 12500; // tRCD ps Active to Read/Write command time
parameter TWTR = 7500; // tWTR ps Write to Read command delay
parameter TRP = 12500; // tRP ps Precharge command period
parameter TRPA = 12500; // tRPA ps Precharge All period
parameter TXARDS = 8; // tXARDS tCK Exit low power active power down to a read command
parameter TXARD = 2; // tXARD tCK Exit active power down to a read command
parameter TXP = 2; // tXP tCK Exit power down to a non-read command
parameter TANPD = 3; // tANPD tCK ODT to power-down entry latency
parameter TAXPD = 10; // tAXPD tCK ODT power-down exit latency
parameter CL_TIME = 12500; // CL ps Minimum CAS Latency
`else `ifdef sg25
parameter TCK_MIN = 2500; // tCK ps Minimum Clock Cycle Time
parameter TJIT_PER = 100; // tJIT(per) ps Period JItter
parameter TJIT_DUTY = 100; // tJIT(duty) ps Half Period Jitter
parameter TJIT_CC = 200; // tJIT(cc) ps Cycle to Cycle jitter
parameter TERR_2PER = 150; // tERR(nper) ps Accumulated Error (2-cycle)
parameter TERR_3PER = 175; // tERR(nper) ps Accumulated Error (3-cycle)
parameter TERR_4PER = 200; // tERR(nper) ps Accumulated Error (4-cycle)
parameter TERR_5PER = 200; // tERR(nper) ps Accumulated Error (5-cycle)
parameter TERR_N1PER = 300; // tERR(nper) ps Accumulated Error (6-10-cycle)
parameter TERR_N2PER = 450; // tERR(nper) ps Accumulated Error (11-50-cycle)
parameter TQHS = 300; // tQHS ps Data hold skew factor
parameter TAC = 400; // tAC ps DQ output access time from CK/CK#
parameter TDS = 50; // tDS ps DQ and DM input setup time relative to DQS
parameter TDH = 125; // tDH ps DQ and DM input hold time relative to DQS
parameter TDQSCK = 350; // tDQSCK ps DQS output access time from CK/CK#
parameter TDQSQ = 200; // tDQSQ ps DQS-DQ skew, DQS to last DQ valid, per group, per access
parameter TIS = 175; // tIS ps Input Setup Time
parameter TIH = 250; // tIH ps Input Hold Time
parameter TRC = 55000; // tRC ps Active to Active/Auto Refresh command time
parameter TRCD = 15000; // tRCD ps Active to Read/Write command time
parameter TWTR = 7500; // tWTR ps Write to Read command delay
parameter TRP = 15000; // tRP ps Precharge command period
parameter TRPA = 15000; // tRPA ps Precharge All period
parameter TXARDS = 8; // tXARDS tCK Exit low power active power down to a read command
parameter TXARD = 2; // tXARD tCK Exit active power down to a read command
parameter TXP = 2; // tXP tCK Exit power down to a non-read command
parameter TANPD = 3; // tANPD tCK ODT to power-down entry latency
parameter TAXPD = 10; // tAXPD tCK ODT power-down exit latency
parameter CL_TIME = 15000; // CL ps Minimum CAS Latency
`else `ifdef sg3E
parameter TCK_MIN = 3000; // tCK ps Minimum Clock Cycle Time
parameter TJIT_PER = 125; // tJIT(per) ps Period JItter
parameter TJIT_DUTY = 125; // tJIT(duty) ps Half Period Jitter
parameter TJIT_CC = 250; // tJIT(cc) ps Cycle to Cycle jitter
parameter TERR_2PER = 175; // tERR(nper) ps Accumulated Error (2-cycle)
parameter TERR_3PER = 225; // tERR(nper) ps Accumulated Error (3-cycle)
parameter TERR_4PER = 250; // tERR(nper) ps Accumulated Error (4-cycle)
parameter TERR_5PER = 250; // tERR(nper) ps Accumulated Error (5-cycle)
parameter TERR_N1PER = 350; // tERR(nper) ps Accumulated Error (6-10-cycle)
parameter TERR_N2PER = 450; // tERR(nper) ps Accumulated Error (11-50-cycle)
parameter TQHS = 340; // tQHS ps Data hold skew factor
parameter TAC = 450; // tAC ps DQ output access time from CK/CK#
parameter TDS = 100; // tDS ps DQ and DM input setup time relative to DQS
parameter TDH = 175; // tDH ps DQ and DM input hold time relative to DQS
parameter TDQSCK = 400; // tDQSCK ps DQS output access time from CK/CK#
parameter TDQSQ = 240; // tDQSQ ps DQS-DQ skew, DQS to last DQ valid, per group, per access
parameter TIS = 200; // tIS ps Input Setup Time
parameter TIH = 275; // tIH ps Input Hold Time
parameter TRC = 54000; // tRC ps Active to Active/Auto Refresh command time
parameter TRCD = 12000; // tRCD ps Active to Read/Write command time
parameter TWTR = 7500; // tWTR ps Write to Read command delay
parameter TRP = 12000; // tRP ps Precharge command period
parameter TRPA = 12000; // tRPA ps Precharge All period
parameter TXARDS = 7; // tXARDS tCK Exit low power active power down to a read command
parameter TXARD = 2; // tXARD tCK Exit active power down to a read command
parameter TXP = 2; // tXP tCK Exit power down to a non-read command
parameter TANPD = 3; // tANPD tCK ODT to power-down entry latency
parameter TAXPD = 8; // tAXPD tCK ODT power-down exit latency
parameter CL_TIME = 12000; // CL ps Minimum CAS Latency
`else `ifdef sg3
parameter TCK_MIN = 3000; // tCK ps Minimum Clock Cycle Time
parameter TJIT_PER = 125; // tJIT(per) ps Period JItter
parameter TJIT_DUTY = 125; // tJIT(duty) ps Half Period Jitter
parameter TJIT_CC = 250; // tJIT(cc) ps Cycle to Cycle jitter
parameter TERR_2PER = 175; // tERR(nper) ps Accumulated Error (2-cycle)
parameter TERR_3PER = 225; // tERR(nper) ps Accumulated Error (3-cycle)
parameter TERR_4PER = 250; // tERR(nper) ps Accumulated Error (4-cycle)
parameter TERR_5PER = 250; // tERR(nper) ps Accumulated Error (5-cycle)
parameter TERR_N1PER = 350; // tERR(nper) ps Accumulated Error (6-10-cycle)
parameter TERR_N2PER = 450; // tERR(nper) ps Accumulated Error (11-50-cycle)
parameter TQHS = 340; // tQHS ps Data hold skew factor
parameter TAC = 450; // tAC ps DQ output access time from CK/CK#
parameter TDS = 100; // tDS ps DQ and DM input setup time relative to DQS
parameter TDH = 175; // tDH ps DQ and DM input hold time relative to DQS
parameter TDQSCK = 400; // tDQSCK ps DQS output access time from CK/CK#
parameter TDQSQ = 240; // tDQSQ ps DQS-DQ skew, DQS to last DQ valid, per group, per access
parameter TIS = 200; // tIS ps Input Setup Time
parameter TIH = 275; // tIH ps Input Hold Time
parameter TRC = 55000; // tRC ps Active to Active/Auto Refresh command time
parameter TRCD = 15000; // tRCD ps Active to Read/Write command time
parameter TWTR = 7500; // tWTR ps Write to Read command delay
parameter TRP = 15000; // tRP ps Precharge command period
parameter TRPA = 15000; // tRPA ps Precharge All period
parameter TXARDS = 7; // tXARDS tCK Exit low power active power down to a read command
parameter TXARD = 2; // tXARD tCK Exit active power down to a read command
parameter TXP = 2; // tXP tCK Exit power down to a non-read command
parameter TANPD = 3; // tANPD tCK ODT to power-down entry latency
parameter TAXPD = 8; // tAXPD tCK ODT power-down exit latency
parameter CL_TIME = 15000; // CL ps Minimum CAS Latency
`else `define sg5E
parameter TCK_MIN = 5000; // tCK ps Minimum Clock Cycle Time
parameter TJIT_PER = 125; // tJIT(per) ps Period JItter
parameter TJIT_DUTY = 150; // tJIT(duty) ps Half Period Jitter
parameter TJIT_CC = 250; // tJIT(cc) ps Cycle to Cycle jitter
parameter TERR_2PER = 175; // tERR(nper) ps Accumulated Error (2-cycle)
parameter TERR_3PER = 225; // tERR(nper) ps Accumulated Error (3-cycle)
parameter TERR_4PER = 250; // tERR(nper) ps Accumulated Error (4-cycle)
parameter TERR_5PER = 250; // tERR(nper) ps Accumulated Error (5-cycle)
parameter TERR_N1PER = 350; // tERR(nper) ps Accumulated Error (6-10-cycle)
parameter TERR_N2PER = 450; // tERR(nper) ps Accumulated Error (11-50-cycle)
parameter TQHS = 450; // tQHS ps Data hold skew factor
parameter TAC = 600; // tAC ps DQ output access time from CK/CK#
parameter TDS = 150; // tDS ps DQ and DM input setup time relative to DQS
parameter TDH = 275; // tDH ps DQ and DM input hold time relative to DQS
parameter TDQSCK = 500; // tDQSCK ps DQS output access time from CK/CK#
parameter TDQSQ = 350; // tDQSQ ps DQS-DQ skew, DQS to last DQ valid, per group, per access
parameter TIS = 350; // tIS ps Input Setup Time
parameter TIH = 475; // tIH ps Input Hold Time
parameter TRC = 55000; // tRC ps Active to Active/Auto Refresh command time
parameter TRCD = 15000; // tRCD ps Active to Read/Write command time
parameter TWTR = 10000; // tWTR ps Write to Read command delay
parameter TRP = 15000; // tRP ps Precharge command period
parameter TRPA = 15000; // tRPA ps Precharge All period
parameter TXARDS = 6; // tXARDS tCK Exit low power active power down to a read command
parameter TXARD = 2; // tXARD tCK Exit active power down to a read command
parameter TXP = 2; // tXP tCK Exit power down to a non-read command
parameter TANPD = 3; // tANPD tCK ODT to power-down entry latency
parameter TAXPD = 8; // tAXPD tCK ODT power-down exit latency
parameter CL_TIME = 15000; // CL ps Minimum CAS Latency
`endif `endif `endif `endif `endif `endif
 
`ifdef x16
`ifdef sg187E
parameter TFAW = 45000; // tFAW ps Four Bank Activate window
`else `ifdef sg25E
parameter TFAW = 45000; // tFAW ps Four Bank Activate window
`else `ifdef sg25
parameter TFAW = 45000; // tFAW ps Four Bank Activate window
`else // sg3E, sg3, sg37E, sg5E
parameter TFAW = 50000; // tFAW ps Four Bank Activate window
`endif `endif `endif
`else // x4, x8
`ifdef sg187E
parameter TFAW = 35000; // tFAW ps Four Bank Activate window
`else `ifdef sg25E
parameter TFAW = 35000; // tFAW ps Four Bank Activate window
`else `ifdef sg25
parameter TFAW = 35000; // tFAW ps Four Bank Activate window
`else // sg3E, sg3, sg37E, sg5E
parameter TFAW = 37500; // tFAW ps Four Bank Activate window
`endif `endif `endif
`endif
 
// Timing Parameters
 
// Mode Register
parameter AL_MIN = 0; // AL tCK Minimum Additive Latency
parameter AL_MAX = 6; // AL tCK Maximum Additive Latency
parameter CL_MIN = 3; // CL tCK Minimum CAS Latency
parameter CL_MAX = 7; // CL tCK Maximum CAS Latency
parameter WR_MIN = 2; // WR tCK Minimum Write Recovery
parameter WR_MAX = 8; // WR tCK Maximum Write Recovery
parameter BL_MIN = 4; // BL tCK Minimum Burst Length
parameter BL_MAX = 8; // BL tCK Minimum Burst Length
// Clock
parameter TCK_MAX = 8000; // tCK ps Maximum Clock Cycle Time
parameter TCH_MIN = 0.48; // tCH tCK Minimum Clock High-Level Pulse Width
parameter TCH_MAX = 0.52; // tCH tCK Maximum Clock High-Level Pulse Width
parameter TCL_MIN = 0.48; // tCL tCK Minimum Clock Low-Level Pulse Width
parameter TCL_MAX = 0.52; // tCL tCK Maximum Clock Low-Level Pulse Width
// Data
parameter TLZ = TAC; // tLZ ps Data-out low-impedance window from CK/CK#
parameter THZ = TAC; // tHZ ps Data-out high impedance window from CK/CK#
parameter TDIPW = 0.35; // tDIPW tCK DQ and DM input Pulse Width
// Data Strobe
parameter TDQSH = 0.35; // tDQSH tCK DQS input High Pulse Width
parameter TDQSL = 0.35; // tDQSL tCK DQS input Low Pulse Width
parameter TDSS = 0.20; // tDSS tCK DQS falling edge to CLK rising (setup time)
parameter TDSH = 0.20; // tDSH tCK DQS falling edge from CLK rising (hold time)
parameter TWPRE = 0.35; // tWPRE tCK DQS Write Preamble
parameter TWPST = 0.40; // tWPST tCK DQS Write Postamble
parameter TDQSS = 0.25; // tDQSS tCK Rising clock edge to DQS/DQS# latching transition
// Command and Address
parameter TIPW = 0.6; // tIPW tCK Control and Address input Pulse Width
parameter TCCD = 2; // tCCD tCK Cas to Cas command delay
parameter TRAS_MIN = 40000; // tRAS ps Minimum Active to Precharge command time
parameter TRAS_MAX =70000000; // tRAS ps Maximum Active to Precharge command time
parameter TRTP = 7500; // tRTP ps Read to Precharge command delay
parameter TWR = 15000; // tWR ps Write recovery time
parameter TMRD = 2; // tMRD tCK Load Mode Register command cycle time
parameter TDLLK = 200; // tDLLK tCK DLL locking time
// Refresh
parameter TRFC_MIN = 105000; // tRFC ps Refresh to Refresh Command interval minimum value
parameter TRFC_MAX =70000000; // tRFC ps Refresh to Refresh Command Interval maximum value
// Self Refresh
parameter TXSNR = TRFC_MIN + 10000; // tXSNR ps Exit self refesh to a non-read command
parameter TXSRD = 200; // tXSRD tCK Exit self refresh to a read command
parameter TISXR = TIS; // tISXR ps CKE setup time during self refresh exit.
// ODT
parameter TAOND = 2; // tAOND tCK ODT turn-on delay
parameter TAOFD = 2.5; // tAOFD tCK ODT turn-off delay
parameter TAONPD = 2000; // tAONPD ps ODT turn-on (precharge power-down mode)
parameter TAOFPD = 2000; // tAOFPD ps ODT turn-off (precharge power-down mode)
parameter TMOD = 12000; // tMOD ps ODT enable in EMR to ODT pin transition
// Power Down
parameter TCKE = 3; // tCKE tCK CKE minimum high or low pulse width
 
// Size Parameters based on Part Width
 
`ifdef x4
parameter ADDR_BITS = 14; // Address Bits
parameter ROW_BITS = 14; // Number of Address bits
parameter COL_BITS = 11; // Number of Column bits
parameter DM_BITS = 1; // Number of Data Mask bits
parameter DQ_BITS = 4; // Number of Data bits
parameter DQS_BITS = 1; // Number of Dqs bits
parameter TRRD = 7500; // tRRD Active bank a to Active bank b command time
`else `ifdef x8
parameter ADDR_BITS = 14; // Address Bits
parameter ROW_BITS = 14; // Number of Address bits
parameter COL_BITS = 10; // Number of Column bits
parameter DM_BITS = 1; // Number of Data Mask bits
parameter DQ_BITS = 8; // Number of Data bits
parameter DQS_BITS = 1; // Number of Dqs bits
parameter TRRD = 7500; // tRRD Active bank a to Active bank b command time
`else `define x16
parameter ADDR_BITS = 13; // Address Bits
parameter ROW_BITS = 13; // Number of Address bits
parameter COL_BITS = 10; // Number of Column bits
parameter DM_BITS = 2; // Number of Data Mask bits
parameter DQ_BITS = 16; // Number of Data bits
parameter DQS_BITS = 2; // Number of Dqs bits
parameter TRRD = 10000; // tRRD Active bank a to Active bank b command time
`endif `endif
 
`ifdef QUAD_RANK
`define DUAL_RANK // also define DUAL_RANK
parameter CS_BITS = 4; // Number of Chip Select Bits
parameter RANKS = 4; // Number of Chip Select Bits
`else `ifdef DUAL_RANK
parameter CS_BITS = 2; // Number of Chip Select Bits
parameter RANKS = 2; // Number of Chip Select Bits
`else
parameter CS_BITS = 2; // Number of Chip Select Bits
parameter RANKS = 1; // Number of Chip Select Bits
`endif `endif
 
// Size Parameters
parameter BA_BITS = 2; // Set this parmaeter to control how many Bank Address bits
// if MEM_BITS== 14, a DQ=16 each part, DQ=64 total (4 parts) => 1MB total (256KB each)
// if MEM_BITS== 15, a DQ=16 each part, DQ=64 total (4 parts) => 2MB total (512KB each)
// if MEM_BITS== 16, a DQ=16 each part, DQ=64 total (4 parts) => 4MB total (1MB each)
// if MEM_BITS== 17, a DQ=16 each part, DQ=64 total (4 parts) => 8MB total (2MB each)
//parameter MEM_BITS = 14; // Number of write data bursts can be stored in memory. The default is 2^10=1024.
parameter MEM_BITS = 17; // Number of write data bursts can be stored in memory.
parameter AP = 10; // the address bit that controls auto-precharge and precharge-all
parameter BL_BITS = 3; // the number of bits required to count to MAX_BL
parameter BO_BITS = 2; // the number of Burst Order Bits
 
// Simulation parameters
parameter STOP_ON_ERROR = 1; // If set to 1, the model will halt on command sequence/major errors
parameter DEBUG = 0; // Turn on Debug messages
parameter BUS_DELAY = 0; // delay in nanoseconds
parameter RANDOM_OUT_DELAY = 0; // If set to 1, the model will put a random amount of delay on DQ/DQS during reads
parameter RANDOM_SEED = 711689044; //seed value for random generator.
 
parameter RDQSEN_PRE = 2; // DQS driving time prior to first read strobe
parameter RDQSEN_PST = 1; // DQS driving time after last read strobe
parameter RDQS_PRE = 2; // DQS low time prior to first read strobe
parameter RDQS_PST = 1; // DQS low time after last valid read strobe
parameter RDQEN_PRE = 0; // DQ/DM driving time prior to first read data
parameter RDQEN_PST = 0; // DQ/DM driving time after last read data
parameter WDQS_PRE = 1; // DQS half clock periods prior to first write strobe
parameter WDQS_PST = 1; // DQS half clock periods after last valid write strobe
/boards/xilinx/ml501/bench/verilog/include/ddr2_model_preload.v
0,0 → 1,56
// File intended to be included in the generate statement for each DDR2 part.
// The following loads a vmem file, "sram.vmem" by default, into the SDRAM.
 
// Wait until the DDR memory is initialised, and then magically
// load it
@(posedge dut.xilinx_ddr2_0.xilinx_ddr2_if0.phy_init_done);
//$display("%t: Loading DDR2",$time);
 
$readmemh("sram.vmem", program_array);
/* Now dish it out to the DDR2 model's memory */
for(ram_ptr = 0 ; ram_ptr < 4096 ; ram_ptr = ram_ptr + 1)
begin
 
// Construct the burst line, with every second word from where we
// started, and picking the correct half of the word with i%2
program_word_ptr = ram_ptr * 16 + (i/2) ; // Start on word0 or word1
tmp_program_word = program_array[program_word_ptr];
ddr2_ram_mem_line[15:0] = tmp_program_word[15 + ((i%2)*16):((i%2)*16)];
 
program_word_ptr = program_word_ptr + 2;
tmp_program_word = program_array[program_word_ptr];
ddr2_ram_mem_line[31:16] = tmp_program_word[15 + ((i%2)*16):((i%2)*16)];
program_word_ptr = program_word_ptr + 2;
tmp_program_word = program_array[program_word_ptr];
ddr2_ram_mem_line[47:32] = tmp_program_word[15 + ((i%2)*16):((i%2)*16)];
program_word_ptr = program_word_ptr + 2;
tmp_program_word = program_array[program_word_ptr];
ddr2_ram_mem_line[63:48] = tmp_program_word[15 + ((i%2)*16):((i%2)*16)];
program_word_ptr = program_word_ptr + 2;
tmp_program_word = program_array[program_word_ptr];
ddr2_ram_mem_line[79:64] = tmp_program_word[15 + ((i%2)*16):((i%2)*16)];
program_word_ptr = program_word_ptr + 2;
tmp_program_word = program_array[program_word_ptr];
ddr2_ram_mem_line[95:80] = tmp_program_word[15 + ((i%2)*16):((i%2)*16)];
program_word_ptr = program_word_ptr + 2;
tmp_program_word = program_array[program_word_ptr];
ddr2_ram_mem_line[111:96] = tmp_program_word[15 + ((i%2)*16):((i%2)*16)];
program_word_ptr = program_word_ptr + 2;
tmp_program_word = program_array[program_word_ptr];
ddr2_ram_mem_line[127:112] = tmp_program_word[15 + ((i%2)*16):((i%2)*16)];
// Put this assembled line into the RAM using its memory writing TASK
u_mem0.memory_write(2'b00,ram_ptr[19:7],
{ram_ptr[6:0],3'b000},ddr2_ram_mem_line);
//$display("Writing 0x%h, ramline=%d",ddr2_ram_mem_line, ram_ptr);
end // for (ram_ptr = 0 ; ram_ptr < ...
$display("(%t) * DDR2 RAM %1d preloaded",$time, i);
end // initial begin
/boards/xilinx/ml501/bench/verilog/include/synthesis-defines.v
0,0 → 1,2
// Nothing in here, just providing synthesis-defines.v for files that include
// it (clkgen, for one.)
/boards/xilinx/ml501/bench/verilog/orpsoc_testbench.v
0,0 → 1,572
//////////////////////////////////////////////////////////////////////
/// ////
/// ORPSoC ML501 testbench ////
/// ////
/// Instantiate ORPSoC, monitors, provide stimulus ////
/// ////
/// Julius Baxter, julius@opencores.org ////
/// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2009, 2010 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
 
`include "orpsoc-defines.v"
`include "orpsoc-testbench-defines.v"
`include "test-defines.v"
`include "timescale.v"
// Xilinx simulation:
`include "glbl.v"
 
module orpsoc_testbench;
 
// Clock and reset signal registers
reg clk = 0;
reg rst_n = 1; // Active LOW
always
#((`BOARD_CLOCK_PERIOD)/2) clk <= ~clk;
 
wire clk_n, clk_p;
assign clk_p = clk;
assign clk_n = ~clk;
 
// Reset, ACTIVE LOW
initial
begin
#1;
repeat (32) @(negedge clk)
rst_n <= 1;
repeat (32) @(negedge clk)
rst_n <= 0;
repeat (32) @(negedge clk)
rst_n <= 1;
end
 
// Include design parameters file
`include "orpsoc-params.v"
 
// Pullup bus for I2C
tri1 i2c_scl, i2c_sda;
`ifdef JTAG_DEBUG
wire tdo_pad_o;
wire tck_pad_i;
wire tms_pad_i;
wire tdi_pad_i;
`endif
`ifdef UART0
wire uart0_stx_pad_o;
wire uart0_srx_pad_i;
`endif
`ifdef GPIO0
wire [gpio0_io_width-1:0] gpio0_io;
`endif
`ifdef SPI0
wire spi0_mosi_o;
wire spi0_miso_i;
wire spi0_sck_o;
wire spi0_hold_n_o;
wire spi0_w_n_o;
wire [spi0_ss_width-1:0] spi0_ss_o;
`endif
`ifdef ETH0
wire mtx_clk_o;
wire [3:0] ethphy_mii_tx_d;
wire ethphy_mii_tx_en;
wire ethphy_mii_tx_err;
wire mrx_clk_o;
wire [3:0] mrxd_o;
wire mrxdv_o;
wire mrxerr_o;
wire mcoll_o;
wire mcrs_o;
wire ethphy_rst_n;
wire eth0_mdc_pad_o;
wire eth0_md_pad_io;
`endif
`ifdef XILINX_DDR2
`include "xilinx_ddr2_params.v"
localparam DEVICE_WIDTH = 16; // Memory device data width
localparam real CLK_PERIOD_NS = CLK_PERIOD / 1000.0;
localparam real TCYC_200 = 5.0;
localparam real TPROP_DQS = 0.00; // Delay for DQS signal during Write Operation
localparam real TPROP_DQS_RD = 0.00; // Delay for DQS signal during Read Operation
localparam real TPROP_PCB_CTRL = 0.00; // Delay for Address and Ctrl signals
localparam real TPROP_PCB_DATA = 0.00; // Delay for data signal during Write operation
localparam real TPROP_PCB_DATA_RD = 0.00; // Delay for data signal during Read operation
 
wire [DQ_WIDTH-1:0] ddr2_dq_sdram;
wire [DQS_WIDTH-1:0] ddr2_dqs_sdram;
wire [DQS_WIDTH-1:0] ddr2_dqs_n_sdram;
wire [DM_WIDTH-1:0] ddr2_dm_sdram;
reg [DM_WIDTH-1:0] ddr2_dm_sdram_tmp;
reg [CLK_WIDTH-1:0] ddr2_ck_sdram;
reg [CLK_WIDTH-1:0] ddr2_ck_n_sdram;
reg [ROW_WIDTH-1:0] ddr2_a_sdram;
reg [BANK_WIDTH-1:0] ddr2_ba_sdram;
reg ddr2_ras_n_sdram;
reg ddr2_cas_n_sdram;
reg ddr2_we_n_sdram;
reg [CS_WIDTH-1:0] ddr2_cs_n_sdram;
reg [CKE_WIDTH-1:0] ddr2_cke_sdram;
reg [ODT_WIDTH-1:0] ddr2_odt_sdram;
wire [DQ_WIDTH-1:0] ddr2_dq_fpga;
wire [DQS_WIDTH-1:0] ddr2_dqs_fpga;
wire [DQS_WIDTH-1:0] ddr2_dqs_n_fpga;
wire [DM_WIDTH-1:0] ddr2_dm_fpga;
wire [CLK_WIDTH-1:0] ddr2_ck_fpga;
wire [CLK_WIDTH-1:0] ddr2_ck_n_fpga;
wire [ROW_WIDTH-1:0] ddr2_a_fpga;
wire [BANK_WIDTH-1:0] ddr2_ba_fpga;
wire ddr2_ras_n_fpga;
wire ddr2_cas_n_fpga;
wire ddr2_we_n_fpga;
wire [CS_WIDTH-1:0] ddr2_cs_n_fpga;
wire [CKE_WIDTH-1:0] ddr2_cke_fpga;
wire [ODT_WIDTH-1:0] ddr2_odt_fpga;
`endif
`ifdef XILINX_SSRAM
wire sram_clk;
wire sram_clk_fb;
wire sram_adv_ld_n;
wire [3:0] sram_bw;
wire sram_cen;
wire [21:1] sram_flash_addr;
wire [31:0] sram_flash_data;
wire sram_flash_oe_n;
wire sram_flash_we_n;
wire sram_mode;
`endif
 
orpsoc_top dut
(
`ifdef JTAG_DEBUG
.tms_pad_i (tms_pad_i),
.tck_pad_i (tck_pad_i),
.tdi_pad_i (tdi_pad_i),
.tdo_pad_o (tdo_pad_o),
`endif
`ifdef XILINX_DDR2
.ddr2_a (ddr2_a_fpga),
.ddr2_ba (ddr2_ba_fpga),
.ddr2_ras_n (ddr2_ras_n_fpga),
.ddr2_cas_n (ddr2_cas_n_fpga),
.ddr2_we_n (ddr2_we_n_fpga),
.ddr2_cs_n (ddr2_cs_n_fpga),
.ddr2_odt (ddr2_odt_fpga),
.ddr2_cke (ddr2_cke_fpga),
.ddr2_dm (ddr2_dm_fpga),
.ddr2_ck (ddr2_ck_fpga),
.ddr2_ck_n (ddr2_ck_n_fpga),
.ddr2_dq (ddr2_dq_fpga),
.ddr2_dqs (ddr2_dqs_fpga),
.ddr2_dqs_n (ddr2_dqs_n_fpga),
`endif
`ifdef XILINX_SSRAM
.sram_clk (sram_clk),
.sram_flash_addr (sram_flash_addr),
.sram_cen (sram_cen),
.sram_flash_oe_n (sram_flash_oe_n),
.sram_flash_we_n (sram_flash_we_n),
.sram_bw (sram_bw),
.sram_adv_ld_n (sram_adv_ld_n),
.sram_mode (sram_mode),
.sram_clk_fb (sram_clk_fb),
.sram_flash_data (sram_flash_data),
`endif
`ifdef UART0
.uart0_stx_pad_o (uart0_stx_pad_o),
.uart0_srx_pad_i (uart0_srx_pad_i),
.uart0_stx_expheader_pad_o (uart0_stx_pad_o),
.uart0_srx_expheader_pad_i (uart0_srx_pad_i),
`endif
`ifdef SPI0
.spi0_sck_o (spi0_sck_o),
.spi0_mosi_o (spi0_mosi_o),
.spi0_miso_i (spi0_miso_i),
.spi0_ss_o (spi0_ss_o),
`endif
`ifdef I2C0
.i2c0_sda_io (i2c_sda),
.i2c0_scl_io (i2c_scl),
`endif
`ifdef I2C1
.i2c1_sda_io (i2c_sda),
.i2c1_scl_io (i2c_scl),
`endif
`ifdef GPIO0
.gpio0_io (gpio0_io),
`endif
`ifdef ETH0
.eth0_tx_clk (mtx_clk_o),
.eth0_tx_data (ethphy_mii_tx_d),
.eth0_tx_en (ethphy_mii_tx_en),
.eth0_tx_er (ethphy_mii_tx_err),
.eth0_rx_clk (mrx_clk_o),
.eth0_rx_data (mrxd_o),
.eth0_dv (mrxdv_o),
.eth0_rx_er (mrxerr_o),
.eth0_col (mcoll_o),
.eth0_crs (mcrs_o),
.eth0_rst_n_o (ethphy_rst_n),
.eth0_mdc_pad_o (eth0_mdc_pad_o),
.eth0_md_pad_io (eth0_md_pad_io),
`endif // `ifdef ETH0
 
.sys_clk_in_p (clk_p),
.sys_clk_in_n (clk_n),
 
.rst_n_pad_i (rst_n)
);
 
//
// Instantiate OR1200 monitor
//
or1200_monitor monitor();
 
`ifndef SIM_QUIET
`define CPU_ic_top or1200_ic_top
`define CPU_dc_top or1200_dc_top
wire ic_en = orpsoc_testbench.dut.or1200_top0.or1200_ic_top.ic_en;
always @(posedge ic_en)
$display("Or1200 IC enabled at %t", $time);
 
wire dc_en = orpsoc_testbench.dut.or1200_top0.or1200_dc_top.dc_en;
always @(posedge dc_en)
$display("Or1200 DC enabled at %t", $time);
`endif
 
 
`ifdef JTAG_DEBUG
`ifdef VPI_DEBUG
// Debugging interface
vpi_debug_module vpi_dbg
(
.tms(tms_pad_i),
.tck(tck_pad_i),
.tdi(tdi_pad_i),
.tdo(tdo_pad_o)
);
`else
// If no VPI debugging, tie off JTAG inputs
assign tdi_pad_i = 1;
assign tck_pad_i = 0;
assign tms_pad_i = 1;
`endif // !`ifdef VPI_DEBUG_ENABLE
`endif // `ifdef JTAG_DEBUG
`ifdef SPI0
// SPI flash memory - M25P16 compatible SPI protocol
AT26DFxxx spi0_flash
(// Outputs
.SO (spi0_miso_i),
// Inputs
.CSB (spi0_ss_o),
.SCK (spi0_sck_o),
.SI (spi0_mosi_o),
.WPB (1'b1)
);
`endif // `ifdef SPI0
 
`ifdef ETH0
/* TX/RXes packets and checks them, enabled when ethernet MAC is */
`include "eth_stim.v"
 
eth_phy eth_phy0
(
// Outputs
.mtx_clk_o (mtx_clk_o),
.mrx_clk_o (mrx_clk_o),
.mrxd_o (mrxd_o[3:0]),
.mrxdv_o (mrxdv_o),
.mrxerr_o (mrxerr_o),
.mcoll_o (mcoll_o),
.mcrs_o (mcrs_o),
.link_o (),
.speed_o (),
.duplex_o (),
.smii_clk_i (1'b0),
.smii_sync_i (1'b0),
.smii_rx_o (),
// Inouts
.md_io (eth0_md_pad_io),
// Inputs
`ifndef ETH0_PHY_RST
// If no reset out from the design, hook up to the board's active low rst
.m_rst_n_i (rst_n),
`else
.m_rst_n_i (ethphy_rst_n),
`endif
.mtxd_i (ethphy_mii_tx_d[3:0]),
.mtxen_i (ethphy_mii_tx_en),
.mtxerr_i (ethphy_mii_tx_err),
.mdc_i (eth0_mdc_pad_o));
 
`endif // `ifdef ETH0
 
`ifdef XILINX_SSRAM
wire [18:0] sram_a;
wire [3:0] dqp;
assign sram_a[18:0] = sram_flash_addr[19:1];
wire sram_ce1b, sram_ce2, sram_ce3b;
assign sram_ce1b = 1'b0;
assign sram_ce2 = 1'b1;
assign sram_ce3b = 1'b0;
assign sram_clk_fb = sram_clk;
 
cy7c1354 ssram0
(
// Inouts
// This model puts each parity bit after each byte, but the ML501's part
// doesn't, so we wire up the data bus like so.
.d ({dqp[3],sram_flash_data[31:24],
dqp[2],sram_flash_data[23:16],
dqp[1],sram_flash_data[15:8],
dqp[0],sram_flash_data[7:0]}),
// Inputs
.clk (sram_clk),
.we_b (sram_flash_we_n),
.adv_lb (sram_adv_ld_n),
.ce1b (sram_ce1b),
.ce2 (sram_ce2),
.ce3b (sram_ce3b),
.oeb (sram_flash_oe_n),
.cenb (sram_cen),
.mode (sram_mode),
.bws (sram_bw),
.a (sram_a));
`endif
 
`ifdef XILINX_DDR2
`ifndef GATE_SIM
defparam dut.xilinx_ddr2_0.xilinx_ddr2_if0.ddr2_mig0.SIM_ONLY = 1;
`endif
 
always @( * ) begin
ddr2_ck_sdram <= #(TPROP_PCB_CTRL) ddr2_ck_fpga;
ddr2_ck_n_sdram <= #(TPROP_PCB_CTRL) ddr2_ck_n_fpga;
ddr2_a_sdram <= #(TPROP_PCB_CTRL) ddr2_a_fpga;
ddr2_ba_sdram <= #(TPROP_PCB_CTRL) ddr2_ba_fpga;
ddr2_ras_n_sdram <= #(TPROP_PCB_CTRL) ddr2_ras_n_fpga;
ddr2_cas_n_sdram <= #(TPROP_PCB_CTRL) ddr2_cas_n_fpga;
ddr2_we_n_sdram <= #(TPROP_PCB_CTRL) ddr2_we_n_fpga;
ddr2_cs_n_sdram <= #(TPROP_PCB_CTRL) ddr2_cs_n_fpga;
ddr2_cke_sdram <= #(TPROP_PCB_CTRL) ddr2_cke_fpga;
ddr2_odt_sdram <= #(TPROP_PCB_CTRL) ddr2_odt_fpga;
ddr2_dm_sdram_tmp <= #(TPROP_PCB_DATA) ddr2_dm_fpga;//DM signal generation
end // always @ ( * )
// Model delays on bi-directional BUS
genvar dqwd;
generate
for (dqwd = 0;dqwd < DQ_WIDTH;dqwd = dqwd+1) begin : dq_delay
wiredelay #
(
.Delay_g (TPROP_PCB_DATA),
.Delay_rd (TPROP_PCB_DATA_RD)
)
u_delay_dq
(
.A (ddr2_dq_fpga[dqwd]),
.B (ddr2_dq_sdram[dqwd]),
.reset (rst_n)
);
end
endgenerate
genvar dqswd;
generate
for (dqswd = 0;dqswd < DQS_WIDTH;dqswd = dqswd+1) begin : dqs_delay
wiredelay #
(
.Delay_g (TPROP_DQS),
.Delay_rd (TPROP_DQS_RD)
)
u_delay_dqs
(
.A (ddr2_dqs_fpga[dqswd]),
.B (ddr2_dqs_sdram[dqswd]),
.reset (rst_n)
);
wiredelay #
(
.Delay_g (TPROP_DQS),
.Delay_rd (TPROP_DQS_RD)
)
u_delay_dqs_n
(
.A (ddr2_dqs_n_fpga[dqswd]),
.B (ddr2_dqs_n_sdram[dqswd]),
.reset (rst_n)
);
end
endgenerate
assign ddr2_dm_sdram = ddr2_dm_sdram_tmp;
parameter NUM_PROGRAM_WORDS=1048576;
integer ram_ptr, program_word_ptr, k;
reg [31:0] tmp_program_word;
reg [31:0] program_array [0:NUM_PROGRAM_WORDS-1]; // 1M words = 4MB
reg [8*16-1:0] ddr2_ram_mem_line; //8*16-bits= 8 shorts (half-words)
genvar i, j;
generate
// if the data width is multiple of 16
for(j = 0; j < CS_NUM; j = j+1) begin : gen_cs // Loop of 1
for(i = 0; i < DQS_WIDTH/2; i = i+1) begin : gen // Loop of 4 (DQS_WIDTH=8)
initial
begin
 
`ifdef PRELOAD_RAM
`include "ddr2_model_preload.v"
`endif
ddr2_model u_mem0
(
.ck (ddr2_ck_sdram[CLK_WIDTH*i/DQS_WIDTH]),
.ck_n (ddr2_ck_n_sdram[CLK_WIDTH*i/DQS_WIDTH]),
.cke (ddr2_cke_sdram[j]),
.cs_n (ddr2_cs_n_sdram[CS_WIDTH*i/DQS_WIDTH]),
.ras_n (ddr2_ras_n_sdram),
.cas_n (ddr2_cas_n_sdram),
.we_n (ddr2_we_n_sdram),
.dm_rdqs (ddr2_dm_sdram[(2*(i+1))-1 : i*2]),
.ba (ddr2_ba_sdram),
.addr (ddr2_a_sdram),
.dq (ddr2_dq_sdram[(16*(i+1))-1 : i*16]),
.dqs (ddr2_dqs_sdram[(2*(i+1))-1 : i*2]),
.dqs_n (ddr2_dqs_n_sdram[(2*(i+1))-1 : i*2]),
.rdqs_n (),
.odt (ddr2_odt_sdram[ODT_WIDTH*i/DQS_WIDTH])
);
end
end
endgenerate
`endif
 
`ifdef VCD
reg vcd_go = 0;
always @(vcd_go)
begin
`ifdef VCD_DELAY
#(`VCD_DELAY);
`endif
 
// Delay by x insns
`ifdef VCD_DELAY_INSNS
#10; // Delay until after the value becomes valid
while (monitor.insns < `VCD_DELAY_INSNS)
@(posedge clk);
`endif
 
`ifdef SIMULATOR_MODELSIM
// Modelsim can GZip VCDs on the fly if given in the suffix
`define VCD_SUFFIX ".vcd.gz"
`else
`define VCD_SUFFIX ".vcd"
`endif
`ifndef SIM_QUIET
$display("* VCD in %s\n", {"../out/",`TEST_NAME_STRING,`VCD_SUFFIX});
`endif
$dumpfile({"../out/",`TEST_NAME_STRING,`VCD_SUFFIX});
`ifndef VCD_DEPTH
`define VCD_DEPTH 0
`endif
$dumpvars(`VCD_DEPTH);
end
`endif // `ifdef VCD
initial
begin
`ifndef SIM_QUIET
$display("\n* Starting simulation of design RTL.\n* Test: %s\n",
`TEST_NAME_STRING );
`endif
`ifdef VCD
vcd_go = 1;
`endif
end // initial begin
`ifdef END_TIME
initial begin
#(`END_TIME);
`ifndef SIM_QUIET
$display("* Finish simulation due to END_TIME being set at %t", $time);
`endif
$finish;
end
`endif
 
`ifdef END_INSNS
initial begin
#10
while (monitor.insns < `END_INSNS)
@(posedge clk);
`ifndef SIM_QUIET
$display("* Finish simulation due to END_INSNS count (%d) reached at %t",
`END_INSNS, $time);
`endif
$finish;
end
`endif
`ifdef UART0
//
// UART0 decoder
//
uart_decoder
#(
.uart_baudrate_period_ns(8680) // 115200 baud = period 8.68uS
)
uart0_decoder
(
.clk(clk),
.uart_tx(uart0_stx_pad_o)
);
// Loopback UART lines
assign uart0_srx_pad_i = uart0_stx_pad_o;
 
`endif // `ifdef UART0
endmodule // orpsoc_testbench
 
// Local Variables:
// verilog-library-directories:("." "../../rtl/verilog/orpsoc_top")
// verilog-library-files:()
// verilog-library-extensions:(".v" ".h")
// End:
 
/boards/xilinx/ml501/rtl/eth_defines.v File deleted \ No newline at end of file
/boards/xilinx/ml501/rtl/ml501_ddr2_wb_if_cache.v File deleted \ No newline at end of file
/boards/xilinx/ml501/rtl/ml501_ddr2_wb_if.v.prev File deleted \ No newline at end of file
/boards/xilinx/ml501/rtl/ddr2_mig/ddr2_usr_top.v File deleted \ No newline at end of file
/boards/xilinx/ml501/rtl/ddr2_mig/ddr2_chipscope.v File deleted \ No newline at end of file
/boards/xilinx/ml501/rtl/verilog/xilinx_ssram/xilinx_ssram.v
0,0 → 1,300
//////////////////////////////////////////////////////////////////////
//// ////
//// Xilinx ML501 SSRAM controller with Wishbone Interface ////
//// ////
//// Description ////
//// ZBT SSRAM controller for ML501 board part (or any ZBT RAM) ////
//// Timing relies on definition of multi-cycle paths during ////
//// synthesis. ////
//// ////
//// To Do: ////
//// ////
//// Author(s): ////
//// - Julius Baxter, julius.baxter@orsoc.se ////
//// ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2010 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
/*
* Controller for ZBT synchronous SRAM (ISSI IS61NLP25636A-200TQL)
* Explicitly uses Xilinx primitives
* Currently configured for a 1/4 ratio between bus/ssram clocks: 50 / 200 MHz
* Requires declaration of some multi-cycle paths during synthesis.
*
* Note: clk_200 and bus clock should be in phase (from same DCM)
*
* Clocking/phase counting scheme (to change it to higher/lower ratio):
*
* We run a phase counter, checking the bus on the last cycle before we hit another multiple of the SSRAM clock to the bus clock (so cycle 3 if ratio is 4, or a 50MHz system bus and 200MHz SRAM), this gives the system bus signals almost another whole cycle to reach our 200MHz regs (and where we define one of the multi-cycle paths). Once we have the stuff registered it's business as usual on the bus to the SRAM. Then we let it sit in our register for a clock or two
*/
module xilinx_ssram
(
// WB ports
input [31:0] wb_adr_i,
input wb_stb_i,
input wb_cyc_i,
input wb_we_i,
input [3:0] wb_sel_i,
input [31:0] wb_dat_i,
output [31:0] wb_dat_o,
output wb_ack_o,
input wb_clk,
input wb_rst,
 
// SSRAM interface
input clk_200,
output wire sram_clk,
input sram_clk_fb,
output reg [21:1] sram_addr,
inout [31:0] sram_dq_io,
output reg sram_ce_l,
output reg sram_oe_l,
output reg sram_we_l,
output reg [3:0] sram_bw_l,
output reg sram_adv_ld_l,
output sram_mode
);
 
wire [31:0] sram_dq_i;
reg [31:0] sram_dq_o;
reg ssram_controller_oe_l;
wire dcm0_clk0_prebufg, dcm0_clk0;
wire dcm0_locked;
 
wire dcms_locked;
 
reg wb_clk_r = 1'b0;
reg wb_clk_r_d;
wire wb_clk_edge;
 
reg wb_ack_write;
reg [2:0] wb_ack_read_shiftreg;
reg [2:0] clk_200_phase;
reg [4:0] clk_200_cycle_counter;
reg [31:0] data_rd;
wire [3:0] we;
reg write_cycle;
reg [3:0] we_r;
reg reg_from_bus_domain, reg_from_bus_domain_r;
 
assign dcms_locked = dcm0_locked;
assign we = wb_sel_i & {4{wb_cyc_i & wb_stb_i & wb_we_i}};
assign sram_clk = dcm0_clk0;
 
// Do wb_clk edge detection with this
assign wb_clk_edge = wb_clk_r & ~wb_clk_r_d;
assign sram_mode = 0;
initial begin
$display("* SSRAM controller instantiated at %m.");
end
 
// We ACK writes after one cycle
always @(posedge wb_clk)
wb_ack_write <= wb_cyc_i & wb_stb_i & wb_we_i & !wb_ack_write;
 
// We ACK reads after 3
always @(posedge wb_clk)
wb_ack_read_shiftreg <= {wb_ack_read_shiftreg[1:0], wb_cyc_i & wb_stb_i & !wb_we_i & !(|wb_ack_read_shiftreg)};
assign wb_ack_o = wb_we_i ? wb_ack_write : wb_ack_read_shiftreg[2];
 
// Push the bus clock through a register
always @(posedge wb_clk) begin
wb_clk_r <= ~wb_clk_r;
end
// Sample this with the 150 MHz clock
always @(posedge clk_200) begin
wb_clk_r_d <= wb_clk_r;
end
// Maintain a phase count, it goes 0->7 (8 phases, to be clear)
always @(posedge clk_200) begin
if (wb_clk_edge) begin
// Will be at 1 next cycle
clk_200_phase <= 3'd1;
end else if (clk_200_phase < 3'd7 & dcms_locked) begin
clk_200_phase <= clk_200_phase + 1;
end else begin
clk_200_phase <= 3'd0;
end
end
// Multicycle trickery
// Reads will happen like this:
// * Read address is given 3 clk_200 cycles to settle
// * It is put onto the bus for two cycles
// * Read data is then registered
// * It then has several phases to make it back to the bus register
// Number of cycles we preload counter with, depending on access
`define WRITE_CYCLES 5'h04
`define READ_CYCLES 5'h0c
// We let the commands settle for 2 cycles (0, 1) and then sample
// *but* data could have come on either cycle 0 _or_ 3, so check both
`define REQ_CHECK_CYCLE ((clk_200_phase == 3'd3)||(clk_200_phase == 3'd7))
// Write OE - whole time, doesn't matter so much
`define WRITE_OE_CYCLE (|clk_200_cycle_counter)
// Read OE, just the first two cycles
//`define READ_OE_CYCLE (clk_200_cycle_counter > (`READ_CYCLES - 5'h4))
`define READ_OE_CYCLE (|clk_200_cycle_counter)
// Sample data from RAM 2 cycles after we sample the addr from system bus
`define RAM_DATA_SAMPLE_CYCLE (!(|we_r) && clk_200_cycle_counter == (`READ_CYCLES - 5'h5))
// Cycle when we pull sram_we_l low
`define WRITE_CE_CYCLE (reg_from_bus_domain & (|we))
// Cycle when we ouptut the CE
`define READ_CE_CYCLE (reg_from_bus_domain & !(|we))
 
// Register stuff when we've just loaded the counter
`define REG_FROM_BUS_DOMAIN reg_from_bus_domain
 
// CE 2 cycles dring writes, only one during reads
always @(posedge clk_200)
sram_ce_l <= 0;
//sram_ce_l <= ~((`WRITE_CE_CYCLE) || (`READ_CE_CYCLE ));
 
always @(posedge clk_200)
sram_adv_ld_l <= 0;
//sram_adv_ld_l <= ~((`WRITE_CE_CYCLE) || (`READ_CE_CYCLE ));
 
always @(posedge clk_200)
sram_we_l <= ~(`WRITE_CE_CYCLE);
 
always @(posedge clk_200)
if (`REG_FROM_BUS_DOMAIN)
sram_addr[21:1] <= wb_adr_i[22:2];
 
always @(posedge clk_200)
if (`REG_FROM_BUS_DOMAIN)
sram_dq_o <= wb_dat_i;
always @(posedge clk_200)
if (`REG_FROM_BUS_DOMAIN)
sram_bw_l <= ~we;
always @(posedge clk_200)
sram_oe_l <= ~((`READ_OE_CYCLE) & !(|(we_r | we)));
 
always @(posedge clk_200)
ssram_controller_oe_l = ~((`WRITE_OE_CYCLE) & (|we_r));
// Register data from SSRAM
always @(posedge clk_200)
if (`RAM_DATA_SAMPLE_CYCLE)
data_rd[31:0] <= sram_dq_i[31:0];
 
assign wb_dat_o = data_rd;
// Determine if we've got a request
// This logic means the bus' control signals are slightly
// more constrained than the data and address.
always @(posedge clk_200)
begin
if (|clk_200_cycle_counter)
clk_200_cycle_counter <= clk_200_cycle_counter - 1;
else if (`REQ_CHECK_CYCLE)
if (wb_cyc_i & wb_stb_i)
clk_200_cycle_counter <= wb_we_i ?
`WRITE_CYCLES : `READ_CYCLES;
else
clk_200_cycle_counter <= 0;
end // always @ (posedge clk_200)
 
always @(posedge clk_200)
begin
reg_from_bus_domain <= ((`REQ_CHECK_CYCLE) & wb_cyc_i & wb_stb_i & !(|clk_200_cycle_counter));
reg_from_bus_domain_r <= reg_from_bus_domain;
end
 
// Must clear
always @(posedge clk_200)
if (`REG_FROM_BUS_DOMAIN)
we_r <= we;
else if (!(|clk_200_cycle_counter))
we_r <= 0;
/* SSRAM Clocking configuration */
 
/* DCM de-skewing SSRAM clock via external trace */
DCM_BASE dcm0
(/*AUTOINST*/
// Outputs
.CLK0 (dcm0_clk0_prebufg),
.CLK180 (),
.CLK270 (),
.CLK2X180 (),
.CLK2X (),
.CLK90 (),
.CLKDV (),
.CLKFX180 (),
.CLKFX (),
.LOCKED (dcm0_locked),
// Inputs
.CLKFB (sram_clk_fb),
.CLKIN (clk_200),
.RST (wb_rst));
BUFG dcm0_clk0_bufg
(// Outputs
.O (dcm0_clk0),
// Inputs
.I (dcm0_clk0_prebufg));
 
/* Generate the DQ bus tristate buffers */
genvar i;
generate
for (i=0; i<32; i=i+1) begin: SSRAM_DQ_TRISTATE
IOBUF U (.O(sram_dq_i[i]),
.IO(sram_dq_io[i]),
.I(sram_dq_o[i]),
.T(ssram_controller_oe_l));
end
endgenerate
endmodule // xilinx_ssram
 
// Local Variables:
// verilog-library-directories:(".")
// verilog-library-extensions:(".v" ".h")
// End:
/boards/xilinx/ml501/rtl/verilog/clkgen/clkgen.v
0,0 → 1,205
/*
*
* Clock, reset generation unit for ML501 board
*
* Implements clock generation according to design defines
*
*/
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2009, 2010 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
 
`include "orpsoc-defines.v"
`include "synthesis-defines.v"
 
module clkgen
(
// Main clocks in, depending on board
sys_clk_in_p, sys_clk_in_n,
 
// Wishbone clock and reset out
wb_clk_o,
wb_rst_o,
 
// JTAG clock
`ifdef JTAG_DEBUG
tck_pad_i,
dbg_tck_o,
`endif
// Main memory clocks
`ifdef XILINX_DDR2
ddr2_if_clk_o,
ddr2_if_rst_o,
clk200_o,
`endif
 
// Asynchronous, active low reset in
rst_n_pad_i
);
 
input sys_clk_in_p,sys_clk_in_n;
 
output wb_rst_o;
output wb_clk_o;
 
`ifdef JTAG_DEBUG
input tck_pad_i;
output dbg_tck_o;
`endif
`ifdef XILINX_DDR2
output ddr2_if_clk_o;
output ddr2_if_rst_o;
output clk200_o;
`endif
 
// Asynchronous, active low reset (pushbutton, typically)
input rst_n_pad_i;
// First, deal with the asychronous reset
wire async_rst;
wire async_rst_n;
 
// Xilinx synthesis tools appear cluey enough to instantiate buffers when and
// where they're needed, so we do simple assigns for this tech.
assign async_rst_n = rst_n_pad_i;
 
// Everyone likes active-high reset signals...
assign async_rst = ~async_rst_n;
`ifdef JTAG_DEBUG
assign dbg_tck_o = tck_pad_i;
`endif
 
//
// Declare synchronous reset wires here
//
// An active-low synchronous reset signal (usually a PLL lock signal)
wire sync_rst_n;
 
// An active-low synchronous reset from ethernet PLL
wire sync_eth_rst_n;
wire sys_clk_in_200;
/* DCM0 wires */
wire dcm0_clk0_prebufg, dcm0_clk0;
wire dcm0_clkfx_prebufg, dcm0_clkfx;
wire dcm0_clkdv_prebufg, dcm0_clkdv;
wire dcm0_locked;
 
/* Dif. input buffer for 200MHz board clock, generate SE 200MHz */
IBUFGDS_LVPECL_25 sys_clk_in_ibufds
(
.O(sys_clk_in_200),
.I(sys_clk_in_p),
.IB(sys_clk_in_n));
/* DCM providing main system/Wishbone clock */
DCM_BASE dcm0
(
// Outputs
.CLK0 (dcm0_clk0_prebufg),
.CLK180 (),
.CLK270 (),
.CLK2X180 (),
.CLK2X (),
.CLK90 (),
.CLKDV (dcm0_clkdv_prebufg),
.CLKFX180 (),
.CLKFX (dcm0_clkfx_prebufg),
.LOCKED (dcm0_locked),
// Inputs
.CLKFB (dcm0_clk0),
.CLKIN (sys_clk_in_200),
.RST (1'b0));
// Generate 266 MHz from CLKFX
defparam dcm0.CLKFX_MULTIPLY = 4;
defparam dcm0.CLKFX_DIVIDE = 3;
 
// Generate 50 MHz from CLKDV
defparam dcm0.CLKDV_DIVIDE = 4.0;
 
BUFG dcm0_clk0_bufg
(// Outputs
.O (dcm0_clk0),
// Inputs
.I (dcm0_clk0_prebufg));
 
BUFG dcm0_clkfx_bufg
(// Outputs
.O (dcm0_clkfx),
// Inputs
.I (dcm0_clkfx_prebufg));
 
BUFG dcm0_clkdv_bufg
(// Outputs
.O (dcm0_clkdv),
// Inputs
.I (dcm0_clkdv_prebufg));
 
assign wb_clk_o = dcm0_clkdv;
assign sync_rst_n = dcm0_locked;
 
`ifdef XILINX_DDR2
assign ddr2_if_clk_o = dcm0_clkfx; // 266MHz
assign clk200_o = dcm0_clk0; // 200MHz
`endif
//
// Reset generation
//
//
 
// Reset generation for wishbone
reg [15:0] wb_rst_shr;
always @(posedge wb_clk_o or posedge async_rst)
if (async_rst)
wb_rst_shr <= 16'hffff;
else
wb_rst_shr <= {wb_rst_shr[14:0], ~(sync_rst_n)};
assign wb_rst_o = wb_rst_shr[15];
 
`ifdef XILINX_DDR2
// Reset generation for DDR2 controller
reg [15:0] ddr2_if_rst_shr;
always @(posedge ddr2_if_clk_o or posedge async_rst)
if (async_rst)
ddr2_if_rst_shr <= 16'hffff;
else
ddr2_if_rst_shr <= {ddr2_if_rst_shr[14:0], ~(sync_rst_n)};
assign ddr2_if_rst_o = ddr2_if_rst_shr[15];
`endif
endmodule // clkgen
/boards/xilinx/ml501/rtl/verilog/include/ethmac_defines.v
0,0 → 1,255
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_defines.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://opencores.org/project,ethmac ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// ////
//// Modified by: ////
//// - Julius Baxter (julius@opencores.org) ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001, 2002 Authors ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
 
 
 
//`define ETH_BIST // Bist for usage with Virtual Silicon RAMS
 
`define ETH_MBIST_CTRL_WIDTH 3 // width of MBIST control bus
 
// Generic FIFO implementation - hopefully synthesizable with Synplify
`define ETH_FIFO_GENERIC
// Ethernet implemented in Xilinx Chips (uncomment following lines)
// `define ETH_FIFO_XILINX // Use Xilinx distributed ram for tx and rx fifo
// `define ETH_XILINX_RAMB4 // Selection of the used memory for Buffer descriptors
// Core is going to be implemented in Virtex FPGA and contains Virtex
// specific elements.
 
// Ethernet implemented in Altera Chips (uncomment following lines)
//`define ETH_ALTERA_ALTSYNCRAM
 
// Ethernet implemented in ASIC with Virtual Silicon RAMs
// `define ETH_VIRTUAL_SILICON_RAM // Virtual Silicon RAMS used storing buffer decriptors (ASIC implementation)
 
// Ethernet implemented in ASIC with Artisan RAMs
// `define ETH_ARTISAN_RAM // Artisan RAMS used storing buffer decriptors (ASIC implementation)
 
// Uncomment when Avalon bus is used
//`define ETH_AVALON_BUS
 
`define ETH_MODER_ADR 8'h0 // 0x0
`define ETH_INT_SOURCE_ADR 8'h1 // 0x4
`define ETH_INT_MASK_ADR 8'h2 // 0x8
`define ETH_IPGT_ADR 8'h3 // 0xC
`define ETH_IPGR1_ADR 8'h4 // 0x10
`define ETH_IPGR2_ADR 8'h5 // 0x14
`define ETH_PACKETLEN_ADR 8'h6 // 0x18
`define ETH_COLLCONF_ADR 8'h7 // 0x1C
`define ETH_TX_BD_NUM_ADR 8'h8 // 0x20
`define ETH_CTRLMODER_ADR 8'h9 // 0x24
`define ETH_MIIMODER_ADR 8'hA // 0x28
`define ETH_MIICOMMAND_ADR 8'hB // 0x2C
`define ETH_MIIADDRESS_ADR 8'hC // 0x30
`define ETH_MIITX_DATA_ADR 8'hD // 0x34
`define ETH_MIIRX_DATA_ADR 8'hE // 0x38
`define ETH_MIISTATUS_ADR 8'hF // 0x3C
`define ETH_MAC_ADDR0_ADR 8'h10 // 0x40
`define ETH_MAC_ADDR1_ADR 8'h11 // 0x44
`define ETH_HASH0_ADR 8'h12 // 0x48
`define ETH_HASH1_ADR 8'h13 // 0x4C
`define ETH_TX_CTRL_ADR 8'h14 // 0x50
`define ETH_RX_CTRL_ADR 8'h15 // 0x54
`define ETH_DBG_ADR 8'h16 // 0x58
 
 
`define ETH_MODER_DEF_0 8'h00
`define ETH_MODER_DEF_1 8'hA0
`define ETH_MODER_DEF_2 1'h0
`define ETH_INT_MASK_DEF_0 7'h0
`define ETH_IPGT_DEF_0 7'h12
`define ETH_IPGR1_DEF_0 7'h0C
`define ETH_IPGR2_DEF_0 7'h12
`define ETH_PACKETLEN_DEF_0 8'h00
`define ETH_PACKETLEN_DEF_1 8'h06
`define ETH_PACKETLEN_DEF_2 8'h40
`define ETH_PACKETLEN_DEF_3 8'h00
`define ETH_COLLCONF_DEF_0 6'h3f
`define ETH_COLLCONF_DEF_2 4'hF
`define ETH_TX_BD_NUM_DEF_0 8'h40
`define ETH_CTRLMODER_DEF_0 3'h0
`define ETH_MIIMODER_DEF_0 8'h64
`define ETH_MIIMODER_DEF_1 1'h0
`define ETH_MIIADDRESS_DEF_0 5'h00
`define ETH_MIIADDRESS_DEF_1 5'h00
`define ETH_MIITX_DATA_DEF_0 8'h00
`define ETH_MIITX_DATA_DEF_1 8'h00
`define ETH_MIIRX_DATA_DEF 16'h0000 // not written from WB
`define ETH_MAC_ADDR0_DEF_0 8'h00
`define ETH_MAC_ADDR0_DEF_1 8'h00
`define ETH_MAC_ADDR0_DEF_2 8'h00
`define ETH_MAC_ADDR0_DEF_3 8'h00
`define ETH_MAC_ADDR1_DEF_0 8'h00
`define ETH_MAC_ADDR1_DEF_1 8'h00
`define ETH_HASH0_DEF_0 8'h00
`define ETH_HASH0_DEF_1 8'h00
`define ETH_HASH0_DEF_2 8'h00
`define ETH_HASH0_DEF_3 8'h00
`define ETH_HASH1_DEF_0 8'h00
`define ETH_HASH1_DEF_1 8'h00
`define ETH_HASH1_DEF_2 8'h00
`define ETH_HASH1_DEF_3 8'h00
`define ETH_TX_CTRL_DEF_0 8'h00 //
`define ETH_TX_CTRL_DEF_1 8'h00 //
`define ETH_TX_CTRL_DEF_2 1'h0 //
`define ETH_RX_CTRL_DEF_0 8'h00
`define ETH_RX_CTRL_DEF_1 8'h00
 
 
`define ETH_MODER_WIDTH_0 8
`define ETH_MODER_WIDTH_1 8
`define ETH_MODER_WIDTH_2 1
`define ETH_INT_SOURCE_WIDTH_0 7
`define ETH_INT_MASK_WIDTH_0 7
`define ETH_IPGT_WIDTH_0 7
`define ETH_IPGR1_WIDTH_0 7
`define ETH_IPGR2_WIDTH_0 7
`define ETH_PACKETLEN_WIDTH_0 8
`define ETH_PACKETLEN_WIDTH_1 8
`define ETH_PACKETLEN_WIDTH_2 8
`define ETH_PACKETLEN_WIDTH_3 8
`define ETH_COLLCONF_WIDTH_0 6
`define ETH_COLLCONF_WIDTH_2 4
`define ETH_TX_BD_NUM_WIDTH_0 8
`define ETH_CTRLMODER_WIDTH_0 3
`define ETH_MIIMODER_WIDTH_0 8
`define ETH_MIIMODER_WIDTH_1 1
`define ETH_MIICOMMAND_WIDTH_0 3
`define ETH_MIIADDRESS_WIDTH_0 5
`define ETH_MIIADDRESS_WIDTH_1 5
`define ETH_MIITX_DATA_WIDTH_0 8
`define ETH_MIITX_DATA_WIDTH_1 8
`define ETH_MIIRX_DATA_WIDTH 16 // not written from WB
`define ETH_MIISTATUS_WIDTH 3 // not written from WB
`define ETH_MAC_ADDR0_WIDTH_0 8
`define ETH_MAC_ADDR0_WIDTH_1 8
`define ETH_MAC_ADDR0_WIDTH_2 8
`define ETH_MAC_ADDR0_WIDTH_3 8
`define ETH_MAC_ADDR1_WIDTH_0 8
`define ETH_MAC_ADDR1_WIDTH_1 8
`define ETH_HASH0_WIDTH_0 8
`define ETH_HASH0_WIDTH_1 8
`define ETH_HASH0_WIDTH_2 8
`define ETH_HASH0_WIDTH_3 8
`define ETH_HASH1_WIDTH_0 8
`define ETH_HASH1_WIDTH_1 8
`define ETH_HASH1_WIDTH_2 8
`define ETH_HASH1_WIDTH_3 8
`define ETH_TX_CTRL_WIDTH_0 8
`define ETH_TX_CTRL_WIDTH_1 8
`define ETH_TX_CTRL_WIDTH_2 1
`define ETH_RX_CTRL_WIDTH_0 8
`define ETH_RX_CTRL_WIDTH_1 8
 
 
// Outputs are registered (uncomment when needed)
`define ETH_REGISTERED_OUTPUTS
 
// Settings for TX FIFO
`define ETH_TX_FIFO_DATA_WIDTH 32
 
// Defines for ethernet TX fifo size - impacts FPGA resource usage
//`define ETH_TX_FULL_PACKET_FIFO // Full 1500 byte TX buffer - uncomment this
//`define ETH_TX_256BYTE_FIFO // 256 byte TX buffer - uncomment this
//`define ETH_TX_512BYTE_FIFO // 512 byte TX buffer - uncomment this
`define ETH_TX_1KBYTE_FIFO // 1024 byte TX buffer - uncomment this
 
`ifdef ETH_TX_FULL_PACKET_FIFO
`define ETH_TX_FIFO_CNT_WIDTH 11
`define ETH_TX_FIFO_DEPTH 375
`else
`ifdef ETH_TX_1KBYTE_FIFO
`define ETH_TX_FIFO_CNT_WIDTH 9
`define ETH_TX_FIFO_DEPTH 256
`else
`ifdef ETH_TX_512BYTE_FIFO
`define ETH_TX_FIFO_CNT_WIDTH 8
`define ETH_TX_FIFO_DEPTH 128
`else
`ifdef ETH_TX_256BYTE_FIFO
`define ETH_TX_FIFO_CNT_WIDTH 7
`define ETH_TX_FIFO_DEPTH 64
`else
// Default is 64 bytes
`define ETH_TX_FIFO_CNT_WIDTH 5
`define ETH_TX_FIFO_DEPTH 16
`endif
`endif
`endif // !`ifdef ETH_TX_512BYTE_FIFO
`endif // !`ifdef ETH_TX_FULL_PACKET_FIFO
 
 
 
// Settings for RX FIFO
`define ETH_RX_FIFO_CNT_WIDTH 9
`define ETH_RX_FIFO_DEPTH 256
//`define ETH_RX_FIFO_CNT_WIDTH 8
//`define ETH_RX_FIFO_DEPTH 128
//`define ETH_RX_FIFO_CNT_WIDTH 7
//`define ETH_RX_FIFO_DEPTH 64
//`define ETH_RX_FIFO_CNT_WIDTH 6
//`define ETH_RX_FIFO_DEPTH 32
//`define ETH_RX_FIFO_CNT_WIDTH 5
//`define ETH_RX_FIFO_DEPTH 16
 
`define ETH_RX_FIFO_DATA_WIDTH 32
 
// Burst length
`define BURST_4BEAT
`ifdef BURST_4BEAT
`define ETH_BURST_LENGTH 4 // Change also ETH_BURST_CNT_WIDTH
`define ETH_BURST_CNT_WIDTH 3 // The counter must be width enough to count to ETH_BURST_LENGTH
`endif
 
//`define ETH_BURST_LENGTH 32 // Change also ETH_BURST_CNT_WIDTH
//`define ETH_BURST_CNT_WIDTH 7 // The counter must be width enough to count to ETH_BURST_LENGTH
 
// Undefine this to enable bursting for RX (writing to memory)
`define ETH_RX_BURST_EN
 
 
// WISHBONE interface is Revision B3 compliant (uncomment when needed)
`define ETH_WISHBONE_B3
 
// Hack where the transmit logic polls each of the TX buffers instead of having to keep track of what's going on
//`define TXBD_POLL
 
// Define this to allow reading of the Wishbone control state machine on reg
// address 0x58
`define WISHBONE_DEBUG
/boards/xilinx/ml501/rtl/verilog/include/i2c_master_slave_defines.v
0,0 → 1,66
/////////////////////////////////////////////////////////////////////
//// ////
//// WISHBONE rev.B2 compliant I2C Master controller defines ////
//// ////
//// ////
//// Author: Richard Herveille ////
//// richard@asics.ws ////
//// www.asics.ws ////
//// ////
//// Downloaded from: http://www.opencores.org/projects/i2c/ ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001 Richard Herveille ////
//// richard@asics.ws ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer.////
//// ////
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
//// 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. ////
//// ////
/////////////////////////////////////////////////////////////////////
 
// CVS Log
//
// $Id: i2c_master_defines.v,v 1.3 2001-11-05 11:59:25 rherveille Exp $
//
// $Date: 2001-11-05 11:59:25 $
// $Revision: 1.3 $
// $Author: rherveille $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: not supported by cvs2svn $
 
 
// I2C registers wishbone addresses
 
// bitcontroller states
`define I2C_CMD_NOP 4'b0000
`define I2C_CMD_START 4'b0001
`define I2C_CMD_STOP 4'b0010
`define I2C_CMD_WRITE 4'b0100
`define I2C_CMD_READ 4'b1000
 
`define I2C_SLAVE_CMD_WRITE 2'b01
`define I2C_SLAVE_CMD_READ 2'b10
`define I2C_SLAVE_CMD_NOP 2'b00
 
 
 
/boards/xilinx/ml501/rtl/verilog/include/dbg_cpu_defines.v
0,0 → 1,85
//////////////////////////////////////////////////////////////////////
//// ////
//// dbg_cpu_defines.v ////
//// ////
//// ////
//// This file is part of the SoC Debug Interface. ////
//// http://www.opencores.org/projects/DebugInterface/ ////
//// ////
//// Author(s): ////
//// Igor Mohor (igorm@opencores.org) ////
//// ////
//// ////
//// All additional information is avaliable in the README.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000 - 2004 Authors ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
 
// Defining length of the command
`define DBG_CPU_CMD_LEN 3'd4
`define DBG_CPU_CMD_CNT_WIDTH 3
 
// Defining length of the access_type field
`define DBG_CPU_ACC_TYPE_LEN 4
 
// Defining length of the address
`define DBG_CPU_ADR_LEN 32
 
// Defining length of the length register
`define DBG_CPU_LEN_LEN 16
 
// Defining total length of the DR needed
`define DBG_CPU_DR_LEN (`DBG_CPU_ACC_TYPE_LEN + `DBG_CPU_ADR_LEN + `DBG_CPU_LEN_LEN)
// Defining length of the CRC
`define DBG_CPU_CRC_LEN 6'd32
`define DBG_CPU_CRC_CNT_WIDTH 6
 
// Defining length of status
`define DBG_CPU_STATUS_LEN 3'd4
`define DBG_CPU_STATUS_CNT_WIDTH 3
 
// Defining length of the data
//define DBG_CPU_DATA_CNT_WIDTH `DBG_CPU_LEN_LEN + 3
`define DBG_CPU_DATA_CNT_WIDTH 19
//define DBG_CPU_DATA_CNT_LIM_WIDTH `DBG_CPU_LEN_LEN
`define DBG_CPU_DATA_CNT_LIM_WIDTH 16
// Defining length of the control register
`define DBG_CPU_CTRL_LEN 2
 
//Defining commands
`define DBG_CPU_GO 4'h0
`define DBG_CPU_RD_COMM 4'h1
`define DBG_CPU_WR_COMM 4'h2
`define DBG_CPU_RD_CTRL 4'h3
`define DBG_CPU_WR_CTRL 4'h4
 
// Defining access types for wishbone
`define DBG_CPU_WRITE 4'h2
`define DBG_CPU_READ 4'h6
 
 
/boards/xilinx/ml501/rtl/verilog/include/or1200_defines.v
0,0 → 1,1732
//////////////////////////////////////////////////////////////////////
//// ////
//// OR1200's definitions ////
//// ////
//// This file is part of the OpenRISC 1200 project ////
//// http://opencores.org/project,or1k ////
//// ////
//// Description ////
//// Defines for the OR1200 core ////
//// ////
//// To Do: ////
//// - add parameters that are missing ////
//// ////
//// Author(s): ////
//// - Damjan Lampret, lampret@opencores.org ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// $Log: or1200_defines.v,v $
// Revision 2.0 2010/06/30 11:00:00 ORSoC
// Minor update:
// Defines added, bugs fixed.
 
//
// Dump VCD
//
//`define OR1200_VCD_DUMP
 
//
// Generate debug messages during simulation
//
//`define OR1200_VERBOSE
 
// `define OR1200_ASIC
////////////////////////////////////////////////////////
//
// Typical configuration for an ASIC
//
`ifdef OR1200_ASIC
 
//
// Target ASIC memories
//
//`define OR1200_ARTISAN_SSP
//`define OR1200_ARTISAN_SDP
//`define OR1200_ARTISAN_STP
`define OR1200_VIRTUALSILICON_SSP
//`define OR1200_VIRTUALSILICON_STP_T1
//`define OR1200_VIRTUALSILICON_STP_T2
 
//
// Do not implement Data cache
//
//`define OR1200_NO_DC
 
//
// Do not implement Insn cache
//
//`define OR1200_NO_IC
 
//
// Do not implement Data MMU
//
//`define OR1200_NO_DMMU
 
//
// Do not implement Insn MMU
//
//`define OR1200_NO_IMMU
 
//
// Select between ASIC optimized and generic multiplier
//
//`define OR1200_ASIC_MULTP2_32X32
`define OR1200_GENERIC_MULTP2_32X32
 
//
// Size/type of insn/data cache if implemented
//
// `define OR1200_IC_1W_512B
// `define OR1200_IC_1W_4KB
`define OR1200_IC_1W_8KB
// `define OR1200_DC_1W_4KB
`define OR1200_DC_1W_8KB
 
`else
 
 
/////////////////////////////////////////////////////////
//
// Typical configuration for an FPGA
//
 
//
// Target FPGA memories
//
//`define OR1200_ALTERA_LPM
//`define OR1200_XILINX_RAMB16
//`define OR1200_XILINX_RAMB4
//`define OR1200_XILINX_RAM32X1D
//`define OR1200_USE_RAM16X1D_FOR_RAM32X1D
// Generic models should infer RAM blocks at synthesis time (not only effects
// single port ram.)
`define OR1200_GENERIC
 
//
// Do not implement Data cache
//
//`define OR1200_NO_DC
 
//
// Do not implement Insn cache
//
//`define OR1200_NO_IC
 
//
// Do not implement Data MMU
//
//`define OR1200_NO_DMMU
 
//
// Do not implement Insn MMU
//
//`define OR1200_NO_IMMU
 
//
// Select between ASIC and generic multiplier
//
// (Generic seems to trigger a bug in the Cadence Ncsim simulator)
//
//`define OR1200_ASIC_MULTP2_32X32
`define OR1200_GENERIC_MULTP2_32X32
 
//
// Size/type of insn/data cache if implemented
// (consider available FPGA memory resources)
//
//`define OR1200_IC_1W_512B
//`define OR1200_IC_1W_4KB
`define OR1200_IC_1W_8KB
//`define OR1200_DC_1W_4KB
`define OR1200_DC_1W_8KB
 
`endif
 
 
//////////////////////////////////////////////////////////
//
// Do not change below unless you know what you are doing
//
 
//
// Reset active low
//
//`define OR1200_RST_ACT_LOW
 
//
// Enable RAM BIST
//
// At the moment this only works for Virtual Silicon
// single port RAMs. For other RAMs it has not effect.
// Special wrapper for VS RAMs needs to be provided
// with scan flops to facilitate bist scan.
//
//`define OR1200_BIST
 
//
// Register OR1200 WISHBONE outputs
// (must be defined/enabled)
//
`define OR1200_REGISTERED_OUTPUTS
 
//
// Register OR1200 WISHBONE inputs
//
// (must be undefined/disabled)
//
//`define OR1200_REGISTERED_INPUTS
 
//
// Disable bursts if they are not supported by the
// memory subsystem (only affect cache line fill)
//
//`define OR1200_NO_BURSTS
//
 
//
// WISHBONE retry counter range
//
// 2^value range for retry counter. Retry counter
// is activated whenever *wb_rty_i is asserted and
// until retry counter expires, corresponding
// WISHBONE interface is deactivated.
//
// To disable retry counters and *wb_rty_i all together,
// undefine this macro.
//
//`define OR1200_WB_RETRY 7
 
//
// WISHBONE Consecutive Address Burst
//
// This was used prior to WISHBONE B3 specification
// to identify bursts. It is no longer needed but
// remains enabled for compatibility with old designs.
//
// To remove *wb_cab_o ports undefine this macro.
//
//`define OR1200_WB_CAB
 
//
// WISHBONE B3 compatible interface
//
// This follows the WISHBONE B3 specification.
// It is not enabled by default because most
// designs still don't use WB b3.
//
// To enable *wb_cti_o/*wb_bte_o ports,
// define this macro.
//
`define OR1200_WB_B3
 
//
// LOG all WISHBONE accesses
//
`define OR1200_LOG_WB_ACCESS
 
//
// Enable additional synthesis directives if using
// _Synopsys_ synthesis tool
//
//`define OR1200_ADDITIONAL_SYNOPSYS_DIRECTIVES
 
//
// Enables default statement in some case blocks
// and disables Synopsys synthesis directive full_case
//
// By default it is enabled. When disabled it
// can increase clock frequency.
//
`define OR1200_CASE_DEFAULT
 
//
// Operand width / register file address width
//
// (DO NOT CHANGE)
//
`define OR1200_OPERAND_WIDTH 32
`define OR1200_REGFILE_ADDR_WIDTH 5
 
//
// l.add/l.addi/l.and and optional l.addc/l.addic
// also set (compare) flag when result of their
// operation equals zero
//
// At the time of writing this, default or32
// C/C++ compiler doesn't generate code that
// would benefit from this optimization.
//
// By default this optimization is disabled to
// save area.
//
//`define OR1200_ADDITIONAL_FLAG_MODIFIERS
 
//
// Implement l.addc/l.addic instructions
//
// By default implementation of l.addc/l.addic
// instructions is enabled in case you need them.
// If you don't use them, then disable implementation
// to save area.
//
//`define OR1200_IMPL_ADDC
 
//
// Implement l.sub instruction
//
// By default implementation of l.sub instructions
// is enabled to be compliant with the simulator.
// If you don't use carry bit, then disable
// implementation to save area.
//
`define OR1200_IMPL_SUB
 
//
// Implement carry bit SR[CY]
//
//
// By default implementation of SR[CY] is enabled
// to be compliant with the simulator. However SR[CY]
// is explicitly only used by l.addc/l.addic/l.sub
// instructions and if these three insns are not
// implemented there is not much point having SR[CY].
//
//`define OR1200_IMPL_CY
 
//
// Implement rotate in the ALU
//
// At the time of writing this, or32
// C/C++ compiler doesn't generate rotate
// instructions. However or32 assembler
// can assemble code that uses rotate insn.
// This means that rotate instructions
// must be used manually inserted.
//
// By default implementation of rotate
// is disabled to save area and increase
// clock frequency.
//
//`define OR1200_IMPL_ALU_ROTATE
 
//
// Type of ALU compare to implement
//
// Try either one to find what yields
// higher clock frequencyin your case.
//
//`define OR1200_IMPL_ALU_COMP1
`define OR1200_IMPL_ALU_COMP2
 
//
// Implement Find First/Last '1'
//
`define OR1200_IMPL_ALU_FFL1
 
//
// Implement multiplier
//
// By default multiplier is implemented
//
`define OR1200_MULT_IMPLEMENTED
 
//
// Implement multiply-and-accumulate
//
// By default MAC is implemented. To
// implement MAC, multiplier needs to be
// implemented.
//
`define OR1200_MAC_IMPLEMENTED
 
//
// Implement optional l.div/l.divu instructions
//
// By default divide instructions are not implemented
// to save area and increase clock frequency. or32 C/C++
// compiler can use soft library for division.
//
// To implement divide, both multiplier and MAC needs to be implemented.
//
`define OR1200_DIV_IMPLEMENTED
 
//
// Low power, slower multiplier
//
// Select between low-power (larger) multiplier
// and faster multiplier. The actual difference
// is only AND logic that prevents distribution
// of operands into the multiplier when instruction
// in execution is not multiply instruction
//
//`define OR1200_LOWPWR_MULT
 
//
// Implement HW Single Precision FPU
//
`define OR1200_FPU_IMPLEMENTED
 
 
//
// Clock ratio RISC clock versus WB clock
//
// If you plan to run WB:RISC clock fixed to 1:1, disable
// both defines
//
// For WB:RISC 1:2 or 1:1, enable OR1200_CLKDIV_2_SUPPORTED
// and use clmode to set ratio
//
// For WB:RISC 1:4, 1:2 or 1:1, enable both defines and use
// clmode to set ratio
//
//`define OR1200_CLKDIV_2_SUPPORTED
//`define OR1200_CLKDIV_4_SUPPORTED
 
//
// Type of register file RAM
//
// Memory macro w/ two ports (see or1200_tpram_32x32.v)
//`define OR1200_RFRAM_TWOPORT
//
// Memory macro dual port (see or1200_dpram.v)
`define OR1200_RFRAM_DUALPORT
 
//
// Generic (flip-flop based) register file (see or1200_rfram_generic.v)
//`define OR1200_RFRAM_GENERIC
// Generic register file supports - 16 registers
`ifdef OR1200_RFRAM_GENERIC
// `define OR1200_RFRAM_16REG
`endif
 
//
// Type of mem2reg aligner to implement.
//
// Once OR1200_IMPL_MEM2REG2 yielded faster
// circuit, however with today tools it will
// most probably give you slower circuit.
//
`define OR1200_IMPL_MEM2REG1
//`define OR1200_IMPL_MEM2REG2
 
//
// Reset value and event
//
`ifdef OR1200_RST_ACT_LOW
`define OR1200_RST_VALUE (1'b0)
`define OR1200_RST_EVENT negedge
`else
`define OR1200_RST_VALUE (1'b1)
`define OR1200_RST_EVENT posedge
`endif
 
//
// ALUOPs
//
`define OR1200_ALUOP_WIDTH 4
`define OR1200_ALUOP_NOP 4'd4
/* Order defined by arith insns that have two source operands both in regs
(see binutils/include/opcode/or32.h) */
`define OR1200_ALUOP_ADD 4'd0
`define OR1200_ALUOP_ADDC 4'd1
`define OR1200_ALUOP_SUB 4'd2
`define OR1200_ALUOP_AND 4'd3
`define OR1200_ALUOP_OR 4'd4
`define OR1200_ALUOP_XOR 4'd5
`define OR1200_ALUOP_MUL 4'd6
`define OR1200_ALUOP_CUST5 4'd7
`define OR1200_ALUOP_SHROT 4'd8
`define OR1200_ALUOP_DIV 4'd9
`define OR1200_ALUOP_DIVU 4'd10
/* Order not specifically defined. */
`define OR1200_ALUOP_IMM 4'd11
`define OR1200_ALUOP_MOVHI 4'd12
`define OR1200_ALUOP_COMP 4'd13
`define OR1200_ALUOP_MTSR 4'd14
`define OR1200_ALUOP_MFSR 4'd15
`define OR1200_ALUOP_CMOV 4'd14
`define OR1200_ALUOP_FFL1 4'd15
 
 
// ALU instructions second opcode field (previously multicycle field in
// machine word)
`define OR1200_ALUOP2_POS 9:8
`define OR1200_ALUOP2_WIDTH 2
 
 
//
// MACOPs
//
`define OR1200_MACOP_WIDTH 3
`define OR1200_MACOP_NOP 3'b000
`define OR1200_MACOP_MAC 3'b001
`define OR1200_MACOP_MSB 3'b010
 
//
// Shift/rotate ops
//
`define OR1200_SHROTOP_WIDTH 2
`define OR1200_SHROTOP_NOP 2'd0
`define OR1200_SHROTOP_SLL 2'd0
`define OR1200_SHROTOP_SRL 2'd1
`define OR1200_SHROTOP_SRA 2'd2
`define OR1200_SHROTOP_ROR 2'd3
 
// Execution cycles per instruction
`define OR1200_MULTICYCLE_WIDTH 3
`define OR1200_ONE_CYCLE 3'd0
`define OR1200_TWO_CYCLES 3'd1
 
// Execution control which will "wait on" a module to finish
`define OR1200_WAIT_ON_WIDTH 2
`define OR1200_WAIT_ON_FPU `OR1200_WAIT_ON_WIDTH'd1
`define OR1200_WAIT_ON_MTSPR `OR1200_WAIT_ON_WIDTH'd2
 
// Operand MUX selects
`define OR1200_SEL_WIDTH 2
`define OR1200_SEL_RF 2'd0
`define OR1200_SEL_IMM 2'd1
`define OR1200_SEL_EX_FORW 2'd2
`define OR1200_SEL_WB_FORW 2'd3
 
//
// BRANCHOPs
//
`define OR1200_BRANCHOP_WIDTH 3
`define OR1200_BRANCHOP_NOP 3'd0
`define OR1200_BRANCHOP_J 3'd1
`define OR1200_BRANCHOP_JR 3'd2
`define OR1200_BRANCHOP_BAL 3'd3
`define OR1200_BRANCHOP_BF 3'd4
`define OR1200_BRANCHOP_BNF 3'd5
`define OR1200_BRANCHOP_RFE 3'd6
 
//
// LSUOPs
//
// Bit 0: sign extend
// Bits 1-2: 00 doubleword, 01 byte, 10 halfword, 11 singleword
// Bit 3: 0 load, 1 store
`define OR1200_LSUOP_WIDTH 4
`define OR1200_LSUOP_NOP 4'b0000
`define OR1200_LSUOP_LBZ 4'b0010
`define OR1200_LSUOP_LBS 4'b0011
`define OR1200_LSUOP_LHZ 4'b0100
`define OR1200_LSUOP_LHS 4'b0101
`define OR1200_LSUOP_LWZ 4'b0110
`define OR1200_LSUOP_LWS 4'b0111
`define OR1200_LSUOP_LD 4'b0001
`define OR1200_LSUOP_SD 4'b1000
`define OR1200_LSUOP_SB 4'b1010
`define OR1200_LSUOP_SH 4'b1100
`define OR1200_LSUOP_SW 4'b1110
 
// Number of bits of load/store EA precalculated in ID stage
// for balancing ID and EX stages.
//
// Valid range: 2,3,...,30,31
`define OR1200_LSUEA_PRECALC 2
 
// FETCHOPs
`define OR1200_FETCHOP_WIDTH 1
`define OR1200_FETCHOP_NOP 1'b0
`define OR1200_FETCHOP_LW 1'b1
 
//
// Register File Write-Back OPs
//
// Bit 0: register file write enable
// Bits 3-1: write-back mux selects
//
`define OR1200_RFWBOP_WIDTH 4
`define OR1200_RFWBOP_NOP 4'b0000
`define OR1200_RFWBOP_ALU 3'b000
`define OR1200_RFWBOP_LSU 3'b001
`define OR1200_RFWBOP_SPRS 3'b010
`define OR1200_RFWBOP_LR 3'b011
`define OR1200_RFWBOP_FPU 3'b100
 
// Compare instructions
`define OR1200_COP_SFEQ 3'b000
`define OR1200_COP_SFNE 3'b001
`define OR1200_COP_SFGT 3'b010
`define OR1200_COP_SFGE 3'b011
`define OR1200_COP_SFLT 3'b100
`define OR1200_COP_SFLE 3'b101
`define OR1200_COP_X 3'b111
`define OR1200_SIGNED_COMPARE 'd3
`define OR1200_COMPOP_WIDTH 4
 
//
// FP OPs
//
// MSbit indicates FPU operation valid
//
`define OR1200_FPUOP_WIDTH 8
// FPU unit from Usselman takes 5 cycles from decode, so 4 ex. cycles
`define OR1200_FPUOP_CYCLES 3'd4
// FP instruction is double precision if bit 4 is set. We're a 32-bit
// implementation thus do not support double precision FP
`define OR1200_FPUOP_DOUBLE_BIT 4
`define OR1200_FPUOP_ADD 8'b0000_0000
`define OR1200_FPUOP_SUB 8'b0000_0001
`define OR1200_FPUOP_MUL 8'b0000_0010
`define OR1200_FPUOP_DIV 8'b0000_0011
`define OR1200_FPUOP_ITOF 8'b0000_0100
`define OR1200_FPUOP_FTOI 8'b0000_0101
`define OR1200_FPUOP_REM 8'b0000_0110
`define OR1200_FPUOP_RESERVED 8'b0000_0111
// FP Compare instructions
`define OR1200_FPCOP_SFEQ 8'b0000_1000
`define OR1200_FPCOP_SFNE 8'b0000_1001
`define OR1200_FPCOP_SFGT 8'b0000_1010
`define OR1200_FPCOP_SFGE 8'b0000_1011
`define OR1200_FPCOP_SFLT 8'b0000_1100
`define OR1200_FPCOP_SFLE 8'b0000_1101
 
//
// TAGs for instruction bus
//
`define OR1200_ITAG_IDLE 4'h0 // idle bus
`define OR1200_ITAG_NI 4'h1 // normal insn
`define OR1200_ITAG_BE 4'hb // Bus error exception
`define OR1200_ITAG_PE 4'hc // Page fault exception
`define OR1200_ITAG_TE 4'hd // TLB miss exception
 
//
// TAGs for data bus
//
`define OR1200_DTAG_IDLE 4'h0 // idle bus
`define OR1200_DTAG_ND 4'h1 // normal data
`define OR1200_DTAG_AE 4'ha // Alignment exception
`define OR1200_DTAG_BE 4'hb // Bus error exception
`define OR1200_DTAG_PE 4'hc // Page fault exception
`define OR1200_DTAG_TE 4'hd // TLB miss exception
 
 
//////////////////////////////////////////////
//
// ORBIS32 ISA specifics
//
 
// SHROT_OP position in machine word
`define OR1200_SHROTOP_POS 7:6
 
//
// Instruction opcode groups (basic)
//
`define OR1200_OR32_J 6'b000000
`define OR1200_OR32_JAL 6'b000001
`define OR1200_OR32_BNF 6'b000011
`define OR1200_OR32_BF 6'b000100
`define OR1200_OR32_NOP 6'b000101
`define OR1200_OR32_MOVHI 6'b000110
`define OR1200_OR32_XSYNC 6'b001000
`define OR1200_OR32_RFE 6'b001001
/* */
`define OR1200_OR32_JR 6'b010001
`define OR1200_OR32_JALR 6'b010010
`define OR1200_OR32_MACI 6'b010011
/* */
`define OR1200_OR32_LWZ 6'b100001
`define OR1200_OR32_LBZ 6'b100011
`define OR1200_OR32_LBS 6'b100100
`define OR1200_OR32_LHZ 6'b100101
`define OR1200_OR32_LHS 6'b100110
`define OR1200_OR32_ADDI 6'b100111
`define OR1200_OR32_ADDIC 6'b101000
`define OR1200_OR32_ANDI 6'b101001
`define OR1200_OR32_ORI 6'b101010
`define OR1200_OR32_XORI 6'b101011
`define OR1200_OR32_MULI 6'b101100
`define OR1200_OR32_MFSPR 6'b101101
`define OR1200_OR32_SH_ROTI 6'b101110
`define OR1200_OR32_SFXXI 6'b101111
/* */
`define OR1200_OR32_MTSPR 6'b110000
`define OR1200_OR32_MACMSB 6'b110001
`define OR1200_OR32_FLOAT 6'b110010
/* */
`define OR1200_OR32_SW 6'b110101
`define OR1200_OR32_SB 6'b110110
`define OR1200_OR32_SH 6'b110111
`define OR1200_OR32_ALU 6'b111000
`define OR1200_OR32_SFXX 6'b111001
//`define OR1200_OR32_CUST5 6'b111100
 
 
/////////////////////////////////////////////////////
//
// Exceptions
//
 
//
// Exception vectors per OR1K architecture:
// 0xPPPPP100 - reset
// 0xPPPPP200 - bus error
// ... etc
// where P represents exception prefix.
//
// Exception vectors can be customized as per
// the following formula:
// 0xPPPPPNVV - exception N
//
// P represents exception prefix
// N represents exception N
// VV represents length of the individual vector space,
// usually it is 8 bits wide and starts with all bits zero
//
 
//
// PPPPP and VV parts
//
// Sum of these two defines needs to be 28
//
`define OR1200_EXCEPT_EPH0_P 20'h00000
`define OR1200_EXCEPT_EPH1_P 20'hF0000
`define OR1200_EXCEPT_V 8'h00
 
//
// N part width
//
`define OR1200_EXCEPT_WIDTH 4
 
//
// Definition of exception vectors
//
// To avoid implementation of a certain exception,
// simply comment out corresponding line
//
`define OR1200_EXCEPT_UNUSED `OR1200_EXCEPT_WIDTH'hf
`define OR1200_EXCEPT_TRAP `OR1200_EXCEPT_WIDTH'he
`define OR1200_EXCEPT_FLOAT `OR1200_EXCEPT_WIDTH'hd
`define OR1200_EXCEPT_SYSCALL `OR1200_EXCEPT_WIDTH'hc
`define OR1200_EXCEPT_RANGE `OR1200_EXCEPT_WIDTH'hb
`define OR1200_EXCEPT_ITLBMISS `OR1200_EXCEPT_WIDTH'ha
`define OR1200_EXCEPT_DTLBMISS `OR1200_EXCEPT_WIDTH'h9
`define OR1200_EXCEPT_INT `OR1200_EXCEPT_WIDTH'h8
`define OR1200_EXCEPT_ILLEGAL `OR1200_EXCEPT_WIDTH'h7
`define OR1200_EXCEPT_ALIGN `OR1200_EXCEPT_WIDTH'h6
`define OR1200_EXCEPT_TICK `OR1200_EXCEPT_WIDTH'h5
`define OR1200_EXCEPT_IPF `OR1200_EXCEPT_WIDTH'h4
`define OR1200_EXCEPT_DPF `OR1200_EXCEPT_WIDTH'h3
`define OR1200_EXCEPT_BUSERR `OR1200_EXCEPT_WIDTH'h2
`define OR1200_EXCEPT_RESET `OR1200_EXCEPT_WIDTH'h1
`define OR1200_EXCEPT_NONE `OR1200_EXCEPT_WIDTH'h0
 
 
/////////////////////////////////////////////////////
//
// SPR groups
//
 
// Bits that define the group
`define OR1200_SPR_GROUP_BITS 15:11
 
// Width of the group bits
`define OR1200_SPR_GROUP_WIDTH 5
 
// Bits that define offset inside the group
`define OR1200_SPR_OFS_BITS 10:0
 
// List of groups
`define OR1200_SPR_GROUP_SYS 5'd00
`define OR1200_SPR_GROUP_DMMU 5'd01
`define OR1200_SPR_GROUP_IMMU 5'd02
`define OR1200_SPR_GROUP_DC 5'd03
`define OR1200_SPR_GROUP_IC 5'd04
`define OR1200_SPR_GROUP_MAC 5'd05
`define OR1200_SPR_GROUP_DU 5'd06
`define OR1200_SPR_GROUP_PM 5'd08
`define OR1200_SPR_GROUP_PIC 5'd09
`define OR1200_SPR_GROUP_TT 5'd10
`define OR1200_SPR_GROUP_FPU 5'd11
 
/////////////////////////////////////////////////////
//
// System group
//
 
//
// System registers
//
`define OR1200_SPR_CFGR 7'd0
`define OR1200_SPR_RF 6'd32 // 1024 >> 5
`define OR1200_SPR_NPC 11'd16
`define OR1200_SPR_SR 11'd17
`define OR1200_SPR_PPC 11'd18
`define OR1200_SPR_FPCSR 11'd20
`define OR1200_SPR_EPCR 11'd32
`define OR1200_SPR_EEAR 11'd48
`define OR1200_SPR_ESR 11'd64
 
//
// SR bits
//
`define OR1200_SR_WIDTH 17
`define OR1200_SR_SM 0
`define OR1200_SR_TEE 1
`define OR1200_SR_IEE 2
`define OR1200_SR_DCE 3
`define OR1200_SR_ICE 4
`define OR1200_SR_DME 5
`define OR1200_SR_IME 6
`define OR1200_SR_LEE 7
`define OR1200_SR_CE 8
`define OR1200_SR_F 9
`define OR1200_SR_CY 10 // Unused
`define OR1200_SR_OV 11 // Unused
`define OR1200_SR_OVE 12 // Unused
`define OR1200_SR_DSX 13 // Unused
`define OR1200_SR_EPH 14
`define OR1200_SR_FO 15
`define OR1200_SR_TED 16
`define OR1200_SR_CID 31:28 // Unimplemented
 
//
// Bits that define offset inside the group
//
`define OR1200_SPROFS_BITS 10:0
 
//
// Default Exception Prefix
//
// 1'b0 - OR1200_EXCEPT_EPH0_P (0x0000_0000)
// 1'b1 - OR1200_EXCEPT_EPH1_P (0xF000_0000)
//
`define OR1200_SR_EPH_DEF 1'b0
 
 
//
// FPCSR bits
//
`define OR1200_FPCSR_WIDTH 12
`define OR1200_FPCSR_FPEE 0
`define OR1200_FPCSR_RM 2:1
`define OR1200_FPCSR_OVF 3
`define OR1200_FPCSR_UNF 4
`define OR1200_FPCSR_SNF 5
`define OR1200_FPCSR_QNF 6
`define OR1200_FPCSR_ZF 7
`define OR1200_FPCSR_IXF 8
`define OR1200_FPCSR_IVF 9
`define OR1200_FPCSR_INF 10
`define OR1200_FPCSR_DZF 11
`define OR1200_FPCSR_RES 31:12
 
/////////////////////////////////////////////////////
//
// Power Management (PM)
//
 
// Define it if you want PM implemented
//`define OR1200_PM_IMPLEMENTED
 
// Bit positions inside PMR (don't change)
`define OR1200_PM_PMR_SDF 3:0
`define OR1200_PM_PMR_DME 4
`define OR1200_PM_PMR_SME 5
`define OR1200_PM_PMR_DCGE 6
`define OR1200_PM_PMR_UNUSED 31:7
 
// PMR offset inside PM group of registers
`define OR1200_PM_OFS_PMR 11'b0
 
// PM group
`define OR1200_SPRGRP_PM 5'd8
 
// Define if PMR can be read/written at any address inside PM group
`define OR1200_PM_PARTIAL_DECODING
 
// Define if reading PMR is allowed
`define OR1200_PM_READREGS
 
// Define if unused PMR bits should be zero
`define OR1200_PM_UNUSED_ZERO
 
 
/////////////////////////////////////////////////////
//
// Debug Unit (DU)
//
 
// Define it if you want DU implemented
`define OR1200_DU_IMPLEMENTED
 
//
// Define if you want HW Breakpoints
// (if HW breakpoints are not implemented
// only default software trapping is
// possible with l.trap insn - this is
// however already enough for use
// with or32 gdb)
//
//`define OR1200_DU_HWBKPTS
 
// Number of DVR/DCR pairs if HW breakpoints enabled
// Comment / uncomment DU_DVRn / DU_DCRn pairs bellow according to this number !
// DU_DVR0..DU_DVR7 should be uncommented for 8 DU_DVRDCR_PAIRS
`define OR1200_DU_DVRDCR_PAIRS 8
 
// Define if you want trace buffer
// (for now only available for Xilinx Virtex FPGAs)
//`define OR1200_DU_TB_IMPLEMENTED
 
 
//
// Address offsets of DU registers inside DU group
//
// To not implement a register, doq not define its address
//
`ifdef OR1200_DU_HWBKPTS
`define OR1200_DU_DVR0 11'd0
`define OR1200_DU_DVR1 11'd1
`define OR1200_DU_DVR2 11'd2
`define OR1200_DU_DVR3 11'd3
`define OR1200_DU_DVR4 11'd4
`define OR1200_DU_DVR5 11'd5
`define OR1200_DU_DVR6 11'd6
`define OR1200_DU_DVR7 11'd7
`define OR1200_DU_DCR0 11'd8
`define OR1200_DU_DCR1 11'd9
`define OR1200_DU_DCR2 11'd10
`define OR1200_DU_DCR3 11'd11
`define OR1200_DU_DCR4 11'd12
`define OR1200_DU_DCR5 11'd13
`define OR1200_DU_DCR6 11'd14
`define OR1200_DU_DCR7 11'd15
`endif
`define OR1200_DU_DMR1 11'd16
`ifdef OR1200_DU_HWBKPTS
`define OR1200_DU_DMR2 11'd17
`define OR1200_DU_DWCR0 11'd18
`define OR1200_DU_DWCR1 11'd19
`endif
`define OR1200_DU_DSR 11'd20
`define OR1200_DU_DRR 11'd21
`ifdef OR1200_DU_TB_IMPLEMENTED
`define OR1200_DU_TBADR 11'h0ff
`define OR1200_DU_TBIA 11'h1??
`define OR1200_DU_TBIM 11'h2??
`define OR1200_DU_TBAR 11'h3??
`define OR1200_DU_TBTS 11'h4??
`endif
 
// Position of offset bits inside SPR address
`define OR1200_DUOFS_BITS 10:0
 
// DCR bits
`define OR1200_DU_DCR_DP 0
`define OR1200_DU_DCR_CC 3:1
`define OR1200_DU_DCR_SC 4
`define OR1200_DU_DCR_CT 7:5
 
// DMR1 bits
`define OR1200_DU_DMR1_CW0 1:0
`define OR1200_DU_DMR1_CW1 3:2
`define OR1200_DU_DMR1_CW2 5:4
`define OR1200_DU_DMR1_CW3 7:6
`define OR1200_DU_DMR1_CW4 9:8
`define OR1200_DU_DMR1_CW5 11:10
`define OR1200_DU_DMR1_CW6 13:12
`define OR1200_DU_DMR1_CW7 15:14
`define OR1200_DU_DMR1_CW8 17:16
`define OR1200_DU_DMR1_CW9 19:18
`define OR1200_DU_DMR1_CW10 21:20
`define OR1200_DU_DMR1_ST 22
`define OR1200_DU_DMR1_BT 23
`define OR1200_DU_DMR1_DXFW 24
`define OR1200_DU_DMR1_ETE 25
 
// DMR2 bits
`define OR1200_DU_DMR2_WCE0 0
`define OR1200_DU_DMR2_WCE1 1
`define OR1200_DU_DMR2_AWTC 12:2
`define OR1200_DU_DMR2_WGB 23:13
 
// DWCR bits
`define OR1200_DU_DWCR_COUNT 15:0
`define OR1200_DU_DWCR_MATCH 31:16
 
// DSR bits
`define OR1200_DU_DSR_WIDTH 14
`define OR1200_DU_DSR_RSTE 0
`define OR1200_DU_DSR_BUSEE 1
`define OR1200_DU_DSR_DPFE 2
`define OR1200_DU_DSR_IPFE 3
`define OR1200_DU_DSR_TTE 4
`define OR1200_DU_DSR_AE 5
`define OR1200_DU_DSR_IIE 6
`define OR1200_DU_DSR_IE 7
`define OR1200_DU_DSR_DME 8
`define OR1200_DU_DSR_IME 9
`define OR1200_DU_DSR_RE 10
`define OR1200_DU_DSR_SCE 11
`define OR1200_DU_DSR_FPE 12
`define OR1200_DU_DSR_TE 13
 
// DRR bits
`define OR1200_DU_DRR_RSTE 0
`define OR1200_DU_DRR_BUSEE 1
`define OR1200_DU_DRR_DPFE 2
`define OR1200_DU_DRR_IPFE 3
`define OR1200_DU_DRR_TTE 4
`define OR1200_DU_DRR_AE 5
`define OR1200_DU_DRR_IIE 6
`define OR1200_DU_DRR_IE 7
`define OR1200_DU_DRR_DME 8
`define OR1200_DU_DRR_IME 9
`define OR1200_DU_DRR_RE 10
`define OR1200_DU_DRR_SCE 11
`define OR1200_DU_DRR_FPE 12
`define OR1200_DU_DRR_TE 13
 
// Define if reading DU regs is allowed
`define OR1200_DU_READREGS
 
// Define if unused DU registers bits should be zero
`define OR1200_DU_UNUSED_ZERO
 
// Define if IF/LSU status is not needed by devel i/f
`define OR1200_DU_STATUS_UNIMPLEMENTED
 
/////////////////////////////////////////////////////
//
// Programmable Interrupt Controller (PIC)
//
 
// Define it if you want PIC implemented
`define OR1200_PIC_IMPLEMENTED
 
// Define number of interrupt inputs (2-31)
`define OR1200_PIC_INTS 31
 
// Address offsets of PIC registers inside PIC group
`define OR1200_PIC_OFS_PICMR 2'd0
`define OR1200_PIC_OFS_PICSR 2'd2
 
// Position of offset bits inside SPR address
`define OR1200_PICOFS_BITS 1:0
 
// Define if you want these PIC registers to be implemented
`define OR1200_PIC_PICMR
`define OR1200_PIC_PICSR
 
// Define if reading PIC registers is allowed
`define OR1200_PIC_READREGS
 
// Define if unused PIC register bits should be zero
`define OR1200_PIC_UNUSED_ZERO
 
 
/////////////////////////////////////////////////////
//
// Tick Timer (TT)
//
 
// Define it if you want TT implemented
`define OR1200_TT_IMPLEMENTED
 
// Address offsets of TT registers inside TT group
`define OR1200_TT_OFS_TTMR 1'd0
`define OR1200_TT_OFS_TTCR 1'd1
 
// Position of offset bits inside SPR group
`define OR1200_TTOFS_BITS 0
 
// Define if you want these TT registers to be implemented
`define OR1200_TT_TTMR
`define OR1200_TT_TTCR
 
// TTMR bits
`define OR1200_TT_TTMR_TP 27:0
`define OR1200_TT_TTMR_IP 28
`define OR1200_TT_TTMR_IE 29
`define OR1200_TT_TTMR_M 31:30
 
// Define if reading TT registers is allowed
`define OR1200_TT_READREGS
 
 
//////////////////////////////////////////////
//
// MAC
//
`define OR1200_MAC_ADDR 0 // MACLO 0xxxxxxxx1, MACHI 0xxxxxxxx0
`define OR1200_MAC_SPR_WE // Define if MACLO/MACHI are SPR writable
 
//
// Shift {MACHI,MACLO} into destination register when executing l.macrc
//
// According to architecture manual there is no shift, so default value is 0.
// However the implementation has deviated in this from the arch manual and had
// hard coded shift by 28 bits which is a useful optimization for MP3 decoding
// (if using libmad fixed point library). Shifts are no longer default setup,
// but if you need to remain backward compatible, define your shift bits, which
// were normally
// dest_GPR = {MACHI,MACLO}[59:28]
`define OR1200_MAC_SHIFTBY 0 // 0 = According to arch manual, 28 = obsolete backward compatibility
 
 
//////////////////////////////////////////////
//
// Data MMU (DMMU)
//
 
//
// Address that selects between TLB TR and MR
//
`define OR1200_DTLB_TM_ADDR 7
 
//
// DTLBMR fields
//
`define OR1200_DTLBMR_V_BITS 0
`define OR1200_DTLBMR_CID_BITS 4:1
`define OR1200_DTLBMR_RES_BITS 11:5
`define OR1200_DTLBMR_VPN_BITS 31:13
 
//
// DTLBTR fields
//
`define OR1200_DTLBTR_CC_BITS 0
`define OR1200_DTLBTR_CI_BITS 1
`define OR1200_DTLBTR_WBC_BITS 2
`define OR1200_DTLBTR_WOM_BITS 3
`define OR1200_DTLBTR_A_BITS 4
`define OR1200_DTLBTR_D_BITS 5
`define OR1200_DTLBTR_URE_BITS 6
`define OR1200_DTLBTR_UWE_BITS 7
`define OR1200_DTLBTR_SRE_BITS 8
`define OR1200_DTLBTR_SWE_BITS 9
`define OR1200_DTLBTR_RES_BITS 11:10
`define OR1200_DTLBTR_PPN_BITS 31:13
 
//
// DTLB configuration
//
`define OR1200_DMMU_PS 13 // 13 for 8KB page size
`define OR1200_DTLB_INDXW 6 // 6 for 64 entry DTLB 7 for 128 entries
`define OR1200_DTLB_INDXL `OR1200_DMMU_PS // 13 13
`define OR1200_DTLB_INDXH `OR1200_DMMU_PS+`OR1200_DTLB_INDXW-1 // 18 19
`define OR1200_DTLB_INDX `OR1200_DTLB_INDXH:`OR1200_DTLB_INDXL // 18:13 19:13
`define OR1200_DTLB_TAGW 32-`OR1200_DTLB_INDXW-`OR1200_DMMU_PS // 13 12
`define OR1200_DTLB_TAGL `OR1200_DTLB_INDXH+1 // 19 20
`define OR1200_DTLB_TAG 31:`OR1200_DTLB_TAGL // 31:19 31:20
`define OR1200_DTLBMRW `OR1200_DTLB_TAGW+1 // +1 because of V bit
`define OR1200_DTLBTRW 32-`OR1200_DMMU_PS+5 // +5 because of protection bits and CI
 
//
// Cache inhibit while DMMU is not enabled/implemented
//
// cache inhibited 0GB-4GB 1'b1
// cache inhibited 0GB-2GB !dcpu_adr_i[31]
// cache inhibited 0GB-1GB 2GB-3GB !dcpu_adr_i[30]
// cache inhibited 1GB-2GB 3GB-4GB dcpu_adr_i[30]
// cache inhibited 2GB-4GB (default) dcpu_adr_i[31]
// cached 0GB-4GB 1'b0
//
`define OR1200_DMMU_CI dcpu_adr_i[31]
 
 
//////////////////////////////////////////////
//
// Insn MMU (IMMU)
//
 
//
// Address that selects between TLB TR and MR
//
`define OR1200_ITLB_TM_ADDR 7
 
//
// ITLBMR fields
//
`define OR1200_ITLBMR_V_BITS 0
`define OR1200_ITLBMR_CID_BITS 4:1
`define OR1200_ITLBMR_RES_BITS 11:5
`define OR1200_ITLBMR_VPN_BITS 31:13
 
//
// ITLBTR fields
//
`define OR1200_ITLBTR_CC_BITS 0
`define OR1200_ITLBTR_CI_BITS 1
`define OR1200_ITLBTR_WBC_BITS 2
`define OR1200_ITLBTR_WOM_BITS 3
`define OR1200_ITLBTR_A_BITS 4
`define OR1200_ITLBTR_D_BITS 5
`define OR1200_ITLBTR_SXE_BITS 6
`define OR1200_ITLBTR_UXE_BITS 7
`define OR1200_ITLBTR_RES_BITS 11:8
`define OR1200_ITLBTR_PPN_BITS 31:13
 
//
// ITLB configuration
//
`define OR1200_IMMU_PS 13 // 13 for 8KB page size
`define OR1200_ITLB_INDXW 6 // 6 for 64 entry ITLB 7 for 128 entries
`define OR1200_ITLB_INDXL `OR1200_IMMU_PS // 13 13
`define OR1200_ITLB_INDXH `OR1200_IMMU_PS+`OR1200_ITLB_INDXW-1 // 18 19
`define OR1200_ITLB_INDX `OR1200_ITLB_INDXH:`OR1200_ITLB_INDXL // 18:13 19:13
`define OR1200_ITLB_TAGW 32-`OR1200_ITLB_INDXW-`OR1200_IMMU_PS // 13 12
`define OR1200_ITLB_TAGL `OR1200_ITLB_INDXH+1 // 19 20
`define OR1200_ITLB_TAG 31:`OR1200_ITLB_TAGL // 31:19 31:20
`define OR1200_ITLBMRW `OR1200_ITLB_TAGW+1 // +1 because of V bit
`define OR1200_ITLBTRW 32-`OR1200_IMMU_PS+3 // +3 because of protection bits and CI
 
//
// Cache inhibit while IMMU is not enabled/implemented
// Note: all combinations that use icpu_adr_i cause async loop
//
// cache inhibited 0GB-4GB 1'b1
// cache inhibited 0GB-2GB !icpu_adr_i[31]
// cache inhibited 0GB-1GB 2GB-3GB !icpu_adr_i[30]
// cache inhibited 1GB-2GB 3GB-4GB icpu_adr_i[30]
// cache inhibited 2GB-4GB (default) icpu_adr_i[31]
// cached 0GB-4GB 1'b0
//
`define OR1200_IMMU_CI 1'b0
 
 
/////////////////////////////////////////////////
//
// Insn cache (IC)
//
 
// 3 for 8 bytes, 4 for 16 bytes etc
`define OR1200_ICLS 4
 
//
// IC configurations
//
`ifdef OR1200_IC_1W_512B
`define OR1200_ICSIZE 9 // 512
`define OR1200_ICINDX `OR1200_ICSIZE-2 // 7
`define OR1200_ICINDXH `OR1200_ICSIZE-1 // 8
`define OR1200_ICTAGL `OR1200_ICINDXH+1 // 9
`define OR1200_ICTAG `OR1200_ICSIZE-`OR1200_ICLS // 5
`define OR1200_ICTAG_W 24
`endif
`ifdef OR1200_IC_1W_4KB
`define OR1200_ICSIZE 12 // 4096
`define OR1200_ICINDX `OR1200_ICSIZE-2 // 10
`define OR1200_ICINDXH `OR1200_ICSIZE-1 // 11
`define OR1200_ICTAGL `OR1200_ICINDXH+1 // 12
`define OR1200_ICTAG `OR1200_ICSIZE-`OR1200_ICLS // 8
`define OR1200_ICTAG_W 21
`endif
`ifdef OR1200_IC_1W_8KB
`define OR1200_ICSIZE 13 // 8192
`define OR1200_ICINDX `OR1200_ICSIZE-2 // 11
`define OR1200_ICINDXH `OR1200_ICSIZE-1 // 12
`define OR1200_ICTAGL `OR1200_ICINDXH+1 // 13
`define OR1200_ICTAG `OR1200_ICSIZE-`OR1200_ICLS // 9
`define OR1200_ICTAG_W 20
`endif
 
 
/////////////////////////////////////////////////
//
// Data cache (DC)
//
 
// 3 for 8 bytes, 4 for 16 bytes etc
`define OR1200_DCLS 4
 
// Define to enable default behavior of cache as write through
// Turning this off enabled write back statergy
//
`define OR1200_DC_WRITETHROUGH
 
// Define to enable stores from the stack not doing writethrough.
// EXPERIMENTAL
//`define OR1200_DC_NOSTACKWRITETHROUGH
 
// Data cache SPR definitions
`define OR1200_SPRGRP_DC_ADR_WIDTH 3
// Data cache group SPR addresses
`define OR1200_SPRGRP_DC_DCCR 3'd0 // Not implemented
`define OR1200_SPRGRP_DC_DCBPR 3'd1 // Not implemented
`define OR1200_SPRGRP_DC_DCBFR 3'd2
`define OR1200_SPRGRP_DC_DCBIR 3'd3
`define OR1200_SPRGRP_DC_DCBWR 3'd4 // Not implemented
`define OR1200_SPRGRP_DC_DCBLR 3'd5 // Not implemented
 
//
// DC configurations
//
`ifdef OR1200_DC_1W_4KB
`define OR1200_DCSIZE 12 // 4096
`define OR1200_DCINDX `OR1200_DCSIZE-2 // 10
`define OR1200_DCINDXH `OR1200_DCSIZE-1 // 11
`define OR1200_DCTAGL `OR1200_DCINDXH+1 // 12
`define OR1200_DCTAG `OR1200_DCSIZE-`OR1200_DCLS // 8
`define OR1200_DCTAG_W 21
`endif
`ifdef OR1200_DC_1W_8KB
`define OR1200_DCSIZE 13 // 8192
`define OR1200_DCINDX `OR1200_DCSIZE-2 // 11
`define OR1200_DCINDXH `OR1200_DCSIZE-1 // 12
`define OR1200_DCTAGL `OR1200_DCINDXH+1 // 13
`define OR1200_DCTAG `OR1200_DCSIZE-`OR1200_DCLS // 9
`define OR1200_DCTAG_W 20
`endif
 
 
/////////////////////////////////////////////////
//
// Store buffer (SB)
//
 
//
// Store buffer
//
// It will improve performance by "caching" CPU stores
// using store buffer. This is most important for function
// prologues because DC can only work in write though mode
// and all stores would have to complete external WB writes
// to memory.
// Store buffer is between DC and data BIU.
// All stores will be stored into store buffer and immediately
// completed by the CPU, even though actual external writes
// will be performed later. As a consequence store buffer masks
// all data bus errors related to stores (data bus errors
// related to loads are delivered normally).
// All pending CPU loads will wait until store buffer is empty to
// ensure strict memory model. Right now this is necessary because
// we don't make destinction between cached and cache inhibited
// address space, so we simply empty store buffer until loads
// can begin.
//
// It makes design a bit bigger, depending what is the number of
// entries in SB FIFO. Number of entries can be changed further
// down.
//
//`define OR1200_SB_IMPLEMENTED
 
//
// Number of store buffer entries
//
// Verified number of entries are 4 and 8 entries
// (2 and 3 for OR1200_SB_LOG). OR1200_SB_ENTRIES must
// always match 2**OR1200_SB_LOG.
// To disable store buffer, undefine
// OR1200_SB_IMPLEMENTED.
//
`define OR1200_SB_LOG 2 // 2 or 3
`define OR1200_SB_ENTRIES 4 // 4 or 8
 
 
/////////////////////////////////////////////////
//
// Quick Embedded Memory (QMEM)
//
 
//
// Quick Embedded Memory
//
// Instantiation of dedicated insn/data memory (RAM or ROM).
// Insn fetch has effective throughput 1insn / clock cycle.
// Data load takes two clock cycles / access, data store
// takes 1 clock cycle / access (if there is no insn fetch)).
// Memory instantiation is shared between insn and data,
// meaning if insn fetch are performed, data load/store
// performance will be lower.
//
// Main reason for QMEM is to put some time critical functions
// into this memory and to have predictable and fast access
// to these functions. (soft fpu, context switch, exception
// handlers, stack, etc)
//
// It makes design a bit bigger and slower. QMEM sits behind
// IMMU/DMMU so all addresses are physical (so the MMUs can be
// used with QMEM and QMEM is seen by the CPU just like any other
// memory in the system). IC/DC are sitting behind QMEM so the
// whole design timing might be worse with QMEM implemented.
//
//`define OR1200_QMEM_IMPLEMENTED
 
//
// Base address and mask of QMEM
//
// Base address defines first address of QMEM. Mask defines
// QMEM range in address space. Actual size of QMEM is however
// determined with instantiated RAM/ROM. However bigger
// mask will reserve more address space for QMEM, but also
// make design faster, while more tight mask will take
// less address space but also make design slower. If
// instantiated RAM/ROM is smaller than space reserved with
// the mask, instatiated RAM/ROM will also be shadowed
// at higher addresses in reserved space.
//
`define OR1200_QMEM_IADDR 32'h0080_0000
`define OR1200_QMEM_IMASK 32'hfff0_0000 // Max QMEM size 1MB
`define OR1200_QMEM_DADDR 32'h0080_0000
`define OR1200_QMEM_DMASK 32'hfff0_0000 // Max QMEM size 1MB
 
//
// QMEM interface byte-select capability
//
// To enable qmem_sel* ports, define this macro.
//
//`define OR1200_QMEM_BSEL
 
//
// QMEM interface acknowledge
//
// To enable qmem_ack port, define this macro.
//
//`define OR1200_QMEM_ACK
 
/////////////////////////////////////////////////////
//
// VR, UPR and Configuration Registers
//
//
// VR, UPR and configuration registers are optional. If
// implemented, operating system can automatically figure
// out how to use the processor because it knows
// what units are available in the processor and how they
// are configured.
//
// This section must be last in or1200_defines.v file so
// that all units are already configured and thus
// configuration registers are properly set.
//
 
// Define if you want configuration registers implemented
`define OR1200_CFGR_IMPLEMENTED
 
// Define if you want full address decode inside SYS group
`define OR1200_SYS_FULL_DECODE
 
// Offsets of VR, UPR and CFGR registers
`define OR1200_SPRGRP_SYS_VR 4'h0
`define OR1200_SPRGRP_SYS_UPR 4'h1
`define OR1200_SPRGRP_SYS_CPUCFGR 4'h2
`define OR1200_SPRGRP_SYS_DMMUCFGR 4'h3
`define OR1200_SPRGRP_SYS_IMMUCFGR 4'h4
`define OR1200_SPRGRP_SYS_DCCFGR 4'h5
`define OR1200_SPRGRP_SYS_ICCFGR 4'h6
`define OR1200_SPRGRP_SYS_DCFGR 4'h7
 
// VR fields
`define OR1200_VR_REV_BITS 5:0
`define OR1200_VR_RES1_BITS 15:6
`define OR1200_VR_CFG_BITS 23:16
`define OR1200_VR_VER_BITS 31:24
 
// VR values
`define OR1200_VR_REV 6'h08
`define OR1200_VR_RES1 10'h000
`define OR1200_VR_CFG 8'h00
`define OR1200_VR_VER 8'h12
 
// UPR fields
`define OR1200_UPR_UP_BITS 0
`define OR1200_UPR_DCP_BITS 1
`define OR1200_UPR_ICP_BITS 2
`define OR1200_UPR_DMP_BITS 3
`define OR1200_UPR_IMP_BITS 4
`define OR1200_UPR_MP_BITS 5
`define OR1200_UPR_DUP_BITS 6
`define OR1200_UPR_PCUP_BITS 7
`define OR1200_UPR_PMP_BITS 8
`define OR1200_UPR_PICP_BITS 9
`define OR1200_UPR_TTP_BITS 10
`define OR1200_UPR_FPP_BITS 11
`define OR1200_UPR_RES1_BITS 23:12
`define OR1200_UPR_CUP_BITS 31:24
 
// UPR values
`define OR1200_UPR_UP 1'b1
`ifdef OR1200_NO_DC
`define OR1200_UPR_DCP 1'b0
`else
`define OR1200_UPR_DCP 1'b1
`endif
`ifdef OR1200_NO_IC
`define OR1200_UPR_ICP 1'b0
`else
`define OR1200_UPR_ICP 1'b1
`endif
`ifdef OR1200_NO_DMMU
`define OR1200_UPR_DMP 1'b0
`else
`define OR1200_UPR_DMP 1'b1
`endif
`ifdef OR1200_NO_IMMU
`define OR1200_UPR_IMP 1'b0
`else
`define OR1200_UPR_IMP 1'b1
`endif
`ifdef OR1200_MAC_IMPLEMENTED
`define OR1200_UPR_MP 1'b1
`else
`define OR1200_UPR_MP 1'b0
`endif
`ifdef OR1200_DU_IMPLEMENTED
`define OR1200_UPR_DUP 1'b1
`else
`define OR1200_UPR_DUP 1'b0
`endif
`define OR1200_UPR_PCUP 1'b0 // Performance counters not present
`ifdef OR1200_PM_IMPLEMENTED
`define OR1200_UPR_PMP 1'b1
`else
`define OR1200_UPR_PMP 1'b0
`endif
`ifdef OR1200_PIC_IMPLEMENTED
`define OR1200_UPR_PICP 1'b1
`else
`define OR1200_UPR_PICP 1'b0
`endif
`ifdef OR1200_TT_IMPLEMENTED
`define OR1200_UPR_TTP 1'b1
`else
`define OR1200_UPR_TTP 1'b0
`endif
`ifdef OR1200_FPU_IMPLEMENTED
`define OR1200_UPR_FPP 1'b1
`else
`define OR1200_UPR_FPP 1'b0
`endif
`define OR1200_UPR_RES1 12'h000
`define OR1200_UPR_CUP 8'h00
 
// CPUCFGR fields
`define OR1200_CPUCFGR_NSGF_BITS 3:0
`define OR1200_CPUCFGR_HGF_BITS 4
`define OR1200_CPUCFGR_OB32S_BITS 5
`define OR1200_CPUCFGR_OB64S_BITS 6
`define OR1200_CPUCFGR_OF32S_BITS 7
`define OR1200_CPUCFGR_OF64S_BITS 8
`define OR1200_CPUCFGR_OV64S_BITS 9
`define OR1200_CPUCFGR_RES1_BITS 31:10
 
// CPUCFGR values
`define OR1200_CPUCFGR_NSGF 4'h0
`ifdef OR1200_RFRAM_16REG
`define OR1200_CPUCFGR_HGF 1'b1
`else
`define OR1200_CPUCFGR_HGF 1'b0
`endif
`define OR1200_CPUCFGR_OB32S 1'b1
`define OR1200_CPUCFGR_OB64S 1'b0
`ifdef OR1200_FPU_IMPLEMENTED
`define OR1200_CPUCFGR_OF32S 1'b1
`else
`define OR1200_CPUCFGR_OF32S 1'b0
`endif
 
`define OR1200_CPUCFGR_OF64S 1'b0
`define OR1200_CPUCFGR_OV64S 1'b0
`define OR1200_CPUCFGR_RES1 22'h000000
 
// DMMUCFGR fields
`define OR1200_DMMUCFGR_NTW_BITS 1:0
`define OR1200_DMMUCFGR_NTS_BITS 4:2
`define OR1200_DMMUCFGR_NAE_BITS 7:5
`define OR1200_DMMUCFGR_CRI_BITS 8
`define OR1200_DMMUCFGR_PRI_BITS 9
`define OR1200_DMMUCFGR_TEIRI_BITS 10
`define OR1200_DMMUCFGR_HTR_BITS 11
`define OR1200_DMMUCFGR_RES1_BITS 31:12
 
// DMMUCFGR values
`ifdef OR1200_NO_DMMU
`define OR1200_DMMUCFGR_NTW 2'h0 // Irrelevant
`define OR1200_DMMUCFGR_NTS 3'h0 // Irrelevant
`define OR1200_DMMUCFGR_NAE 3'h0 // Irrelevant
`define OR1200_DMMUCFGR_CRI 1'b0 // Irrelevant
`define OR1200_DMMUCFGR_PRI 1'b0 // Irrelevant
`define OR1200_DMMUCFGR_TEIRI 1'b0 // Irrelevant
`define OR1200_DMMUCFGR_HTR 1'b0 // Irrelevant
`define OR1200_DMMUCFGR_RES1 20'h00000
`else
`define OR1200_DMMUCFGR_NTW 2'h0 // 1 TLB way
`define OR1200_DMMUCFGR_NTS 3'h`OR1200_DTLB_INDXW // Num TLB sets
`define OR1200_DMMUCFGR_NAE 3'h0 // No ATB entries
`define OR1200_DMMUCFGR_CRI 1'b0 // No control register
`define OR1200_DMMUCFGR_PRI 1'b0 // No protection reg
`define OR1200_DMMUCFGR_TEIRI 1'b1 // TLB entry inv reg impl.
`define OR1200_DMMUCFGR_HTR 1'b0 // No HW TLB reload
`define OR1200_DMMUCFGR_RES1 20'h00000
`endif
 
// IMMUCFGR fields
`define OR1200_IMMUCFGR_NTW_BITS 1:0
`define OR1200_IMMUCFGR_NTS_BITS 4:2
`define OR1200_IMMUCFGR_NAE_BITS 7:5
`define OR1200_IMMUCFGR_CRI_BITS 8
`define OR1200_IMMUCFGR_PRI_BITS 9
`define OR1200_IMMUCFGR_TEIRI_BITS 10
`define OR1200_IMMUCFGR_HTR_BITS 11
`define OR1200_IMMUCFGR_RES1_BITS 31:12
 
// IMMUCFGR values
`ifdef OR1200_NO_IMMU
`define OR1200_IMMUCFGR_NTW 2'h0 // Irrelevant
`define OR1200_IMMUCFGR_NTS 3'h0 // Irrelevant
`define OR1200_IMMUCFGR_NAE 3'h0 // Irrelevant
`define OR1200_IMMUCFGR_CRI 1'b0 // Irrelevant
`define OR1200_IMMUCFGR_PRI 1'b0 // Irrelevant
`define OR1200_IMMUCFGR_TEIRI 1'b0 // Irrelevant
`define OR1200_IMMUCFGR_HTR 1'b0 // Irrelevant
`define OR1200_IMMUCFGR_RES1 20'h00000
`else
`define OR1200_IMMUCFGR_NTW 2'h0 // 1 TLB way
`define OR1200_IMMUCFGR_NTS 3'h`OR1200_ITLB_INDXW // Num TLB sets
`define OR1200_IMMUCFGR_NAE 3'h0 // No ATB entry
`define OR1200_IMMUCFGR_CRI 1'b0 // No control reg
`define OR1200_IMMUCFGR_PRI 1'b0 // No protection reg
`define OR1200_IMMUCFGR_TEIRI 1'b1 // TLB entry inv reg impl
`define OR1200_IMMUCFGR_HTR 1'b0 // No HW TLB reload
`define OR1200_IMMUCFGR_RES1 20'h00000
`endif
 
// DCCFGR fields
`define OR1200_DCCFGR_NCW_BITS 2:0
`define OR1200_DCCFGR_NCS_BITS 6:3
`define OR1200_DCCFGR_CBS_BITS 7
`define OR1200_DCCFGR_CWS_BITS 8
`define OR1200_DCCFGR_CCRI_BITS 9
`define OR1200_DCCFGR_CBIRI_BITS 10
`define OR1200_DCCFGR_CBPRI_BITS 11
`define OR1200_DCCFGR_CBLRI_BITS 12
`define OR1200_DCCFGR_CBFRI_BITS 13
`define OR1200_DCCFGR_CBWBRI_BITS 14
`define OR1200_DCCFGR_RES1_BITS 31:15
 
// DCCFGR values
`ifdef OR1200_NO_DC
`define OR1200_DCCFGR_NCW 3'h0 // Irrelevant
`define OR1200_DCCFGR_NCS 4'h0 // Irrelevant
`define OR1200_DCCFGR_CBS 1'b0 // Irrelevant
`define OR1200_DCCFGR_CWS 1'b0 // Irrelevant
`define OR1200_DCCFGR_CCRI 1'b0 // Irrelevant
`define OR1200_DCCFGR_CBIRI 1'b0 // Irrelevant
`define OR1200_DCCFGR_CBPRI 1'b0 // Irrelevant
`define OR1200_DCCFGR_CBLRI 1'b0 // Irrelevant
`define OR1200_DCCFGR_CBFRI 1'b0 // Irrelevant
`define OR1200_DCCFGR_CBWBRI 1'b0 // Irrelevant
`define OR1200_DCCFGR_RES1 17'h00000
`else
`define OR1200_DCCFGR_NCW 3'h0 // 1 cache way
`define OR1200_DCCFGR_NCS (`OR1200_DCTAG) // Num cache sets
`define OR1200_DCCFGR_CBS `OR1200_DCLS==4 ? 1'b0 : 1'b1 // 16 byte cache block
`ifdef OR1200_DC_WRITETHROUGH
`define OR1200_DCCFGR_CWS 1'b0 // Write-through strategy
`else
`define OR1200_DCCFGR_CWS 1'b1 // Write-back strategy
`endif
`define OR1200_DCCFGR_CCRI 1'b1 // Cache control reg impl.
`define OR1200_DCCFGR_CBIRI 1'b1 // Cache block inv reg impl.
`define OR1200_DCCFGR_CBPRI 1'b0 // Cache block prefetch reg not impl.
`define OR1200_DCCFGR_CBLRI 1'b0 // Cache block lock reg not impl.
`define OR1200_DCCFGR_CBFRI 1'b1 // Cache block flush reg impl.
`ifdef OR1200_DC_WRITETHROUGH
`define OR1200_DCCFGR_CBWBRI 1'b0 // Cache block WB reg not impl.
`else
`define OR1200_DCCFGR_CBWBRI 1'b1 // Cache block WB reg impl.
`endif
`define OR1200_DCCFGR_RES1 17'h00000
`endif
 
// ICCFGR fields
`define OR1200_ICCFGR_NCW_BITS 2:0
`define OR1200_ICCFGR_NCS_BITS 6:3
`define OR1200_ICCFGR_CBS_BITS 7
`define OR1200_ICCFGR_CWS_BITS 8
`define OR1200_ICCFGR_CCRI_BITS 9
`define OR1200_ICCFGR_CBIRI_BITS 10
`define OR1200_ICCFGR_CBPRI_BITS 11
`define OR1200_ICCFGR_CBLRI_BITS 12
`define OR1200_ICCFGR_CBFRI_BITS 13
`define OR1200_ICCFGR_CBWBRI_BITS 14
`define OR1200_ICCFGR_RES1_BITS 31:15
 
// ICCFGR values
`ifdef OR1200_NO_IC
`define OR1200_ICCFGR_NCW 3'h0 // Irrelevant
`define OR1200_ICCFGR_NCS 4'h0 // Irrelevant
`define OR1200_ICCFGR_CBS 1'b0 // Irrelevant
`define OR1200_ICCFGR_CWS 1'b0 // Irrelevant
`define OR1200_ICCFGR_CCRI 1'b0 // Irrelevant
`define OR1200_ICCFGR_CBIRI 1'b0 // Irrelevant
`define OR1200_ICCFGR_CBPRI 1'b0 // Irrelevant
`define OR1200_ICCFGR_CBLRI 1'b0 // Irrelevant
`define OR1200_ICCFGR_CBFRI 1'b0 // Irrelevant
`define OR1200_ICCFGR_CBWBRI 1'b0 // Irrelevant
`define OR1200_ICCFGR_RES1 17'h00000
`else
`define OR1200_ICCFGR_NCW 3'h0 // 1 cache way
`define OR1200_ICCFGR_NCS (`OR1200_ICTAG) // Num cache sets
`define OR1200_ICCFGR_CBS `OR1200_ICLS==4 ? 1'b0: 1'b1 // 16 byte cache block
`define OR1200_ICCFGR_CWS 1'b0 // Irrelevant
`define OR1200_ICCFGR_CCRI 1'b1 // Cache control reg impl.
`define OR1200_ICCFGR_CBIRI 1'b1 // Cache block inv reg impl.
`define OR1200_ICCFGR_CBPRI 1'b0 // Cache block prefetch reg not impl.
`define OR1200_ICCFGR_CBLRI 1'b0 // Cache block lock reg not impl.
`define OR1200_ICCFGR_CBFRI 1'b1 // Cache block flush reg impl.
`define OR1200_ICCFGR_CBWBRI 1'b0 // Irrelevant
`define OR1200_ICCFGR_RES1 17'h00000
`endif
 
// DCFGR fields
`define OR1200_DCFGR_NDP_BITS 3:0
`define OR1200_DCFGR_WPCI_BITS 4
`define OR1200_DCFGR_RES1_BITS 31:5
 
// DCFGR values
`ifdef OR1200_DU_HWBKPTS
`define OR1200_DCFGR_NDP 4'h`OR1200_DU_DVRDCR_PAIRS // # of DVR/DCR pairs
`ifdef OR1200_DU_DWCR0
`define OR1200_DCFGR_WPCI 1'b1
`else
`define OR1200_DCFGR_WPCI 1'b0 // WP counters not impl.
`endif
`else
`define OR1200_DCFGR_NDP 4'h0 // Zero DVR/DCR pairs
`define OR1200_DCFGR_WPCI 1'b0 // WP counters not impl.
`endif
`define OR1200_DCFGR_RES1 27'd0
 
///////////////////////////////////////////////////////////////////////////////
// Boot Address Selection //
// This only changes where the initial reset occurs. EPH setting is still //
// used to determine where vectors are located. //
///////////////////////////////////////////////////////////////////////////////
// Boot from 0xf0000100
//`define OR1200_BOOT_PCREG_DEFAULT 30'h3c00003f
//`define OR1200_BOOT_ADR 32'hf0000100
// Boot from 0x100
`define OR1200_BOOT_PCREG_DEFAULT 30'h0000003f
`define OR1200_BOOT_ADR 32'h00000100
/boards/xilinx/ml501/rtl/verilog/include/orpsoc-defines.v
0,0 → 1,89
//////////////////////////////////////////////////////////////////////
//// ////
//// orpsoc-defines ////
//// ////
//// Top level ORPSoC defines file ////
//// ////
//// Included in toplevel and testbench ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2009, 2010 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//
// Uncomment a `define BOARD_XYZ to configure design RTL for it.
//
// Mainly presets are for internal frequency settings, and what
// external oscillator is expected (ordb1's were made with various
// XTALs.)
//
//////////////////////////////////////////////////////////////////////
 
`define XILINX
`define XILINX_PLL
`define FPGA_BOARD_XILINX_ML501
`define IOCONFIG_XILINX_ML501
`define BOARD_CLOCK_PERIOD 5000 // 200MHz (pS accuracy for Xilinx sims.)
 
`define JTAG_DEBUG
// `define RAM_WB
// `define XILINX_SSRAM
`define XILINX_DDR2
`define UART0
`define GPIO0
`define SPI0
`define I2C0
`define I2C1
`define ETH0
`define ETH0_PHY_RST
 
// end of included module defines - keep this comment line here, scripts depend on it!!
 
 
//
// Arbiter defines
//
 
// Uncomment to register things through arbiter (hopefully quicker design)
// Instruction bus arbiter
//`define ARBITER_IBUS_REGISTERING
`define ARBITER_IBUS_WATCHDOG
// Watchdog timeout: 2^(ARBITER_IBUS_WATCHDOG_TIMER_WIDTH+1) cycles
`define ARBITER_IBUS_WATCHDOG_TIMER_WIDTH 12
 
// Data bus arbiter
 
//`define ARBITER_DBUS_REGISTERING
`define ARBITER_DBUS_WATCHDOG
// Watchdog timeout: 2^(ARBITER_DBUS_WATCHDOG_TIMER_WIDTH+1) cycles
`define ARBITER_DBUS_WATCHDOG_TIMER_WIDTH 12
 
// Byte bus (peripheral bus) arbiter
// Don't really need the watchdog here - the databus will pick it up
//`define ARBITER_BYTEBUS_WATCHDOG
// Watchdog timeout: 2^(ARBITER_BYTEBUS_WATCHDOG_TIMER_WIDTH+1) cycles
`define ARBITER_BYTEBUS_WATCHDOG_TIMER_WIDTH 9
 
/boards/xilinx/ml501/rtl/verilog/include/dbg_wb_defines.v
0,0 → 1,113
//////////////////////////////////////////////////////////////////////
//// ////
//// dbg_wb_defines.v ////
//// ////
//// ////
//// This file is part of the SoC Debug Interface. ////
//// http://www.opencores.org/projects/DebugInterface/ ////
//// ////
//// Author(s): ////
//// Igor Mohor (igorm@opencores.org) ////
//// ////
//// ////
//// All additional information is avaliable in the README.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000 - 2004 Authors ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: dbg_wb_defines.v,v $
// Revision 1.7 2004/03/31 14:34:08 igorm
// data_cnt_lim length changed to reduce number of warnings.
//
// Revision 1.6 2004/03/28 20:27:02 igorm
// New release of the debug interface (3rd. release).
//
// Revision 1.5 2004/03/22 16:35:46 igorm
// Temp version before changing dbg interface.
//
// Revision 1.4 2004/01/16 14:51:33 mohor
// cpu registers added.
//
// Revision 1.3 2004/01/08 17:53:36 mohor
// tmp version.
//
// Revision 1.2 2004/01/06 17:15:19 mohor
// temp3 version.
//
// Revision 1.1 2003/12/23 15:09:04 mohor
// New directory structure. New version of the debug interface.
//
//
//
 
// Defining length of the command
`define DBG_WB_CMD_LEN 3'd4
`define DBG_WB_CMD_LEN_INT 4
`define DBG_WB_CMD_CNT_WIDTH 3
 
// Defining length of the access_type field
`define DBG_WB_ACC_TYPE_LEN 4
 
 
// Defining length of the address
`define DBG_WB_ADR_LEN 32
 
// Defining length of the length register
`define DBG_WB_LEN_LEN 16
 
// Defining total length of the DR needed
`define DBG_WB_DR_LEN (`DBG_WB_ACC_TYPE_LEN + `DBG_WB_ADR_LEN + `DBG_WB_LEN_LEN)
 
// Defining length of the CRC
`define DBG_WB_CRC_LEN 6'd32
`define DBG_WB_CRC_CNT_WIDTH 6
 
// Defining length of status
`define DBG_WB_STATUS_LEN 3'd4
`define DBG_WB_STATUS_CNT_WIDTH 3
 
// Defining length of the data
`define DBG_WB_DATA_CNT_WIDTH (`DBG_WB_LEN_LEN + 3)
`define DBG_WB_DATA_CNT_LIM_WIDTH `DBG_WB_LEN_LEN
 
//Defining commands
`define DBG_WB_GO 4'h0
`define DBG_WB_RD_COMM 4'h1
`define DBG_WB_WR_COMM 4'h2
 
// Defining access types for wishbone
`define DBG_WB_WRITE8 4'h0
`define DBG_WB_WRITE16 4'h1
`define DBG_WB_WRITE32 4'h2
`define DBG_WB_READ8 4'h4
`define DBG_WB_READ16 4'h5
`define DBG_WB_READ32 4'h6
 
 
/boards/xilinx/ml501/rtl/verilog/include/tap_defines.v
0,0 → 1,69
//////////////////////////////////////////////////////////////////////
//// ////
//// tap_defines.v ////
//// ////
//// ////
//// This file is part of the JTAG Test Access Port (TAP) ////
//// http://www.opencores.org/projects/jtag/ ////
//// ////
//// Author(s): ////
//// Igor Mohor (igorm@opencores.org) ////
//// ////
//// ////
//// All additional information is avaliable in the README.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000 - 2003 Authors ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: tap_defines.v,v $
// Revision 1.2 2004/01/27 10:00:33 mohor
// Unused registers removed.
//
// Revision 1.1 2003/12/23 14:52:14 mohor
// Directory structure changed. New version of TAP.
//
//
//
 
 
// Define IDCODE Value
`define IDCODE_VALUE 32'h14951185
 
// Length of the Instruction register
`define IR_LENGTH 4
 
// Supported Instructions
`define EXTEST 4'b0000
`define SAMPLE_PRELOAD 4'b0001
`define IDCODE 4'b0010
`define DEBUG 4'b1000
`define MBIST 4'b1001
`define BYPASS 4'b1111
 
/boards/xilinx/ml501/rtl/verilog/include/orpsoc-params.v
0,0 → 1,165
//////////////////////////////////////////////////////////////////////
//// ////
//// orpsoc-params ////
//// ////
//// Top level ORPSoC parameters file ////
//// ////
//// Included in toplevel and testbench ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2009, 2010 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
 
///////////////////////////
// //
// Peripheral parameters //
// //
///////////////////////////
 
// SPI 0 params
parameter spi0_ss_width = 1;
parameter spi0_wb_adr = 8'hb0;
parameter wbs_d_spi0_data_width = 8;
parameter spi0_wb_adr_width = 3;
 
// i2c master slave params
// Slave addresses
parameter HV0_SADR = 8'h44;
parameter HV1_SADR = 8'h45;
parameter HV2_SADR = 8'h46;
parameter HV3_SADR = 8'h47;
 
// i2c 0 params
parameter i2c_0_wb_adr = 8'ha0;
parameter i2c_0_wb_adr_width = 3;
parameter wbs_d_i2c0_data_width = 8;
 
// i2c 1 params
parameter i2c_1_wb_adr = 8'ha1;
parameter i2c_1_wb_adr_width = 3;
parameter wbs_d_i2c1_data_width = 8;
 
 
// GPIO 0 params
parameter wbs_d_gpio0_data_width = 8;
parameter gpio0_wb_adr_width = 3;
parameter gpio0_io_width = 24;
parameter gpio0_wb_adr = 8'h91;
parameter gpio0_dir_reset_val = 0;
parameter gpio0_o_reset_val = 0;
 
// UART 0 params
parameter wbs_d_uart0_data_width = 8;
parameter uart0_wb_adr = 8'h90;
parameter uart0_data_width = 8;
parameter uart0_addr_width = 3;
 
// ROM
parameter wbs_i_rom0_data_width = 32;
parameter wbs_i_rom0_addr_width = 6;
parameter rom0_wb_adr = 4'hf;
 
// MC0 (SDRAM, or other)
parameter wbs_i_mc0_data_width = 32;
parameter wbs_d_mc0_data_width = 32;
 
// ETH0 defines
parameter eth0_wb_adr = 8'h92;
parameter wbs_d_eth0_data_width = 32;
parameter wbs_d_eth0_addr_width = 12;
parameter wbm_eth0_data_width = 32;
parameter wbm_eth0_addr_width = 32;
 
// Memory sizing for synthesis (small)
parameter internal_sram_mem_span = 32'h0080_0000;
parameter internal_sram_adr_width_for_span = 23;
 
//////////////////////////////////////////////////////
// //
// Wishbone bus parameters //
// //
//////////////////////////////////////////////////////
 
////////////////////////
// //
// Arbiter parameters //
// //
////////////////////////
 
parameter wb_dw = 32; // Default Wishbone full word width
parameter wb_aw = 32; // Default Wishbone full address width
 
///////////////////////////
// //
// Instruction bus //
// //
///////////////////////////
parameter ibus_arb_addr_match_width = 4;
// Slave addresses
parameter ibus_arb_slave0_adr = rom0_wb_adr; // FLASH ROM
parameter ibus_arb_slave1_adr = 4'h0; // Main memory (SDRAM/FPGA SRAM)
 
///////////////////////////
// //
// Data bus //
// //
///////////////////////////
// Has auto foward to last slave when no address hits
parameter dbus_arb_wb_addr_match_width = 8;
parameter dbus_arb_wb_num_slaves = 5;
// Slave addresses
parameter dbus_arb_slave0_adr = 4'h0; // Main memory (SDRAM/FPGA SRAM)
parameter dbus_arb_slave1_adr = eth0_wb_adr; // Ethernet 0
 
///////////////////////////////
// //
// Byte-wide peripheral bus //
// //
///////////////////////////////
parameter bbus_arb_wb_addr_match_width = 8;
parameter bbus_arb_wb_num_slaves = 5; // Update this when changing slaves!
// Slave addresses
parameter bbus_arb_slave0_adr = uart0_wb_adr;
parameter bbus_arb_slave1_adr = gpio0_wb_adr;
parameter bbus_arb_slave2_adr = i2c_0_wb_adr;
parameter bbus_arb_slave3_adr = i2c_1_wb_adr;
parameter bbus_arb_slave4_adr = spi0_wb_adr;
parameter bbus_arb_slave5_adr = 0 /* UNASSIGNED */;
parameter bbus_arb_slave6_adr = 0 /* UNASSIGNED */;
parameter bbus_arb_slave7_adr = 0 /* UNASSIGNED */;
parameter bbus_arb_slave8_adr = 0 /* UNASSIGNED */;
parameter bbus_arb_slave9_adr = 0 /* UNASSIGNED */;
parameter bbus_arb_slave10_adr = 0 /* UNASSIGNED */;
parameter bbus_arb_slave11_adr = 0 /* UNASSIGNED */;
parameter bbus_arb_slave12_adr = 0 /* UNASSIGNED */;
parameter bbus_arb_slave13_adr = 0 /* UNASSIGNED */;
parameter bbus_arb_slave14_adr = 0 /* UNASSIGNED */;
parameter bbus_arb_slave15_adr = 0 /* UNASSIGNED */;
parameter bbus_arb_slave16_adr = 0 /* UNASSIGNED */;
 
 
 
 
/boards/xilinx/ml501/rtl/verilog/include/uart_defines.v
0,0 → 1,250
//////////////////////////////////////////////////////////////////////
//// ////
//// uart_defines.v ////
//// ////
//// ////
//// This file is part of the "UART 16550 compatible" project ////
//// http://www.opencores.org/cores/uart16550/ ////
//// ////
//// Documentation related to this project: ////
//// - http://www.opencores.org/cores/uart16550/ ////
//// ////
//// Projects compatibility: ////
//// - WISHBONE ////
//// RS232 Protocol ////
//// 16550D uart (mostly supported) ////
//// ////
//// Overview (main Features): ////
//// Defines of the Core ////
//// ////
//// Known problems (limits): ////
//// None ////
//// ////
//// To Do: ////
//// Nothing. ////
//// ////
//// Author(s): ////
//// - gorban@opencores.org ////
//// - Jacob Gorban ////
//// - Igor Mohor (igorm@opencores.org) ////
//// ////
//// Created: 2001/05/12 ////
//// Last Updated: 2001/05/17 ////
//// (See log for the revision history) ////
//// ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000, 2001 Authors ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.13 2003/06/11 16:37:47 gorban
// This fixes errors in some cases when data is being read and put to the FIFO at the same time. Patch is submitted by Scott Furman. Update is very recommended.
//
// Revision 1.12 2002/07/22 23:02:23 gorban
// Bug Fixes:
// * Possible loss of sync and bad reception of stop bit on slow baud rates fixed.
// Problem reported by Kenny.Tung.
// * Bad (or lack of ) loopback handling fixed. Reported by Cherry Withers.
//
// Improvements:
// * Made FIFO's as general inferrable memory where possible.
// So on FPGA they should be inferred as RAM (Distributed RAM on Xilinx).
// This saves about 1/3 of the Slice count and reduces P&R and synthesis times.
//
// * Added optional baudrate output (baud_o).
// This is identical to BAUDOUT* signal on 16550 chip.
// It outputs 16xbit_clock_rate - the divided clock.
// It's disabled by default. Define UART_HAS_BAUDRATE_OUTPUT to use.
//
// Revision 1.10 2001/12/11 08:55:40 mohor
// Scratch register define added.
//
// Revision 1.9 2001/12/03 21:44:29 gorban
// Updated specification documentation.
// Added full 32-bit data bus interface, now as default.
// Address is 5-bit wide in 32-bit data bus mode.
// Added wb_sel_i input to the core. It's used in the 32-bit mode.
// Added debug interface with two 32-bit read-only registers in 32-bit mode.
// Bits 5 and 6 of LSR are now only cleared on TX FIFO write.
// My small test bench is modified to work with 32-bit mode.
//
// Revision 1.8 2001/11/26 21:38:54 gorban
// Lots of fixes:
// Break condition wasn't handled correctly at all.
// LSR bits could lose their values.
// LSR value after reset was wrong.
// Timing of THRE interrupt signal corrected.
// LSR bit 0 timing corrected.
//
// Revision 1.7 2001/08/24 21:01:12 mohor
// Things connected to parity changed.
// Clock devider changed.
//
// Revision 1.6 2001/08/23 16:05:05 mohor
// Stop bit bug fixed.
// Parity bug fixed.
// WISHBONE read cycle bug fixed,
// OE indicator (Overrun Error) bug fixed.
// PE indicator (Parity Error) bug fixed.
// Register read bug fixed.
//
// Revision 1.5 2001/05/31 20:08:01 gorban
// FIFO changes and other corrections.
//
// Revision 1.4 2001/05/21 19:12:02 gorban
// Corrected some Linter messages.
//
// Revision 1.3 2001/05/17 18:34:18 gorban
// First 'stable' release. Should be sythesizable now. Also added new header.
//
// Revision 1.0 2001-05-17 21:27:11+02 jacob
// Initial revision
//
//
 
// remove comments to restore to use the new version with 8 data bit interface
// in 32bit-bus mode, the wb_sel_i signal is used to put data in correct place
// also, in 8-bit version there'll be no debugging features included
// CAUTION: doesn't work with current version of OR1200
`define DATA_BUS_WIDTH_8
 
`ifdef DATA_BUS_WIDTH_8
`define UART_ADDR_WIDTH 3
`define UART_DATA_WIDTH 8
`else
`define UART_ADDR_WIDTH 5
`define UART_DATA_WIDTH 32
`endif
 
// Uncomment this if you want your UART to have
// 16xBaudrate output port.
// If defined, the enable signal will be used to drive baudrate_o signal
// It's frequency is 16xbaudrate
 
// `define UART_HAS_BAUDRATE_OUTPUT
 
// Register addresses
`define UART_REG_RB `UART_ADDR_WIDTH'd0 // receiver buffer
`define UART_REG_TR `UART_ADDR_WIDTH'd0 // transmitter
`define UART_REG_IE `UART_ADDR_WIDTH'd1 // Interrupt enable
`define UART_REG_II `UART_ADDR_WIDTH'd2 // Interrupt identification
`define UART_REG_FC `UART_ADDR_WIDTH'd2 // FIFO control
`define UART_REG_LC `UART_ADDR_WIDTH'd3 // Line Control
`define UART_REG_MC `UART_ADDR_WIDTH'd4 // Modem control
`define UART_REG_LS `UART_ADDR_WIDTH'd5 // Line status
`define UART_REG_MS `UART_ADDR_WIDTH'd6 // Modem status
`define UART_REG_SR `UART_ADDR_WIDTH'd7 // Scratch register
`define UART_REG_DL1 `UART_ADDR_WIDTH'd0 // Divisor latch bytes (1-2)
`define UART_REG_DL2 `UART_ADDR_WIDTH'd1
 
// Interrupt Enable register bits
`define UART_IE_RDA 0 // Received Data available interrupt
`define UART_IE_THRE 1 // Transmitter Holding Register empty interrupt
`define UART_IE_RLS 2 // Receiver Line Status Interrupt
`define UART_IE_MS 3 // Modem Status Interrupt
 
// Interrupt Identification register bits
`define UART_II_IP 0 // Interrupt pending when 0
`define UART_II_II 3:1 // Interrupt identification
 
// Interrupt identification values for bits 3:1
`define UART_II_RLS 3'b011 // Receiver Line Status
`define UART_II_RDA 3'b010 // Receiver Data available
`define UART_II_TI 3'b110 // Timeout Indication
`define UART_II_THRE 3'b001 // Transmitter Holding Register empty
`define UART_II_MS 3'b000 // Modem Status
 
// FIFO Control Register bits
`define UART_FC_TL 1:0 // Trigger level
 
// FIFO trigger level values
`define UART_FC_1 2'b00
`define UART_FC_4 2'b01
`define UART_FC_8 2'b10
`define UART_FC_14 2'b11
 
// Line Control register bits
`define UART_LC_BITS 1:0 // bits in character
`define UART_LC_SB 2 // stop bits
`define UART_LC_PE 3 // parity enable
`define UART_LC_EP 4 // even parity
`define UART_LC_SP 5 // stick parity
`define UART_LC_BC 6 // Break control
`define UART_LC_DL 7 // Divisor Latch access bit
 
// Modem Control register bits
`define UART_MC_DTR 0
`define UART_MC_RTS 1
`define UART_MC_OUT1 2
`define UART_MC_OUT2 3
`define UART_MC_LB 4 // Loopback mode
 
// Line Status Register bits
`define UART_LS_DR 0 // Data ready
`define UART_LS_OE 1 // Overrun Error
`define UART_LS_PE 2 // Parity Error
`define UART_LS_FE 3 // Framing Error
`define UART_LS_BI 4 // Break interrupt
`define UART_LS_TFE 5 // Transmit FIFO is empty
`define UART_LS_TE 6 // Transmitter Empty indicator
`define UART_LS_EI 7 // Error indicator
 
// Modem Status Register bits
`define UART_MS_DCTS 0 // Delta signals
`define UART_MS_DDSR 1
`define UART_MS_TERI 2
`define UART_MS_DDCD 3
`define UART_MS_CCTS 4 // Complement signals
`define UART_MS_CDSR 5
`define UART_MS_CRI 6
`define UART_MS_CDCD 7
 
// FIFO parameter defines
 
`define UART_FIFO_WIDTH 8
`define UART_FIFO_DEPTH 16
`define UART_FIFO_POINTER_W 4
`define UART_FIFO_COUNTER_W 5
// receiver fifo has width 11 because it has break, parity and framing error bits
`define UART_FIFO_REC_WIDTH 11
 
 
`define VERBOSE_WB 0 // All activity on the WISHBONE is recorded
`define VERBOSE_LINE_STATUS 0 // Details about the lsr (line status register)
`define FAST_TEST 1 // 64/1024 packets are sent
 
// Defines hard baud prescaler register - uncomment to enable
`define PRESCALER_PRESET_HARD
// 115200 baud preset values
// 20MHz: prescaler 10.8 (11, rounded up)
//`define PRESCALER_HIGH_PRESET 8'd0
//`define PRESCALER_LOW_PRESET 8'd11
// 50MHz: prescaler 27.1
`define PRESCALER_HIGH_PRESET 8'd0
`define PRESCALER_LOW_PRESET 8'd27
/boards/xilinx/ml501/rtl/verilog/include/dbg_defines.v
0,0 → 1,153
//////////////////////////////////////////////////////////////////////
//// ////
//// dbg_defines.v ////
//// ////
//// ////
//// This file is part of the SoC Debug Interface. ////
//// http://www.opencores.org/projects/DebugInterface/ ////
//// ////
//// Author(s): ////
//// Igor Mohor (igorm@opencores.org) ////
//// ////
//// ////
//// All additional information is avaliable in the README.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000 - 2004 Authors ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: dbg_defines.v,v $
// Revision 1.20 2004/04/01 11:56:59 igorm
// Port names and defines for the supported CPUs changed.
//
// Revision 1.19 2004/03/28 20:27:02 igorm
// New release of the debug interface (3rd. release).
//
// Revision 1.18 2004/03/22 16:35:46 igorm
// Temp version before changing dbg interface.
//
// Revision 1.17 2004/01/30 10:24:30 mohor
// Defines WISHBONE_SUPPORTED and CPU_SUPPORTED added. By default both are
// turned on.
//
// Revision 1.16 2004/01/20 14:23:45 mohor
// Define name changed.
//
// Revision 1.15 2003/12/23 15:07:34 mohor
// New directory structure. New version of the debug interface.
// Files that are not needed removed.
//
// Revision 1.14 2003/10/23 16:17:00 mohor
// CRC logic changed.
//
// Revision 1.13 2003/10/21 09:48:31 simons
// Mbist support added.
//
// Revision 1.12 2003/09/17 14:38:57 simons
// WB_CNTL register added, some syncronization fixes.
//
// Revision 1.11 2003/08/28 13:55:21 simons
// Three more chains added for cpu debug access.
//
// Revision 1.10 2003/07/31 12:19:49 simons
// Multiple cpu support added.
//
// Revision 1.9 2002/05/07 14:43:59 mohor
// mon_cntl_o signals that controls monitor mux added.
//
// Revision 1.8 2002/01/25 07:58:34 mohor
// IDCODE bug fixed, chains reused to decreas size of core. Data is shifted-in
// not filled-in. Tested in hw.
//
// Revision 1.7 2001/12/06 10:08:06 mohor
// Warnings from synthesys tools fixed.
//
// Revision 1.6 2001/11/28 09:38:30 mohor
// Trace disabled by default.
//
// Revision 1.5 2001/10/15 09:55:47 mohor
// Wishbone interface added, few fixes for better performance,
// hooks for boundary scan testing added.
//
// Revision 1.4 2001/09/24 14:06:42 mohor
// Changes connected to the OpenRISC access (SPR read, SPR write).
//
// Revision 1.3 2001/09/20 10:11:25 mohor
// Working version. Few bugs fixed, comments added.
//
// Revision 1.2 2001/09/18 14:13:47 mohor
// Trace fixed. Some registers changed, trace simplified.
//
// Revision 1.1.1.1 2001/09/13 13:49:19 mohor
// Initial official release.
//
// Revision 1.3 2001/06/01 22:22:35 mohor
// This is a backup. It is not a fully working version. Not for use, yet.
//
// Revision 1.2 2001/05/18 13:10:00 mohor
// Headers changed. All additional information is now avaliable in the README.txt file.
//
// Revision 1.1.1.1 2001/05/18 06:35:08 mohor
// Initial release
//
//
 
 
// Length of the MODULE ID register
`define DBG_TOP_MODULE_ID_LENGTH 4
 
// Length of data
`define DBG_TOP_MODULE_DATA_LEN `DBG_TOP_MODULE_ID_LENGTH + 1
`define DBG_TOP_DATA_CNT 3
 
// Length of status
`define DBG_TOP_STATUS_LEN 3'd4
`define DBG_TOP_STATUS_CNT_WIDTH 3
 
// Length of the CRC
`define DBG_TOP_CRC_LEN 32
`define DBG_TOP_CRC_CNT 6
 
// Chains
`define DBG_TOP_WISHBONE_DEBUG_MODULE 4'h0
`define DBG_TOP_CPU0_DEBUG_MODULE 4'h1
`define DBG_TOP_CPU1_DEBUG_MODULE 4'h2
 
// If WISHBONE sub-module is supported uncomment the folowing line
`define DBG_WISHBONE_SUPPORTED
 
// If CPU_0 sub-module is supported uncomment the folowing line
`define DBG_CPU0_SUPPORTED
 
// If CPU_1 sub-module is supported uncomment the folowing line
//`define DBG_CPU1_SUPPORTED
 
// If more debug info is needed, uncomment the follofing line
//`define DBG_MORE_INFO
 
/boards/xilinx/ml501/rtl/verilog/include/xilinx_ddr2_params.v
0,0 → 1,53
 
// memory controller parameters
parameter BANK_WIDTH = 2; // # of memory bank addr bits
parameter CKE_WIDTH = 2; // # of memory clock enable outputs
parameter CLK_WIDTH = 2; // # of clock outputs
parameter CLK_TYPE = "SINGLE_ENDED"; // # of clock type
parameter COL_WIDTH = 10; // # of memory column bits
parameter CS_NUM = 1; // # of separate memory chip selects
parameter CS_WIDTH = 2; // # of total memory chip selects
parameter CS_BITS = 0; // set to log2(CS_NUM) (rounded up)
parameter DM_WIDTH = 8; // # of data mask bits
parameter DQ_WIDTH = 64; // # of data width
parameter DQ_PER_DQS = 8; // # of DQ data bits per strobe
parameter DQS_WIDTH = 8; // # of DQS strobes
parameter DQ_BITS = 6; // set to log2(DQS_WIDTH*DQ_PER_DQS)
parameter DQS_BITS = 3; // set to log2(DQS_WIDTH)
parameter HIGH_PERFORMANCE_MODE = "TRUE"; // Sets the performance mode for IODELAY elements
parameter ODT_WIDTH = 2; // # of memory on-die term enables
parameter ROW_WIDTH = 13; // # of memory row & # of addr bits
// Can't change this!!
parameter APPDATA_WIDTH = 128; // # of usr read/write data bus bits
//parameter APPDATA_WIDTH = 32; // # of usr read/write data bus bits
 
parameter ADDITIVE_LAT = 0; // additive write latency
// Controller with cache!
parameter BURST_LEN = 8; // burst length (in double words)
// Old controller
// parameter BURST_LEN = 4; // burst length (in double words)
parameter BURST_TYPE = 0; // burst type (=0 seq; =1 interlved)
parameter CAS_LAT = 4; // CAS latency
parameter ECC_ENABLE = 0; // enable ECC (=1 enable)
parameter MULTI_BANK_EN = 1; // enable bank management
parameter TWO_T_TIME_EN = 1; // 2t timing for unbuffered dimms
parameter ODT_TYPE = 1; // ODT (=0(none),=1(75),=2(150),=3(50))
parameter REDUCE_DRV = 0; // reduced strength mem I/O (=1 yes)
parameter REG_ENABLE = 0; // registered addr/ctrl (=1 yes)
parameter TREFI_NS = 7800; // auto refresh interval (ns)
parameter TRAS = 40000; // active->precharge delay
parameter TRCD = 15000; // active->read/write delay
parameter TRFC = 105000; // ref->ref, ref->active delay
parameter TRP = 15000; // precharge->command delay
parameter TRTP = 7500; // read->precharge delay
parameter TWR = 15000; // used to determine wr->prech
parameter TWTR = 7500; // write->read delay
// Synthesize with this set to one if running post-synthesis simulations (don't have to wait forever for powerup delay on DDR2 controller)
// parameter SIM_ONLY = 1; // = 0 to allow power up delay
parameter SIM_ONLY = 0; // = 0 to allow power up delay
parameter DEBUG_EN = 0; // Enable debug signals/controls
parameter RST_ACT_LOW = 0; // =1 for active low reset, =0 for active high
parameter DLL_FREQ_MODE = "HIGH"; // DCM Frequency range
parameter CLK_PERIOD = 3750; // 266MHz Core/Mem clk period (in ps)
// parameter CLK_PERIOD = 5000; // 200MHz Core/Mem clk period (in ps)
 
/boards/xilinx/ml501/rtl/verilog/lfsr/lfsr.v
0,0 → 1,118
//////////////////////////////////////////////////////////////////////
//// ////
//// Linear feedback shift register with Wishbone interface ////
//// ////
//// Description ////
//// Simple LFSR module (feedback hardcoded) ////
//// Two accessible registers: ////
//// Address 0: LFSR Register (R/W) ////
//// Address 4: Control register, active high, self resetting (WO)////
//// Bit[0]: lfsr shift enable ////
//// Bit[1]: lfsr reset ////
//// ////
//// To Do: ////
//// Perhaps make feedback parameterisable ////
//// ////
//// Author(s): ////
//// - Julius Baxter, julius.baxter@orsoc.se ////
//// ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2010 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
module wb_lfsr( wb_clk, wb_rst, wb_adr_i, wb_dat_i, wb_cyc_i, wb_stb_i, wb_we_i,
wb_dat_o, wb_ack_o);
parameter width = 32;
parameter lfsr_rst_value = 32'b0011_0001_0000_1010;
input wb_clk;
input wb_rst;
input [2:0] wb_adr_i;
input [width-1:0] wb_dat_i;
input wb_cyc_i, wb_stb_i, wb_we_i;
output [width-1:0] wb_dat_o;
output reg wb_ack_o;
wire wb_req;
assign wb_req = wb_stb_i & wb_cyc_i;
reg [width-1:0] lfsr;
wire lfsr_feedback;
 
assign wb_dat_o = lfsr;
 
// Only 2 registers here, the lfsr itself and
wire lfsr_sel;
assign lfsr_sel = !wb_adr_i[2];
wire lfsr_control_reg_sel;
assign lfsr_control_reg_sel = wb_adr_i[2];
 
// [0]: shift enable, [1]: reset
reg [1:0] lfsr_control_reg;
wire lfsr_control_enable;
wire lfsr_control_rst;
 
// Load the control reg when required,
always @(posedge wb_clk)
begin
if (wb_rst)
lfsr_control_reg <= 0;
else if (wb_req & wb_we_i & lfsr_control_reg_sel & wb_ack_o)
lfsr_control_reg <= wb_dat_i;
if (lfsr_control_reg[0])
lfsr_control_reg[0] <= 0;
if (lfsr_control_reg[1])
lfsr_control_reg[1] <= 0;
end // always @ (posedge wb_clk)
 
assign lfsr_control_enable = lfsr_control_reg[0];
assign lfsr_control_rst = lfsr_control_reg[1];
assign lfsr_feedback = !(((lfsr[27] ^ lfsr[13]) ^ lfsr[8]) ^ lfsr[5]);
always @(posedge wb_clk)
if (wb_rst)
lfsr <= lfsr_rst_value;
else if (lfsr_control_rst)
lfsr <= lfsr_rst_value;
else if (wb_req & wb_we_i & lfsr_sel & wb_ack_o) // Set lfsr
lfsr <= wb_dat_i;
else if (lfsr_control_enable)
lfsr <= {lfsr[width-2:0], lfsr_feedback};
always @(posedge wb_clk)
if (wb_rst)
wb_ack_o <= 0;
else if (wb_req & !wb_ack_o)
wb_ack_o <= 1;
else if (wb_ack_o)
wb_ack_o <= 0;
 
endmodule // lfsr
/boards/xilinx/ml501/rtl/verilog/xilinx_ddr2/ddr2_phy_dqs_iob.v
0,0 → 1,263
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007, 2008 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_phy_dqs_iob.v
// /___/ /\ Date Last Modified: $Date: 2008/12/23 14:26:00 $
// \ \ / \ Date Created: Wed Aug 16 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR2
//Purpose:
// This module places the data strobes in the IOBs.
//Reference:
//Revision History:
// Rev 1.1 - Parameter HIGH_PERFORMANCE_MODE added. PK. 7/10/08
// Rev 1.2 - Parameter IODELAY_GRP added and constraint IODELAY_GROUP added
// on IODELAY primitives. PK. 11/27/08
//*****************************************************************************
 
`timescale 1ns/1ps
 
module ddr2_phy_dqs_iob #
(
// Following parameters are for 72-bit RDIMM design (for ML561 Reference
// board design). Actual values may be different. Actual parameters values
// are passed from design top module ddr2_mig module. Please refer to
// the ddr2_mig module for actual values.
parameter DDR_TYPE = 1,
parameter HIGH_PERFORMANCE_MODE = "TRUE",
parameter IODELAY_GRP = "IODELAY_MIG"
)
(
input clk0,
input clkdiv0,
input rst0,
input dlyinc_dqs,
input dlyce_dqs,
input dlyrst_dqs,
input dlyinc_gate,
input dlyce_gate,
input dlyrst_gate,
input dqs_oe_n,
input dqs_rst_n,
input en_dqs,
inout ddr_dqs,
inout ddr_dqs_n,
output dq_ce,
output delayed_dqs
);
 
wire clk180;
wire dqs_bufio;
 
wire dqs_ibuf;
wire dqs_idelay;
wire dqs_oe_n_delay;
wire dqs_oe_n_r;
wire dqs_rst_n_delay;
reg dqs_rst_n_r /* synthesis syn_preserve = 1*/;
wire dqs_out;
wire en_dqs_sync /* synthesis syn_keep = 1 */;
 
// for simulation only. Synthesis should ignore this delay
localparam DQS_NET_DELAY = 0.8;
 
assign clk180 = ~clk0;
 
// add delta delay to inputs clocked by clk180 to avoid delta-delay
// simulation issues
assign dqs_rst_n_delay = dqs_rst_n;
assign dqs_oe_n_delay = dqs_oe_n;
 
//***************************************************************************
// DQS input-side resources:
// - IODELAY (pad -> IDELAY)
// - BUFIO (IDELAY -> BUFIO)
//***************************************************************************
 
// Route DQS from PAD to IDELAY
(* IODELAY_GROUP = IODELAY_GRP *) IODELAY #
(
.DELAY_SRC("I"),
.IDELAY_TYPE("VARIABLE"),
.HIGH_PERFORMANCE_MODE(HIGH_PERFORMANCE_MODE),
.IDELAY_VALUE(0),
.ODELAY_VALUE(0)
)
u_idelay_dqs
(
.DATAOUT (dqs_idelay),
.C (clkdiv0),
.CE (dlyce_dqs),
.DATAIN (),
.IDATAIN (dqs_ibuf),
.INC (dlyinc_dqs),
.ODATAIN (),
.RST (dlyrst_dqs),
.T ()
);
 
// From IDELAY to BUFIO
BUFIO u_bufio_dqs
(
.I (dqs_idelay),
.O (dqs_bufio)
);
 
// To model additional delay of DQS BUFIO + gating network
// for behavioral simulation. Make sure to select a delay number smaller
// than half clock cycle (otherwise output will not track input changes
// because of inertial delay). Duplicate to avoid delta delay issues.
assign #(DQS_NET_DELAY) i_delayed_dqs = dqs_bufio;
assign #(DQS_NET_DELAY) delayed_dqs = dqs_bufio;
 
//***************************************************************************
// DQS gate circuit (not supported for all controllers)
//***************************************************************************
 
// Gate routing:
// en_dqs -> IDELAY -> en_dqs_sync -> IDDR.S -> dq_ce ->
// capture IDDR.CE
 
// Delay CE control so that it's in phase with delayed DQS
(* IODELAY_GROUP = IODELAY_GRP *) IODELAY #
(
.DELAY_SRC ("DATAIN"),
.IDELAY_TYPE ("VARIABLE"),
.HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
.IDELAY_VALUE (0),
.ODELAY_VALUE (0)
)
u_iodelay_dq_ce
(
.DATAOUT (en_dqs_sync),
.C (clkdiv0),
.CE (dlyce_gate),
.DATAIN (en_dqs),
.IDATAIN (),
.INC (dlyinc_gate),
.ODATAIN (),
.RST (dlyrst_gate),
.T ()
);
 
// Generate sync'ed CE to DQ IDDR's using an IDDR clocked by DQS
// We could also instantiate a negative-edge SDR flop here
IDDR #
(
.DDR_CLK_EDGE ("OPPOSITE_EDGE"),
.INIT_Q1 (1'b0),
.INIT_Q2 (1'b0),
.SRTYPE ("ASYNC")
)
u_iddr_dq_ce
(
.Q1 (),
.Q2 (dq_ce), // output on falling edge
.C (i_delayed_dqs),
.CE (1'b1),
.D (en_dqs_sync),
.R (1'b0),
.S (en_dqs_sync)
);
 
//***************************************************************************
// DQS output-side resources
//***************************************************************************
 
// synthesis attribute keep of dqs_rst_n_r is "true"
always @(posedge clk180)
dqs_rst_n_r <= dqs_rst_n_delay;
 
ODDR #
(
.SRTYPE("SYNC"),
.DDR_CLK_EDGE("OPPOSITE_EDGE")
)
u_oddr_dqs
(
.Q (dqs_out),
.C (clk180),
.CE (1'b1),
.D1 (dqs_rst_n_r), // keep output deasserted for write preamble
.D2 (1'b0),
.R (1'b0),
.S (1'b0)
);
 
(* IOB = "FORCE" *) FDP u_tri_state_dqs
(
.D (dqs_oe_n_delay),
.Q (dqs_oe_n_r),
.C (clk180),
.PRE (rst0)
) /* synthesis syn_useioff = 1 */;
 
//***************************************************************************
 
// use either single-ended (for DDR1) or differential (for DDR2) DQS input
 
generate
if (DDR_TYPE > 0) begin: gen_dqs_iob_ddr2
IOBUFDS u_iobuf_dqs
(
.O (dqs_ibuf),
.IO (ddr_dqs),
.IOB (ddr_dqs_n),
.I (dqs_out),
.T (dqs_oe_n_r)
);
end else begin: gen_dqs_iob_ddr1
IOBUF u_iobuf_dqs
(
.O (dqs_ibuf),
.IO (ddr_dqs),
.I (dqs_out),
.T (dqs_oe_n_r)
);
end
endgenerate
 
endmodule
/boards/xilinx/ml501/rtl/verilog/xilinx_ddr2/ddr2_top.v
0,0 → 1,278
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007, 2008 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_top.v
// /___/ /\ Date Last Modified: $Date: 2009/01/15 14:22:14 $
// \ \ / \ Date Created: Wed Aug 16 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR2
//Purpose:
// System level module. This level contains just the memory controller.
// This level will be intiantated when the user wants to remove the
// synthesizable test bench, IDELAY control block and the clock
// generation modules.
//Reference:
//Revision History:
// Rev 1.1 - Parameter USE_DM_PORT added. PK. 6/25/08
// Rev 1.2 - Parameter HIGH_PERFORMANCE_MODE added. PK. 7/10/08
// Rev 1.3 - Parameter IODELAY_GRP added. PK. 11/27/08
//*****************************************************************************
 
`timescale 1ns/1ps
 
module ddr2_top #
(
// Following parameters are for 72-bit RDIMM design (for ML561 Reference
// board design). Actual values may be different. Actual parameters values
// are passed from design top module ddr2_mig module. Please refer to
// the ddr2_mig module for actual values.
parameter BANK_WIDTH = 2, // # of memory bank addr bits
parameter CKE_WIDTH = 1, // # of memory clock enable outputs
parameter CLK_WIDTH = 1, // # of clock outputs
parameter COL_WIDTH = 10, // # of memory column bits
parameter CS_NUM = 1, // # of separate memory chip selects
parameter CS_BITS = 0, // set to log2(CS_NUM) (rounded up)
parameter CS_WIDTH = 1, // # of total memory chip selects
parameter USE_DM_PORT = 1, // enable Data Mask (=1 enable)
parameter DM_WIDTH = 9, // # of data mask bits
parameter DQ_WIDTH = 72, // # of data width
parameter DQ_BITS = 7, // set to log2(DQS_WIDTH*DQ_PER_DQS)
parameter DQ_PER_DQS = 8, // # of DQ data bits per strobe
parameter DQS_WIDTH = 9, // # of DQS strobes
parameter DQS_BITS = 4, // set to log2(DQS_WIDTH)
parameter HIGH_PERFORMANCE_MODE = "TRUE", // IODELAY Performance Mode
parameter IODELAY_GRP = "IODELAY_MIG", // IODELAY Group Name
parameter ODT_WIDTH = 1, // # of memory on-die term enables
parameter ROW_WIDTH = 14, // # of memory row & # of addr bits
parameter APPDATA_WIDTH = 144, // # of usr read/write data bus bits
parameter ADDITIVE_LAT = 0, // additive write latency
parameter BURST_LEN = 4, // burst length (in double words)
parameter BURST_TYPE = 0, // burst type (=0 seq; =1 interlved)
parameter CAS_LAT = 5, // CAS latency
parameter ECC_ENABLE = 0, // enable ECC (=1 enable)
parameter ODT_TYPE = 1, // ODT (=0(none),=1(75),=2(150),=3(50))
parameter MULTI_BANK_EN = 1, // enable bank management
parameter TWO_T_TIME_EN = 0, // 2t timing for unbuffered dimms
parameter REDUCE_DRV = 0, // reduced strength mem I/O (=1 yes)
parameter REG_ENABLE = 1, // registered addr/ctrl (=1 yes)
parameter TREFI_NS = 7800, // auto refresh interval (ns)
parameter TRAS = 40000, // active->precharge delay
parameter TRCD = 15000, // active->read/write delay
parameter TRFC = 105000, // ref->ref, ref->active delay
parameter TRP = 15000, // precharge->command delay
parameter TRTP = 7500, // read->precharge delay
parameter TWR = 15000, // used to determine wr->prech
parameter TWTR = 10000, // write->read delay
parameter CLK_PERIOD = 3000, // Core/Mem clk period (in ps)
parameter SIM_ONLY = 0, // = 1 to skip power up delay
parameter DEBUG_EN = 0, // Enable debug signals/controls
parameter FPGA_SPEED_GRADE = 2 // FPGA Speed Grade
)
(
input clk0,
input usr_clk, // jb
input clk90,
input clkdiv0,
input rst0,
input rst90,
input rstdiv0,
input [2:0] app_af_cmd,
input [30:0] app_af_addr,
input app_af_wren,
input app_wdf_wren,
input [APPDATA_WIDTH-1:0] app_wdf_data,
input [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data,
output app_af_afull,
output app_wdf_afull,
output rd_data_valid,
output [APPDATA_WIDTH-1:0] rd_data_fifo_out,
output [1:0] rd_ecc_error,
output phy_init_done,
output [CLK_WIDTH-1:0] ddr2_ck,
output [CLK_WIDTH-1:0] ddr2_ck_n,
output [ROW_WIDTH-1:0] ddr2_a,
output [BANK_WIDTH-1:0] ddr2_ba,
output ddr2_ras_n,
output ddr2_cas_n,
output ddr2_we_n,
output [CS_WIDTH-1:0] ddr2_cs_n,
output [CKE_WIDTH-1:0] ddr2_cke,
output [ODT_WIDTH-1:0] ddr2_odt,
output [DM_WIDTH-1:0] ddr2_dm,
inout [DQS_WIDTH-1:0] ddr2_dqs,
inout [DQS_WIDTH-1:0] ddr2_dqs_n,
inout [DQ_WIDTH-1:0] ddr2_dq,
// Debug signals (optional use)
input dbg_idel_up_all,
input dbg_idel_down_all,
input dbg_idel_up_dq,
input dbg_idel_down_dq,
input dbg_idel_up_dqs,
input dbg_idel_down_dqs,
input dbg_idel_up_gate,
input dbg_idel_down_gate,
input [DQ_BITS-1:0] dbg_sel_idel_dq,
input dbg_sel_all_idel_dq,
input [DQS_BITS:0] dbg_sel_idel_dqs,
input dbg_sel_all_idel_dqs,
input [DQS_BITS:0] dbg_sel_idel_gate,
input dbg_sel_all_idel_gate,
output [3:0] dbg_calib_done,
output [3:0] dbg_calib_err,
output [(6*DQ_WIDTH)-1:0] dbg_calib_dq_tap_cnt,
output [(6*DQS_WIDTH)-1:0] dbg_calib_dqs_tap_cnt,
output [(6*DQS_WIDTH)-1:0] dbg_calib_gate_tap_cnt,
output [DQS_WIDTH-1:0] dbg_calib_rd_data_sel,
output [(5*DQS_WIDTH)-1:0] dbg_calib_rden_dly,
output [(5*DQS_WIDTH)-1:0] dbg_calib_gate_dly
);
 
// memory initialization/control logic
ddr2_mem_if_top #
(
.BANK_WIDTH (BANK_WIDTH),
.CKE_WIDTH (CKE_WIDTH),
.CLK_WIDTH (CLK_WIDTH),
.COL_WIDTH (COL_WIDTH),
.CS_BITS (CS_BITS),
.CS_NUM (CS_NUM),
.CS_WIDTH (CS_WIDTH),
.USE_DM_PORT (USE_DM_PORT),
.DM_WIDTH (DM_WIDTH),
.DQ_WIDTH (DQ_WIDTH),
.DQ_BITS (DQ_BITS),
.DQ_PER_DQS (DQ_PER_DQS),
.DQS_BITS (DQS_BITS),
.DQS_WIDTH (DQS_WIDTH),
.HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
.IODELAY_GRP (IODELAY_GRP),
.ODT_WIDTH (ODT_WIDTH),
.ROW_WIDTH (ROW_WIDTH),
.APPDATA_WIDTH (APPDATA_WIDTH),
.ADDITIVE_LAT (ADDITIVE_LAT),
.BURST_LEN (BURST_LEN),
.BURST_TYPE (BURST_TYPE),
.CAS_LAT (CAS_LAT),
.ECC_ENABLE (ECC_ENABLE),
.MULTI_BANK_EN (MULTI_BANK_EN),
.TWO_T_TIME_EN (TWO_T_TIME_EN),
.ODT_TYPE (ODT_TYPE),
.DDR_TYPE (1),
.REDUCE_DRV (REDUCE_DRV),
.REG_ENABLE (REG_ENABLE),
.TREFI_NS (TREFI_NS),
.TRAS (TRAS),
.TRCD (TRCD),
.TRFC (TRFC),
.TRP (TRP),
.TRTP (TRTP),
.TWR (TWR),
.TWTR (TWTR),
.CLK_PERIOD (CLK_PERIOD),
.SIM_ONLY (SIM_ONLY),
.DEBUG_EN (DEBUG_EN),
.FPGA_SPEED_GRADE (FPGA_SPEED_GRADE)
)
u_mem_if_top
(
.clk0 (clk0),
.usr_clk (usr_clk), // jb
.clk90 (clk90),
.clkdiv0 (clkdiv0),
.rst0 (rst0),
.rst90 (rst90),
.rstdiv0 (rstdiv0),
.app_af_cmd (app_af_cmd),
.app_af_addr (app_af_addr),
.app_af_wren (app_af_wren),
.app_wdf_wren (app_wdf_wren),
.app_wdf_data (app_wdf_data),
.app_wdf_mask_data (app_wdf_mask_data),
.app_af_afull (app_af_afull),
.app_wdf_afull (app_wdf_afull),
.rd_data_valid (rd_data_valid),
.rd_data_fifo_out (rd_data_fifo_out),
.rd_ecc_error (rd_ecc_error),
.phy_init_done (phy_init_done),
.ddr_ck (ddr2_ck),
.ddr_ck_n (ddr2_ck_n),
.ddr_addr (ddr2_a),
.ddr_ba (ddr2_ba),
.ddr_ras_n (ddr2_ras_n),
.ddr_cas_n (ddr2_cas_n),
.ddr_we_n (ddr2_we_n),
.ddr_cs_n (ddr2_cs_n),
.ddr_cke (ddr2_cke),
.ddr_odt (ddr2_odt),
.ddr_dm (ddr2_dm),
.ddr_dqs (ddr2_dqs),
.ddr_dqs_n (ddr2_dqs_n),
.ddr_dq (ddr2_dq),
.dbg_idel_up_all (dbg_idel_up_all),
.dbg_idel_down_all (dbg_idel_down_all),
.dbg_idel_up_dq (dbg_idel_up_dq),
.dbg_idel_down_dq (dbg_idel_down_dq),
.dbg_idel_up_dqs (dbg_idel_up_dqs),
.dbg_idel_down_dqs (dbg_idel_down_dqs),
.dbg_idel_up_gate (dbg_idel_up_gate),
.dbg_idel_down_gate (dbg_idel_down_gate),
.dbg_sel_idel_dq (dbg_sel_idel_dq),
.dbg_sel_all_idel_dq (dbg_sel_all_idel_dq),
.dbg_sel_idel_dqs (dbg_sel_idel_dqs),
.dbg_sel_all_idel_dqs (dbg_sel_all_idel_dqs),
.dbg_sel_idel_gate (dbg_sel_idel_gate),
.dbg_sel_all_idel_gate (dbg_sel_all_idel_gate),
.dbg_calib_done (dbg_calib_done),
.dbg_calib_err (dbg_calib_err),
.dbg_calib_dq_tap_cnt (dbg_calib_dq_tap_cnt),
.dbg_calib_dqs_tap_cnt (dbg_calib_dqs_tap_cnt),
.dbg_calib_gate_tap_cnt (dbg_calib_gate_tap_cnt),
.dbg_calib_rd_data_sel (dbg_calib_rd_data_sel),
.dbg_calib_rden_dly (dbg_calib_rden_dly),
.dbg_calib_gate_dly (dbg_calib_gate_dly)
);
 
endmodule
/boards/xilinx/ml501/rtl/verilog/xilinx_ddr2/ddr2_ctrl.v
0,0 → 1,1239
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007, 2008 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_ctrl.v
// /___/ /\ Date Last Modified: $Date: 2008/12/23 14:26:00 $
// \ \ / \ Date Created: Wed Aug 30 2006
// \___\/\___\
//
//
//Device: Virtex-5
//Design Name: DDR/DDR2
//Purpose:
// This module is the main control logic of the memory interface. All
// commands are issued from here according to the burst, CAS Latency and the
// user commands.
//Reference:
//Revision History:
// Rev 1.2 - Fixed auto refresh to activate bug. KP 11-19-2007
// Rev 1.3 - For Dual Rank parts support CS logic modified. KP. 05/08/08
// Rev 1.4 - AUTO_REFRESH_WAIT state modified for Auto Refresh flag asserted
// immediately after calibration is completed. KP. 07/28/08
// Rev 1.5 - Assignment of bank_valid_r is modified to fix a bug in
// Bank Management logic. PK. 10/29/08
//*****************************************************************************
 
`timescale 1ns/1ps
 
module ddr2_ctrl #
(
// Following parameters are for 72-bit RDIMM design (for ML561 Reference
// board design). Actual values may be different. Actual parameters values
// are passed from design top module ddr2_mig module. Please refer to
// the ddr2_mig module for actual values.
parameter BANK_WIDTH = 2,
parameter COL_WIDTH = 10,
parameter CS_BITS = 0,
parameter CS_NUM = 1,
parameter ROW_WIDTH = 14,
parameter ADDITIVE_LAT = 0,
parameter BURST_LEN = 4,
parameter CAS_LAT = 5,
parameter ECC_ENABLE = 0,
parameter REG_ENABLE = 1,
parameter TREFI_NS = 7800,
parameter TRAS = 40000,
parameter TRCD = 15000,
parameter TRRD = 10000,
parameter TRFC = 105000,
parameter TRP = 15000,
parameter TRTP = 7500,
parameter TWR = 15000,
parameter TWTR = 10000,
parameter CLK_PERIOD = 3000,
parameter MULTI_BANK_EN = 1,
parameter TWO_T_TIME_EN = 0,
parameter DDR_TYPE = 1
)
(
input clk,
input rst,
input [2:0] af_cmd,
input [30:0] af_addr,
input af_empty,
input phy_init_done,
output ctrl_ref_flag,
output ctrl_af_rden,
output reg ctrl_wren,
output reg ctrl_rden,
output [ROW_WIDTH-1:0] ctrl_addr,
output [BANK_WIDTH-1:0] ctrl_ba,
output ctrl_ras_n,
output ctrl_cas_n,
output ctrl_we_n,
output [CS_NUM-1:0] ctrl_cs_n
);
 
// input address split into various ranges
localparam ROW_RANGE_START = COL_WIDTH;
localparam ROW_RANGE_END = ROW_WIDTH + ROW_RANGE_START - 1;
localparam BANK_RANGE_START = ROW_RANGE_END + 1;
localparam BANK_RANGE_END = BANK_WIDTH + BANK_RANGE_START - 1;
localparam CS_RANGE_START = BANK_RANGE_START + BANK_WIDTH;
localparam CS_RANGE_END = CS_BITS + CS_RANGE_START - 1;
// compare address (for determining bank/row hits) split into various ranges
// (compare address doesn't include column bits)
localparam CMP_WIDTH = CS_BITS + BANK_WIDTH + ROW_WIDTH;
localparam CMP_ROW_RANGE_START = 0;
localparam CMP_ROW_RANGE_END = ROW_WIDTH + CMP_ROW_RANGE_START - 1;
localparam CMP_BANK_RANGE_START = CMP_ROW_RANGE_END + 1;
localparam CMP_BANK_RANGE_END = BANK_WIDTH + CMP_BANK_RANGE_START - 1;
localparam CMP_CS_RANGE_START = CMP_BANK_RANGE_END + 1;
localparam CMP_CS_RANGE_END = CS_BITS + CMP_CS_RANGE_START-1;
 
localparam BURST_LEN_DIV2 = BURST_LEN / 2;
localparam OPEN_BANK_NUM = 4;
localparam CS_BITS_FIX = (CS_BITS == 0) ? 1 : CS_BITS;
 
// calculation counters based on clock cycle and memory parameters
// TRAS: ACTIVE->PRECHARGE interval - 2
localparam integer TRAS_CYC = (TRAS + CLK_PERIOD)/CLK_PERIOD;
// TRCD: ACTIVE->READ/WRITE interval - 3 (for DDR2 factor in ADD_LAT)
localparam integer TRRD_CYC = (TRRD + CLK_PERIOD)/CLK_PERIOD;
localparam integer TRCD_CYC = (((TRCD + CLK_PERIOD)/CLK_PERIOD) >
ADDITIVE_LAT )?
((TRCD+CLK_PERIOD)/ CLK_PERIOD) - ADDITIVE_LAT : 0;
// TRFC: REFRESH->REFRESH, REFRESH->ACTIVE interval - 2
localparam integer TRFC_CYC = (TRFC + CLK_PERIOD)/CLK_PERIOD;
// TRP: PRECHARGE->COMMAND interval - 2
// for precharge all add 1 extra clock cycle
localparam integer TRP_CYC = ((TRP + CLK_PERIOD)/CLK_PERIOD) +1;
// TRTP: READ->PRECHARGE interval - 2 (Al + BL/2 + (max (TRTP, 2tck))-2
localparam integer TRTP_TMP_MIN = (((TRTP + CLK_PERIOD)/CLK_PERIOD) >= 2)?
((TRTP + CLK_PERIOD)/CLK_PERIOD) : 2;
localparam integer TRTP_CYC = TRTP_TMP_MIN + ADDITIVE_LAT
+ BURST_LEN_DIV2 - 2;
// TWR: WRITE->PRECHARGE interval - 2
localparam integer WR_LAT = (DDR_TYPE > 0) ? CAS_LAT + ADDITIVE_LAT - 1 : 1;
localparam integer TWR_CYC = ((TWR + CLK_PERIOD)/CLK_PERIOD) +
WR_LAT + BURST_LEN_DIV2 ;
// TWTR: WRITE->READ interval - 3 (for DDR1, TWTR = 2 clks)
// DDR2 = CL-1 + BL/2 +TWTR
localparam integer TWTR_TMP_MIN = (TWTR + CLK_PERIOD)/CLK_PERIOD;
localparam integer TWTR_CYC = (DDR_TYPE > 0) ? (TWTR_TMP_MIN + (CAS_LAT -1)
+ BURST_LEN_DIV2 ): 2;
 
// TRTW: READ->WRITE interval - 3
// DDR1: CL + (BL/2)
// DDR2: (BL/2) + 2. Two more clocks are added to
// the DDR2 counter to account for the delay in
// arrival of the DQS during reads (pcb trace + buffer
// delays + memory parameters).
localparam TRTW_CYC = (DDR_TYPE > 0) ? BURST_LEN_DIV2 + 4 :
(CAS_LAT == 25) ? 2 + BURST_LEN_DIV2 : CAS_LAT + BURST_LEN_DIV2;
 
localparam integer CAS_LAT_RD = (CAS_LAT == 25) ? 2 : CAS_LAT;
 
// Make sure all values >= 0 (some may be = 0)
localparam TRAS_COUNT = (TRAS_CYC > 0) ? TRAS_CYC : 0;
localparam TRCD_COUNT = (TRCD_CYC > 0) ? TRCD_CYC : 0;
localparam TRRD_COUNT = (TRRD_CYC > 0) ? TRRD_CYC : 0;
localparam TRFC_COUNT = (TRFC_CYC > 0) ? TRFC_CYC : 0;
localparam TRP_COUNT = (TRP_CYC > 0) ? TRP_CYC : 0;
localparam TRTP_COUNT = (TRTP_CYC > 0) ? TRTP_CYC : 0;
localparam TWR_COUNT = (TWR_CYC > 0) ? TWR_CYC : 0;
localparam TWTR_COUNT = (TWTR_CYC > 0) ? TWTR_CYC : 0;
localparam TRTW_COUNT = (TRTW_CYC > 0) ? TRTW_CYC : 0;
 
// Auto refresh interval
localparam TREFI_COUNT = ((TREFI_NS * 1000)/CLK_PERIOD) - 1;
 
// memory controller states
localparam CTRL_IDLE = 5'h00;
localparam CTRL_PRECHARGE = 5'h01;
localparam CTRL_PRECHARGE_WAIT = 5'h02;
localparam CTRL_AUTO_REFRESH = 5'h03;
localparam CTRL_AUTO_REFRESH_WAIT = 5'h04;
localparam CTRL_ACTIVE = 5'h05;
localparam CTRL_ACTIVE_WAIT = 5'h06;
localparam CTRL_BURST_READ = 5'h07;
localparam CTRL_READ_WAIT = 5'h08;
localparam CTRL_BURST_WRITE = 5'h09;
localparam CTRL_WRITE_WAIT = 5'h0A;
localparam CTRL_PRECHARGE_WAIT1 = 5'h0B;
 
 
reg [CMP_WIDTH-1:0] act_addr_r;
wire [30:0] af_addr_r;
reg [30:0] af_addr_r1;
reg [30:0] af_addr_r2;
reg [30:0] af_addr_r3;
wire [2:0] af_cmd_r;
reg [2:0] af_cmd_r1;
reg [2:0] af_cmd_r2;
reg af_valid_r;
reg af_valid_r1;
reg af_valid_r2;
reg [CS_BITS_FIX :0] auto_cnt_r;
reg auto_ref_r;
reg [(OPEN_BANK_NUM*CMP_WIDTH)-1:0] bank_cmp_addr_r;
reg [OPEN_BANK_NUM-1:0] bank_hit;
reg [OPEN_BANK_NUM-1:0] bank_hit_r;
reg [OPEN_BANK_NUM-1:0] bank_hit_r1;
reg [OPEN_BANK_NUM-1:0] bank_valid_r;
reg bank_conflict_r;
reg conflict_resolved_r;
reg ctrl_af_rden_r;
reg conflict_detect_r;
wire conflict_detect;
reg cs_change_r;
reg cs_change_sticky_r;
reg [ROW_WIDTH-1:0] ddr_addr_r;
wire [ROW_WIDTH-1:0] ddr_addr_col;
wire [ROW_WIDTH-1:0] ddr_addr_row;
reg [BANK_WIDTH-1:0] ddr_ba_r;
reg ddr_cas_n_r;
reg [CS_NUM-1:0] ddr_cs_n_r;
reg ddr_ras_n_r;
reg ddr_we_n_r;
reg [4:0] next_state;
reg no_precharge_wait_r;
reg no_precharge_r;
reg no_precharge_r1;
reg phy_init_done_r;
reg [4:0] precharge_ok_cnt_r;
reg precharge_ok_r;
reg [4:0] ras_cnt_r;
reg [3:0] rcd_cnt_r;
reg rcd_cnt_ok_r;
reg [2:0] rdburst_cnt_r;
reg rdburst_ok_r;
reg rdburst_rden_ok_r;
reg rd_af_flag_r;
wire rd_flag;
reg rd_flag_r;
reg [4:0] rd_to_wr_cnt_r;
reg rd_to_wr_ok_r;
reg ref_flag_r;
reg [11:0] refi_cnt_r;
reg refi_cnt_ok_r;
reg rst_r
/* synthesis syn_preserve = 1 */;
reg rst_r1
/* synthesis syn_maxfan = 10 */;
reg [7:0] rfc_cnt_r;
reg rfc_ok_r;
reg [3:0] row_miss;
reg [3:0] row_conflict_r;
reg [3:0] rp_cnt_r;
reg rp_cnt_ok_r;
reg [CMP_WIDTH-1:0] sb_open_add_r;
reg [4:0] state_r;
reg [4:0] state_r1;
wire sm_rden;
reg sm_rden_r;
reg [2:0] trrd_cnt_r;
reg trrd_cnt_ok_r;
reg [2:0] two_t_enable_r;
reg [CS_NUM-1:0] two_t_enable_r1;
reg [2:0] wrburst_cnt_r;
reg wrburst_ok_r;
reg wrburst_wren_ok_r;
wire wr_flag;
reg wr_flag_r;
reg [4:0] wr_to_rd_cnt_r;
reg wr_to_rd_ok_r;
 
// XST attributes for local reset "tree"
// synthesis attribute shreg_extract of rst_r is "no";
// synthesis attribute shreg_extract of rst_r1 is "no";
// synthesis attribute equivalent_register_removal of rst_r is "no"
 
//***************************************************************************
 
// sm_rden is used to assert read enable to the address FIFO
assign sm_rden = ((state_r == CTRL_BURST_WRITE) ||
(state_r == CTRL_BURST_READ)) ;
 
// Assert this when approaching refresh and not in an access
reg ref_approaching;
always @(posedge clk)
ref_approaching <= (refi_cnt_r >= (TREFI_COUNT -80)) & ~af_valid_r2;
reg ref_just_happened;
always @(posedge clk)
ref_just_happened <= (refi_cnt_r < 12'h30) & ~af_valid_r2;
 
// assert read flag to the adress FIFO
assign ctrl_af_rden = (sm_rden || rd_af_flag_r) & !(ref_approaching | ref_just_happened);
 
// local reset "tree" for controller logic only. Create this to ease timing
// on reset path. Prohibit equivalent register removal on RST_R to prevent
// "sharing" with other local reset trees (caution: make sure global fanout
// limit is set to large enough value, otherwise SLICES may be used for
// fanout control on RST_R.
always @(posedge clk) begin
rst_r <= rst;
rst_r1 <= rst_r;
end
 
//*****************************************************************
// interpret commands from Command/Address FIFO
//*****************************************************************
 
assign wr_flag = (af_valid_r2) ? ((af_cmd_r2 == 3'b000) ? 1'b1 : 1'b0): 1'b0;
assign rd_flag = (af_valid_r2) ? ((af_cmd_r2 == 3'b001) ? 1'b1 : 1'b0): 1'b0;
 
always @(posedge clk) begin
rd_flag_r <= rd_flag;
wr_flag_r <= wr_flag;
end
 
//////////////////////////////////////////////////
// The data from the address FIFO is fetched and
// stored in two register stages. The data will be
// pulled out of the second register stage whenever
// the state machine can handle new data from the
// address FIFO.
 
// This flag is asserted when there is no
// cmd & address in the pipe. When there is
// valid cmd & addr from the address FIFO the
// af_valid signals will be asserted. This flag will
// be set the cycle af_valid_r is de-asserted.
always @(posedge clk) begin
// for simulation purposes - to force CTRL_AF_RDEN low during reset
if (rst_r1)
rd_af_flag_r <= 1'd0;
else if (rd_af_flag_r) // jb - probably should find a way to stop this toggling all the time
rd_af_flag_r <= 0; // jb
else if((ctrl_af_rden_r) ||
(/*rd_af_flag_r &&*/ (af_valid_r || af_valid_r1))) // Fixed bug where third addresses would get lost (pulled off fifo and then clobbered by other value later, thus ignored/skipped) - just make sure we don't get too excited and pull too many off at once - jb
rd_af_flag_r <= 1'd0;
else if (~af_valid_r1 || ~af_valid_r)
rd_af_flag_r <= 1'd1;
 
end // always @ (posedge clk)
 
 
// First register stage for the cmd & add from the FIFO.
// The af_valid_r signal gives the status of the data
// in this stage. The af_valid_r will be asserted when there
// is valid data. This register stage will be updated
// 1. read to the FIFO and the FIFO not empty
// 2. After write and read states
// 3. The valid signal is not asserted in the last stage.
always @(posedge clk) begin
if (rst_r1)begin
af_valid_r <= 1'd0;
end else begin
if (ctrl_af_rden_r || sm_rden_r || ~af_valid_r1
|| ~af_valid_r2)begin
af_valid_r <= ctrl_af_rden_r;
end
end
end
 
// The output register in the FIFO is used. The addr
// and command are already registered in the FIFO.
assign af_addr_r = af_addr;
assign af_cmd_r = af_cmd;
 
// Second register stage for the cmd & add from the FIFO.
// The af_valid_r1 signal gives the status of the data
// in this stage. The af_valid_r will be asserted when there
// is valid data. This register stage will be updated
// 1. read to the FIFO and the FIFO not empty and there
// is no valid data on this stage
// 2. After write and read states
// 3. The valid signal is not asserted in the last stage.
always@(posedge clk) begin
if (rst_r1)begin
af_valid_r1 <= 1'd0;
af_addr_r1 <= {31{1'bx}};
af_cmd_r1 <= {3{1'bx}};
end else if (~af_valid_r1 || sm_rden_r ||
~af_valid_r2) begin
af_valid_r1 <= af_valid_r;
af_addr_r1 <= af_addr_r;
af_cmd_r1 <= af_cmd_r;
end
end
 
// The state machine uses the address and command in this
// register stage. The data is fetched from the second
// register stage whenever the state machine can accept new
// addr. The conflict flags are also generated based on the
// second register stage and updated when the new address
// is loaded for the state machine.
always@(posedge clk) begin
if (rst_r1)begin
af_valid_r2 <= 1'd0;
af_addr_r2 <= {31{1'bx}};
af_cmd_r2 <= {3{1'bx}};
bank_hit_r <= {OPEN_BANK_NUM{1'bx}};
bank_conflict_r <= 1'bx;
row_conflict_r <= 4'bx;
end else if(sm_rden || ~af_valid_r2)begin
af_valid_r2 <= af_valid_r1;
af_addr_r2 <= af_addr_r1;
af_cmd_r2 <= af_cmd_r1;
if(MULTI_BANK_EN)begin
bank_hit_r <= bank_hit;
row_conflict_r <= row_miss;
bank_conflict_r <= (~(|bank_hit));
end else begin
bank_hit_r <= {OPEN_BANK_NUM{1'b0}};
bank_conflict_r <= 1'd0;
row_conflict_r[0] <= (af_addr_r1[CS_RANGE_END:ROW_RANGE_START]
!= sb_open_add_r[CMP_WIDTH-1:0]);
end
end
end // always@ (posedge clk)
 
//detecting cs change for multi chip select case
generate
if(CS_NUM > 1) begin: gen_cs_change
always @(posedge clk) begin
if(sm_rden || ~af_valid_r2)begin
cs_change_r <= af_addr_r1[CS_RANGE_END:CS_RANGE_START] !=
af_addr_r2[CS_RANGE_END:CS_RANGE_START] ;
cs_change_sticky_r <=
af_addr_r1[CS_RANGE_END:CS_RANGE_START] !=
af_addr_r2[CS_RANGE_END:CS_RANGE_START] ;
end else
cs_change_r <= 1'd0;
end
end // block: gen_cs_change
else begin: gen_cs_0
always @(posedge clk) begin
cs_change_r <= 1'd0;
cs_change_sticky_r <= 1'd0;
end
end
endgenerate
 
assign conflict_detect = (MULTI_BANK_EN) ?
((|(row_conflict_r[3:0] & bank_hit_r[3:0]))
| bank_conflict_r) & af_valid_r2 :
row_conflict_r[0] & af_valid_r2;
 
always @(posedge clk) begin
conflict_detect_r <= conflict_detect;
sm_rden_r <= sm_rden;
af_addr_r3 <= af_addr_r2;
ctrl_af_rden_r <= ctrl_af_rden & ~af_empty;
end
 
// conflict resolved signal. When this signal is asserted
// the conflict is resolved. The address to be compared
// for the conflict_resolved_r will be stored in act_add_r
// when the bank is opened.
always @(posedge clk) begin
conflict_resolved_r <= (act_addr_r ==
af_addr_r2[CS_RANGE_END:ROW_RANGE_START]);
if((state_r == CTRL_ACTIVE))
act_addr_r <= af_addr_r2[CS_RANGE_END:ROW_RANGE_START];
end
 
//***************************************************************************
// Bank management logic
// Semi-hardcoded for now for 4 banks
// will keep multiple banks open if MULTI_BANK_EN is true.
//***************************************************************************
 
genvar bank_i;
generate // if multiple bank option chosen
if(MULTI_BANK_EN) begin: gen_multi_bank_open
 
for (bank_i = 0; bank_i < OPEN_BANK_NUM;
bank_i = bank_i + 1) begin: gen_bank_hit1
// asserted if bank address match + open bank entry is valid
always @(*) begin
bank_hit[bank_i]
= ((bank_cmp_addr_r[(CMP_WIDTH*(bank_i+1))-1:
(CMP_WIDTH*bank_i)+ROW_WIDTH] ==
af_addr_r1[CS_RANGE_END:BANK_RANGE_START]) &&
bank_valid_r[bank_i]);
// asserted if row address match (no check for bank entry valid, rely
// on this term to be used in conjunction with BANK_HIT[])
row_miss[bank_i]
= (bank_cmp_addr_r[(CMP_WIDTH*bank_i)+ROW_WIDTH-1:
(CMP_WIDTH*bank_i)] !=
af_addr_r1[ROW_RANGE_END:ROW_RANGE_START]);
end
end
 
always @(posedge clk) begin
no_precharge_wait_r <= bank_valid_r[3] & bank_conflict_r;
bank_hit_r1 <= bank_hit_r;
end
 
always@(*)
no_precharge_r = ~bank_valid_r[3] & bank_conflict_r;
 
always@(posedge clk)
no_precharge_r1 <= no_precharge_r;
 
 
always @(posedge clk) begin
// Clear all bank valid bits during AR (i.e. since all banks get
// precharged during auto-refresh)
if ((state_r1 == CTRL_AUTO_REFRESH)) begin
bank_valid_r <= {OPEN_BANK_NUM{1'b0}};
bank_cmp_addr_r <= {(OPEN_BANK_NUM*CMP_WIDTH-1){1'b0}};
end else begin
if (state_r1 == CTRL_ACTIVE) begin
// 00 is always going to have the latest bank and row.
bank_cmp_addr_r[CMP_WIDTH-1:0]
<= af_addr_r3[CS_RANGE_END:ROW_RANGE_START];
// This indicates the bank was activated
bank_valid_r[0] <= 1'b1;
 
case ({bank_hit_r1[2:0]})
3'b001: begin
bank_cmp_addr_r[CMP_WIDTH-1:0]
<= af_addr_r3[CS_RANGE_END:ROW_RANGE_START];
// This indicates the bank was activated
bank_valid_r[0] <= 1'b1;
end
3'b010: begin //(b0->b1)
bank_cmp_addr_r[(2*CMP_WIDTH)-1:CMP_WIDTH]
<= bank_cmp_addr_r[CMP_WIDTH-1:0];
bank_valid_r[1] <= bank_valid_r[0];
end
3'b100:begin //(b0->b1, b1->b2)
bank_cmp_addr_r[(2*CMP_WIDTH)-1:CMP_WIDTH]
<= bank_cmp_addr_r[CMP_WIDTH-1:0];
bank_cmp_addr_r[(3*CMP_WIDTH)-1:2*CMP_WIDTH]
<= bank_cmp_addr_r[(2*CMP_WIDTH)-1:CMP_WIDTH];
bank_valid_r[1] <= bank_valid_r[0];
bank_valid_r[2] <= bank_valid_r[1];
end
default: begin //(b0->b1, b1->b2, b2->b3)
bank_cmp_addr_r[(2*CMP_WIDTH)-1:CMP_WIDTH]
<= bank_cmp_addr_r[CMP_WIDTH-1:0];
bank_cmp_addr_r[(3*CMP_WIDTH)-1:2*CMP_WIDTH]
<= bank_cmp_addr_r[(2*CMP_WIDTH)-1:CMP_WIDTH];
bank_cmp_addr_r[(4*CMP_WIDTH)-1:3*CMP_WIDTH]
<= bank_cmp_addr_r[(3*CMP_WIDTH)-1:2*CMP_WIDTH];
bank_valid_r[1] <= bank_valid_r[0];
bank_valid_r[2] <= bank_valid_r[1];
bank_valid_r[3] <= bank_valid_r[2];
end
endcase
end
end
end
end else begin: gen_single_bank_open // single bank option
always @(posedge clk) begin
no_precharge_r <= 1'd0;
no_precharge_r1 <= 1'd0;
no_precharge_wait_r <= 1'd0;
if (rst_r1)
sb_open_add_r <= {CMP_WIDTH{1'b0}};
else if (state_r == CTRL_ACTIVE)
sb_open_add_r <= af_addr_r2[CS_RANGE_END:ROW_RANGE_START];
end
end
endgenerate
 
//***************************************************************************
// Timing counters
//***************************************************************************
 
//*****************************************************************
// Write and read enable generation for PHY
//*****************************************************************
 
// write burst count. Counts from (BL/2 to 1).
// Also logic for controller write enable.
always @(posedge clk) begin
if (state_r == CTRL_BURST_WRITE) begin
wrburst_cnt_r <= BURST_LEN_DIV2;
end else if (wrburst_cnt_r >= 3'd1)
wrburst_cnt_r <= wrburst_cnt_r - 1;
end // always @ (posedge clk)
 
 
always @(posedge clk) begin
if (rst_r1) begin
ctrl_wren <= 1'b0;
end else if (state_r == CTRL_BURST_WRITE) begin
ctrl_wren <= 1'b1;
end else if (wrburst_wren_ok_r)
ctrl_wren <= 1'b0;
end
 
 
always @(posedge clk) begin
if ((state_r == CTRL_BURST_WRITE)
&& (BURST_LEN_DIV2 > 2))
wrburst_ok_r <= 1'd0;
else if ((wrburst_cnt_r <= 3'd3) ||
(BURST_LEN_DIV2 <= 2))
wrburst_ok_r <= 1'b1;
end
 
// flag to check when wrburst count has reached
// a value of 1. This flag is used in the ctrl_wren
// logic
always @(posedge clk) begin
if(wrburst_cnt_r == 3'd2)
wrburst_wren_ok_r <=1'b1;
else
wrburst_wren_ok_r <= 1'b0;
end
 
 
// read burst count. Counts from (BL/2 to 1)
always @(posedge clk) begin
if (state_r == CTRL_BURST_READ) begin
rdburst_cnt_r <= BURST_LEN_DIV2;
end else if (rdburst_cnt_r >= 3'd1)
rdburst_cnt_r <= rdburst_cnt_r - 1;
end // always @ (posedge clk)
 
 
always @(posedge clk) begin
if (rst_r1) begin
ctrl_rden <= 1'b0;
end else if (state_r == CTRL_BURST_READ) begin
ctrl_rden <= 1'b1;
end else if (rdburst_rden_ok_r)
ctrl_rden <= 1'b0;
end
 
// the rd_burst_ok_r signal will be asserted one cycle later
// in multi chip select cases if the back to back read is to
// different chip selects. The cs_changed_sticky_r signal will
// be asserted only for multi chip select cases.
always @(posedge clk) begin
if ((state_r == CTRL_BURST_READ)
&& (BURST_LEN_DIV2 > 2))
rdburst_ok_r <= 1'd0;
else if ((rdburst_cnt_r <=( 3'd3 - cs_change_sticky_r)) ||
(BURST_LEN_DIV2 <= 2))
rdburst_ok_r <= 1'b1;
end
 
// flag to check when rdburst count has reached
// a value of 1. This flag is used in the ctrl_rden
// logic
always @(posedge clk) begin
if (rdburst_cnt_r == 3'd2)
rdburst_rden_ok_r <= 1'b1;
else
rdburst_rden_ok_r <= 1'b0;
end
 
 
//*****************************************************************
// Various delay counters
// The counters are checked for value of <= 3 to determine the
// if the count values are reached during different commands.
// It is checked for 3 because
// 1. The counters are loaded during the state when the command
// state is reached (+1)
// 2. After the <= 3 condition is reached the sm takes two cycles
// to transition to the new command state (+2)
//*****************************************************************
 
// tRP count - precharge command period
always @(posedge clk) begin
if (state_r == CTRL_PRECHARGE)
rp_cnt_r <= TRP_COUNT;
else if (rp_cnt_r != 4'd0)
rp_cnt_r <= rp_cnt_r - 1;
end
 
always @(posedge clk) begin
if (state_r == CTRL_PRECHARGE)
rp_cnt_ok_r <= 1'd0;
else if (rp_cnt_r <= 4'd3)
rp_cnt_ok_r <= 1'd1;
end
 
// tRFC count - refresh-refresh, refresh-active
always @(posedge clk) begin
if (state_r == CTRL_AUTO_REFRESH)
rfc_cnt_r <= TRFC_COUNT;
else if (rfc_cnt_r != 8'd0)
rfc_cnt_r <= rfc_cnt_r - 1;
end
 
always @(posedge clk) begin
if (state_r == CTRL_AUTO_REFRESH)
rfc_ok_r <= 1'b0;
else if(rfc_cnt_r <= 8'd3)
rfc_ok_r <= 1'b1;
end
 
// tRCD count - active to read/write
always @(posedge clk) begin
if (state_r == CTRL_ACTIVE)
rcd_cnt_r <= TRCD_COUNT;
else if (rcd_cnt_r != 4'd0)
rcd_cnt_r <= rcd_cnt_r - 1;
end
 
always @(posedge clk) begin
if ((state_r == CTRL_ACTIVE)
&& (TRCD_COUNT > 2))
rcd_cnt_ok_r <= 1'd0;
else if (rcd_cnt_r <= 4'd3)
rcd_cnt_ok_r <= 1;
end
 
// tRRD count - active to active
always @(posedge clk) begin
if (state_r == CTRL_ACTIVE)
trrd_cnt_r <= TRRD_COUNT;
else if (trrd_cnt_r != 3'd0)
trrd_cnt_r <= trrd_cnt_r - 1;
end
 
always @(posedge clk) begin
if (state_r == CTRL_ACTIVE)
trrd_cnt_ok_r <= 1'd0;
else if (trrd_cnt_r <= 3'd3)
trrd_cnt_ok_r <= 1;
end
 
// tRAS count - active to precharge
always @(posedge clk) begin
if (state_r == CTRL_ACTIVE)
ras_cnt_r <= TRAS_COUNT;
else if (ras_cnt_r != 5'd0)
ras_cnt_r <= ras_cnt_r - 1;
end
 
// counter for write to prcharge
// read to precharge and
// activate to precharge
// precharge_ok_cnt_r is added with trtp count,
// there can be cases where the sm can go from
// activate to read and the act->pre count time
// would not have been satisfied. The rd->pre
// time is very less. wr->pre time is almost the
// same as act-> pre
always @(posedge clk) begin
if (state_r == CTRL_BURST_READ) begin
// assign only if the cnt is < TRTP_COUNT
if (precharge_ok_cnt_r < TRTP_COUNT)
precharge_ok_cnt_r <= TRTP_COUNT;
end else if (state_r == CTRL_BURST_WRITE)
precharge_ok_cnt_r <= TWR_COUNT;
else if (state_r == CTRL_ACTIVE)
precharge_ok_cnt_r <= TRAS_COUNT;
else if (precharge_ok_cnt_r != 5'd0)
precharge_ok_cnt_r <= precharge_ok_cnt_r - 1;
end
 
always @(posedge clk) begin
if ((state_r == CTRL_BURST_READ) ||
(state_r == CTRL_BURST_WRITE)||
(state_r == CTRL_ACTIVE))
precharge_ok_r <= 1'd0;
else if(precharge_ok_cnt_r <= 5'd3)
precharge_ok_r <=1'd1;
end
 
// write to read counter
// write to read includes : write latency + burst time + tWTR
always @(posedge clk) begin
if (rst_r1)
wr_to_rd_cnt_r <= 5'd0;
else if (state_r == CTRL_BURST_WRITE)
wr_to_rd_cnt_r <= (TWTR_COUNT);
else if (wr_to_rd_cnt_r != 5'd0)
wr_to_rd_cnt_r <= wr_to_rd_cnt_r - 1;
end
 
always @(posedge clk) begin
if (state_r == CTRL_BURST_WRITE)
wr_to_rd_ok_r <= 1'd0;
else if (wr_to_rd_cnt_r <= 5'd3)
wr_to_rd_ok_r <= 1'd1;
end
 
// read to write counter
always @(posedge clk) begin
if (rst_r1)
rd_to_wr_cnt_r <= 5'd0;
else if (state_r == CTRL_BURST_READ)
rd_to_wr_cnt_r <= (TRTW_COUNT);
else if (rd_to_wr_cnt_r != 5'd0)
rd_to_wr_cnt_r <= rd_to_wr_cnt_r - 1;
end
 
always @(posedge clk) begin
if (state_r == CTRL_BURST_READ)
rd_to_wr_ok_r <= 1'b0;
else if (rd_to_wr_cnt_r <= 5'd3)
rd_to_wr_ok_r <= 1'b1;
end
 
always @(posedge clk) begin
if(refi_cnt_r == (TREFI_COUNT -1))
refi_cnt_ok_r <= 1'b1;
else
refi_cnt_ok_r <= 1'b0;
end
 
// auto refresh interval counter in refresh_clk domain
always @(posedge clk) begin
if ((rst_r1) || (refi_cnt_ok_r)) begin
refi_cnt_r <= 12'd0;
end else begin
refi_cnt_r <= refi_cnt_r + 1;
end
end // always @ (posedge clk)
 
// auto refresh flag
always @(posedge clk) begin
if (refi_cnt_ok_r) begin
ref_flag_r <= 1'b1;
end else begin
ref_flag_r <= 1'b0;
end
end // always @ (posedge clk)
 
assign ctrl_ref_flag = ref_flag_r;
 
//refresh flag detect
//auto_ref high indicates auto_refresh requirement
//auto_ref is held high until auto refresh command is issued.
always @(posedge clk)begin
if (rst_r1)
auto_ref_r <= 1'b0;
else if (ref_flag_r)
auto_ref_r <= 1'b1;
else if (state_r == CTRL_AUTO_REFRESH)
auto_ref_r <= 1'b0;
end
 
 
// keep track of which chip selects got auto-refreshed (avoid auto-refreshing
// all CS's at once to avoid current spike)
always @(posedge clk)begin
if (rst_r1 || (state_r1 == CTRL_PRECHARGE))
auto_cnt_r <= 'd0;
else if (state_r1 == CTRL_AUTO_REFRESH)
auto_cnt_r <= auto_cnt_r + 1;
end
 
// register for timing purposes. Extra delay doesn't really matter
always @(posedge clk)
phy_init_done_r <= phy_init_done;
 
always @(posedge clk)begin
if (rst_r1) begin
state_r <= CTRL_IDLE;
state_r1 <= CTRL_IDLE;
end else begin
state_r <= next_state;
state_r1 <= state_r;
end
end
 
//***************************************************************************
// main control state machine
//***************************************************************************
 
always @(*) begin
next_state = state_r;
(* full_case, parallel_case *) case (state_r)
CTRL_IDLE: begin
// perform auto refresh as soon as we are done with calibration.
// The calibration logic does not do any refreshes.
if (phy_init_done_r)
next_state = CTRL_AUTO_REFRESH;
end
 
CTRL_PRECHARGE: begin
if (auto_ref_r)
next_state = CTRL_PRECHARGE_WAIT1;
// when precharging an LRU bank, do not have to go to wait state
// since we can't possibly be activating row in same bank next
// disabled for 2t timing. There needs to be a gap between cmds
// in 2t timing
else if (no_precharge_wait_r && !TWO_T_TIME_EN)
next_state = CTRL_ACTIVE;
else
next_state = CTRL_PRECHARGE_WAIT;
end
 
CTRL_PRECHARGE_WAIT:begin
if (rp_cnt_ok_r)begin
if (auto_ref_r)
// precharge again to make sure we close all the banks
next_state = CTRL_PRECHARGE;
else
next_state = CTRL_ACTIVE;
end
end
 
CTRL_PRECHARGE_WAIT1:
if (rp_cnt_ok_r)
next_state = CTRL_AUTO_REFRESH;
 
CTRL_AUTO_REFRESH:
next_state = CTRL_AUTO_REFRESH_WAIT;
 
CTRL_AUTO_REFRESH_WAIT:
//staggering Auto refresh for multi
// chip select designs. The SM waits
// for the rfc time before issuing the
// next auto refresh.
if (auto_cnt_r < (CS_NUM))begin
if (rfc_ok_r )
next_state = CTRL_AUTO_REFRESH;
end else if (rfc_ok_r)begin
if(auto_ref_r)
// MIG 2.3: For deep designs if Auto Refresh
// flag asserted immediately after calibration is completed
next_state = CTRL_PRECHARGE;
else if ( wr_flag || rd_flag)
next_state = CTRL_ACTIVE;
end
 
CTRL_ACTIVE:
next_state = CTRL_ACTIVE_WAIT;
 
CTRL_ACTIVE_WAIT: begin
if (rcd_cnt_ok_r) begin
if ((conflict_detect_r && ~conflict_resolved_r) ||
auto_ref_r) begin
if (no_precharge_r1 && ~auto_ref_r && trrd_cnt_ok_r)
next_state = CTRL_ACTIVE;
else if(precharge_ok_r)
next_state = CTRL_PRECHARGE;
end else if ((wr_flag_r) && (rd_to_wr_ok_r))
next_state = CTRL_BURST_WRITE;
else if ((rd_flag_r)&& (wr_to_rd_ok_r))
next_state = CTRL_BURST_READ;
end
end
 
// beginning of write burst
CTRL_BURST_WRITE: begin
if (BURST_LEN_DIV2 == 1) begin
// special case if BL = 2 (i.e. burst lasts only one clk cycle)
if (wr_flag)
// if we have another non-conflict write command right after the
// current write, then stay in this state
next_state = CTRL_BURST_WRITE;
else
// otherwise, if we're done with this burst, and have no write
// immediately scheduled after this one, wait until write-read
// delay has passed
next_state = CTRL_WRITE_WAIT;
end else
// otherwise BL > 2, and we have at least one more write cycle for
// current burst
next_state = CTRL_WRITE_WAIT;
// continuation of write burst (also covers waiting after write burst
// has completed for write-read delay to pass)
end
 
CTRL_WRITE_WAIT: begin
if ((conflict_detect) || auto_ref_r) begin
if (no_precharge_r && ~auto_ref_r && wrburst_ok_r)
next_state = CTRL_ACTIVE;
else if (precharge_ok_r)
next_state = CTRL_PRECHARGE;
end else if (wrburst_ok_r && wr_flag)
next_state = CTRL_BURST_WRITE;
else if ((rd_flag) && (wr_to_rd_ok_r))
next_state = CTRL_BURST_READ;
end
 
CTRL_BURST_READ: begin
if (BURST_LEN_DIV2 == 1) begin
// special case if BL = 2 (i.e. burst lasts only one clk cycle)
if (rd_flag)
next_state = CTRL_BURST_READ;
else
next_state = CTRL_READ_WAIT;
end else
next_state = CTRL_READ_WAIT;
end
 
CTRL_READ_WAIT: begin
if ((conflict_detect) || auto_ref_r)begin
if (no_precharge_r && ~auto_ref_r && rdburst_ok_r)
next_state = CTRL_ACTIVE;
else if (precharge_ok_r)
next_state = CTRL_PRECHARGE;
// for burst of 4 in multi chip select
// if there is a change in cs wait one cycle before the
// next read command. cs_change_r will be asserted.
end else if (rdburst_ok_r && rd_flag && ~cs_change_r)
next_state = CTRL_BURST_READ;
else if (wr_flag && (rd_to_wr_ok_r))
next_state = CTRL_BURST_WRITE;
end
endcase
end
 
//***************************************************************************
// control signals to memory
//***************************************************************************
 
always @(posedge clk) begin
if ((state_r == CTRL_AUTO_REFRESH) ||
(state_r == CTRL_ACTIVE) ||
(state_r == CTRL_PRECHARGE)) begin
ddr_ras_n_r <= 1'b0;
two_t_enable_r[0] <= 1'b0;
end else begin
if (TWO_T_TIME_EN)
ddr_ras_n_r <= two_t_enable_r[0] ;
else
ddr_ras_n_r <= 1'd1;
two_t_enable_r[0] <= 1'b1;
end
end
 
always @(posedge clk)begin
if ((state_r == CTRL_BURST_WRITE) ||
(state_r == CTRL_BURST_READ) ||
(state_r == CTRL_AUTO_REFRESH)) begin
ddr_cas_n_r <= 1'b0;
two_t_enable_r[1] <= 1'b0;
end else begin
if (TWO_T_TIME_EN)
ddr_cas_n_r <= two_t_enable_r[1];
else
ddr_cas_n_r <= 1'b1;
two_t_enable_r[1] <= 1'b1;
end
end
 
always @(posedge clk) begin
if ((state_r == CTRL_BURST_WRITE) ||
(state_r == CTRL_PRECHARGE)) begin
ddr_we_n_r <= 1'b0;
two_t_enable_r[2] <= 1'b0;
end else begin
if(TWO_T_TIME_EN)
ddr_we_n_r <= two_t_enable_r[2];
else
ddr_we_n_r <= 1'b1;
two_t_enable_r[2] <= 1'b1;
end
end
 
// turn off auto-precharge when issuing commands (A10 = 0)
// mapping the col add for linear addressing.
generate
if (TWO_T_TIME_EN) begin: gen_addr_col_two_t
if (COL_WIDTH == ROW_WIDTH-1) begin: gen_ddr_addr_col_0
assign ddr_addr_col = {af_addr_r3[COL_WIDTH-1:10], 1'b0,
af_addr_r3[9:0]};
end else begin
if (COL_WIDTH > 10) begin: gen_ddr_addr_col_1
assign ddr_addr_col = {{(ROW_WIDTH-COL_WIDTH-1){1'b0}},
af_addr_r3[COL_WIDTH-1:10], 1'b0,
af_addr_r3[9:0]};
end else begin: gen_ddr_addr_col_2
assign ddr_addr_col = {{(ROW_WIDTH-COL_WIDTH-1){1'b0}}, 1'b0,
af_addr_r3[COL_WIDTH-1:0]};
end
end
end else begin: gen_addr_col_one_t
if (COL_WIDTH == ROW_WIDTH-1) begin: gen_ddr_addr_col_0_1
assign ddr_addr_col = {af_addr_r2[COL_WIDTH-1:10], 1'b0,
af_addr_r2[9:0]};
end else begin
if (COL_WIDTH > 10) begin: gen_ddr_addr_col_1_1
assign ddr_addr_col = {{(ROW_WIDTH-COL_WIDTH-1){1'b0}},
af_addr_r2[COL_WIDTH-1:10], 1'b0,
af_addr_r2[9:0]};
end else begin: gen_ddr_addr_col_2_1
assign ddr_addr_col = {{(ROW_WIDTH-COL_WIDTH-1){1'b0}}, 1'b0,
af_addr_r2[COL_WIDTH-1:0]};
end
end
end
endgenerate
 
// Assign address during row activate
generate
if (TWO_T_TIME_EN)
assign ddr_addr_row = af_addr_r3[ROW_RANGE_END:ROW_RANGE_START];
else
assign ddr_addr_row = af_addr_r2[ROW_RANGE_END:ROW_RANGE_START];
endgenerate
 
 
always @(posedge clk)begin
if ((state_r == CTRL_ACTIVE) ||
((state_r1 == CTRL_ACTIVE) && TWO_T_TIME_EN))
ddr_addr_r <= ddr_addr_row;
else if ((state_r == CTRL_BURST_WRITE) ||
(state_r == CTRL_BURST_READ) ||
(((state_r1 == CTRL_BURST_WRITE) ||
(state_r1 == CTRL_BURST_READ)) &&
TWO_T_TIME_EN))
ddr_addr_r <= ddr_addr_col;
else if (((state_r == CTRL_PRECHARGE) ||
((state_r1 == CTRL_PRECHARGE) && TWO_T_TIME_EN))
&& auto_ref_r) begin
// if we're precharging as a result of AUTO-REFRESH, precharge all banks
ddr_addr_r <= {ROW_WIDTH{1'b0}};
ddr_addr_r[10] <= 1'b1;
end else if ((state_r == CTRL_PRECHARGE) ||
((state_r1 == CTRL_PRECHARGE) && TWO_T_TIME_EN))
// if we're precharging to close a specific bank/row, set A10=0
ddr_addr_r <= {ROW_WIDTH{1'b0}};
else
ddr_addr_r <= {ROW_WIDTH{1'bx}};
end
 
always @(posedge clk)begin
// whenever we're precharging, we're either: (1) precharging all banks (in
// which case banks bits are don't care, (2) precharging the LRU bank,
// b/c we've exceeded the limit of # of banks open (need to close the LRU
// bank to make room for a new one), (3) we haven't exceed the maximum #
// of banks open, but we trying to open a different row in a bank that's
// already open
if (((state_r == CTRL_PRECHARGE) ||
((state_r1 == CTRL_PRECHARGE) && TWO_T_TIME_EN)) &&
bank_conflict_r && MULTI_BANK_EN)
// When LRU bank needs to be closed
ddr_ba_r <= bank_cmp_addr_r[(3*CMP_WIDTH)+CMP_BANK_RANGE_END:
(3*CMP_WIDTH)+CMP_BANK_RANGE_START];
else begin
// Either precharge due to refresh or bank hit case
if (TWO_T_TIME_EN)
ddr_ba_r <= af_addr_r3[BANK_RANGE_END:BANK_RANGE_START];
else
ddr_ba_r <= af_addr_r2[BANK_RANGE_END:BANK_RANGE_START];
end
end
 
// chip enable generation logic
generate
// if only one chip select, always assert it after reset
if (CS_BITS == 0) begin: gen_ddr_cs_0
always @(posedge clk)
if (rst_r1)
ddr_cs_n_r[0] <= 1'b1;
else
ddr_cs_n_r[0] <= 1'b0;
// otherwise if we have multiple chip selects
end else begin: gen_ddr_cs_1
if(TWO_T_TIME_EN) begin: gen_2t_cs
always @(posedge clk)
if (rst_r1)
ddr_cs_n_r <= {CS_NUM{1'b1}};
else if ((state_r1 == CTRL_AUTO_REFRESH)) begin
// if auto-refreshing, only auto-refresh one CS at any time (avoid
// beating on the ground plane by refreshing all CS's at same time)
ddr_cs_n_r <= {CS_NUM{1'b1}};
ddr_cs_n_r[auto_cnt_r] <= 1'b0;
end else if (auto_ref_r && (state_r1 == CTRL_PRECHARGE)) begin
ddr_cs_n_r <= {CS_NUM{1'b0}};
end else if ((state_r1 == CTRL_PRECHARGE) && ( bank_conflict_r
&& MULTI_BANK_EN))begin
// precharging the LRU bank
ddr_cs_n_r <= {CS_NUM{1'b1}};
ddr_cs_n_r[bank_cmp_addr_r[(3*CMP_WIDTH)+CMP_CS_RANGE_END:
(3*CMP_WIDTH)+CMP_CS_RANGE_START]] <= 1'b0;
end else begin
// otherwise, check the upper address bits to see which CS to assert
ddr_cs_n_r <= {CS_NUM{1'b1}};
ddr_cs_n_r[af_addr_r3[CS_RANGE_END:CS_RANGE_START]] <= 1'b0;
end // else: !if(((state_r == CTRL_PRECHARGE) ||...
end else begin: gen_1t_cs // block: gen_2t_cs
always @(posedge clk)
if (rst_r1)
ddr_cs_n_r <= {CS_NUM{1'b1}};
else if ((state_r == CTRL_AUTO_REFRESH) ) begin
// if auto-refreshing, only auto-refresh one CS at any time (avoid
// beating on the ground plane by refreshing all CS's at same time)
ddr_cs_n_r <= {CS_NUM{1'b1}};
ddr_cs_n_r[auto_cnt_r] <= 1'b0;
end else if (auto_ref_r && (state_r == CTRL_PRECHARGE) ) begin
ddr_cs_n_r <= {CS_NUM{1'b0}};
end else if ((state_r == CTRL_PRECHARGE) &&
(bank_conflict_r && MULTI_BANK_EN))begin
// precharging the LRU bank
ddr_cs_n_r <= {CS_NUM{1'b1}};
ddr_cs_n_r[bank_cmp_addr_r[(3*CMP_WIDTH)+CMP_CS_RANGE_END:
(3*CMP_WIDTH)+CMP_CS_RANGE_START]] <= 1'b0;
end else begin
// otherwise, check the upper address bits to see which CS to assert
ddr_cs_n_r <= {CS_NUM{1'b1}};
ddr_cs_n_r[af_addr_r2[CS_RANGE_END:CS_RANGE_START]] <= 1'b0;
end // else: !if(((state_r == CTRL_PRECHARGE) ||...
end // block: gen_1t_cs
end
endgenerate
 
// registring the two_t timing enable signal.
// This signal will be asserted (low) when the
// chip select has to be asserted.
always @(posedge clk)begin
if(&two_t_enable_r)
two_t_enable_r1 <= {CS_NUM{1'b1}};
else
two_t_enable_r1 <= {CS_NUM{1'b0}};
end
 
assign ctrl_addr = ddr_addr_r;
assign ctrl_ba = ddr_ba_r;
assign ctrl_ras_n = ddr_ras_n_r;
assign ctrl_cas_n = ddr_cas_n_r;
assign ctrl_we_n = ddr_we_n_r;
assign ctrl_cs_n = (TWO_T_TIME_EN) ?
(ddr_cs_n_r | two_t_enable_r1) :
ddr_cs_n_r;
 
endmodule
 
/boards/xilinx/ml501/rtl/verilog/xilinx_ddr2/ddr2_usr_addr_fifo.v
0,0 → 1,133
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_usr_addr_fifo.v
// /___/ /\ Date Last Modified: $Date: 2008/12/23 14:26:01 $
// \ \ / \ Date Created: Mon Aug 28 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR2
//Purpose:
// This module instantiates the block RAM based FIFO to store the user
// address and the command information. Also calculates potential bank/row
// conflicts by comparing the new address with last address issued.
//Reference:
//Revision History:
//*****************************************************************************
 
`timescale 1ns/1ps
 
module ddr2_usr_addr_fifo #
(
// Following parameters are for 72-bit RDIMM design (for ML561 Reference
// board design). Actual values may be different. Actual parameters values
// are passed from design top module ddr2_mig module. Please refer to
// the ddr2_mig module for actual values.
parameter BANK_WIDTH = 2,
parameter COL_WIDTH = 10,
parameter CS_BITS = 0,
parameter ROW_WIDTH = 14
)
(
input clk0,
input rst0,
input usr_clk,
input [2:0] app_af_cmd,
input [30:0] app_af_addr,
input app_af_wren,
input ctrl_af_rden,
output [2:0] af_cmd,
output [30:0] af_addr,
output af_empty,
output app_af_afull
);
 
wire [35:0] fifo_data_out;
reg rst_r;
 
 
always @(posedge clk0)
rst_r <= rst0;
 
 
//***************************************************************************
 
assign af_cmd = fifo_data_out[33:31];
assign af_addr = fifo_data_out[30:0];
 
//***************************************************************************
 
FIFO36 #
(
.ALMOST_EMPTY_OFFSET (13'h0007),
.ALMOST_FULL_OFFSET (13'h000F),
.DATA_WIDTH (36),
.DO_REG (1),
.EN_SYN ("FALSE"), // changed to FALSE - jb
.FIRST_WORD_FALL_THROUGH ("FALSE")
)
u_af
(
.ALMOSTEMPTY (),
.ALMOSTFULL (app_af_afull),
.DO (fifo_data_out[31:0]),
.DOP (fifo_data_out[35:32]),
.EMPTY (af_empty),
.FULL (),
.RDCOUNT (),
.RDERR (),
.WRCOUNT (),
.WRERR (),
.DI ({app_af_cmd[0],app_af_addr}),
.DIP ({2'b00,app_af_cmd[2:1]}),
.RDCLK (clk0),
.RDEN (ctrl_af_rden),
.RST (rst_r),
//.WRCLK (clk0),
.WRCLK (usr_clk),
.WREN (app_af_wren)
);
 
endmodule
/boards/xilinx/ml501/rtl/verilog/xilinx_ddr2/ddr2_phy_dm_iob.v
0,0 → 1,106
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007, 2008 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_phy_dm_iob.v
// /___/ /\ Date Last Modified: $Date: 2008/12/23 14:26:00 $
// \ \ / \ Date Created: Wed Aug 16 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR2
//Purpose:
// This module places the data mask signals into the IOBs.
//Reference:
//Revision History:
// Rev 1.1 - To fix timing issues with Synplicity 9.6.1, syn_preserve
// attribute added for the instance u_dm_ce. PK. 11/11/08
//*****************************************************************************
 
`timescale 1ns/1ps
 
module ddr2_phy_dm_iob
(
input clk90,
input dm_ce,
input mask_data_rise,
input mask_data_fall,
output ddr_dm
);
 
wire dm_out;
wire dm_ce_r;
 
FDRSE_1 u_dm_ce
(
.Q (dm_ce_r),
.C (clk90),
.CE (1'b1),
.D (dm_ce),
.R (1'b0),
.S (1'b0)
) /* synthesis syn_preserve=1 */;
 
ODDR #
(
.SRTYPE("SYNC"),
.DDR_CLK_EDGE("SAME_EDGE")
)
u_oddr_dm
(
.Q (dm_out),
.C (clk90),
.CE (dm_ce_r),
.D1 (mask_data_rise),
.D2 (mask_data_fall),
.R (1'b0),
.S (1'b0)
);
 
OBUF u_obuf_dm
(
.I (dm_out),
.O (ddr_dm)
);
 
endmodule
/boards/xilinx/ml501/rtl/verilog/xilinx_ddr2/ddr2_phy_write.v
0,0 → 1,442
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007, 2008 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_phy_write.v
// /___/ /\ Date Last Modified: $Date: 2008/12/23 14:26:00 $
// \ \ / \ Date Created: Thu Aug 24 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR2
//Purpose:
//Reference:
// Handles delaying various write control signals appropriately depending
// on CAS latency, additive latency, etc. Also splits the data and mask in
// rise and fall buses.
//Revision History:
// Rev 1.1 - For Dual Rank parts support ODT logic corrected. PK. 08/05/08
//*****************************************************************************
 
`timescale 1ns/1ps
 
module ddr2_phy_write #
(
// Following parameters are for 72-bit RDIMM design (for ML561 Reference
// board design). Actual values may be different. Actual parameters values
// are passed from design top module ddr2_mig module. Please refer to
// the ddr2_mig module for actual values.
parameter DQ_WIDTH = 72,
parameter CS_NUM = 1,
parameter ADDITIVE_LAT = 0,
parameter CAS_LAT = 5,
parameter ECC_ENABLE = 0,
parameter ODT_TYPE = 1,
parameter REG_ENABLE = 1,
parameter DDR_TYPE = 1
)
(
input clk0,
input clk90,
input rst90,
input [(2*DQ_WIDTH)-1:0] wdf_data,
input [(2*DQ_WIDTH/8)-1:0] wdf_mask_data,
input ctrl_wren,
input phy_init_wren,
input phy_init_data_sel,
output reg dm_ce,
output reg [1:0] dq_oe_n,
output reg dqs_oe_n ,
output reg dqs_rst_n ,
output wdf_rden,
output reg [CS_NUM-1:0] odt ,
output [DQ_WIDTH-1:0] wr_data_rise,
output [DQ_WIDTH-1:0] wr_data_fall,
output [(DQ_WIDTH/8)-1:0] mask_data_rise,
output [(DQ_WIDTH/8)-1:0] mask_data_fall
);
 
localparam MASK_WIDTH = DQ_WIDTH/8;
localparam DDR1 = 0;
localparam DDR2 = 1;
localparam DDR3 = 2;
 
// (MIN,MAX) value of WR_LATENCY for DDR1:
// REG_ENABLE = (0,1)
// ECC_ENABLE = (0,1)
// Write latency = 1
// Total: (1,3)
// (MIN,MAX) value of WR_LATENCY for DDR2:
// REG_ENABLE = (0,1)
// ECC_ENABLE = (0,1)
// Write latency = ADDITIVE_CAS + CAS_LAT - 1 = (0,4) + (3,5) - 1 = (2,8)
// ADDITIVE_LAT = (0,4) (JEDEC79-2B)
// CAS_LAT = (3,5) (JEDEC79-2B)
// Total: (2,10)
localparam WR_LATENCY = (DDR_TYPE == DDR3) ?
(ADDITIVE_LAT + (CAS_LAT) + REG_ENABLE ) :
(DDR_TYPE == DDR2) ?
(ADDITIVE_LAT + (CAS_LAT-1) + REG_ENABLE ) :
(1 + REG_ENABLE );
 
// NOTE that ODT timing does not need to be delayed for registered
// DIMM case, since like other control/address signals, it gets
// delayed by one clock cycle at the DIMM
localparam ODT_WR_LATENCY = WR_LATENCY - REG_ENABLE;
 
wire dm_ce_0;
reg dm_ce_r;
wire [1:0] dq_oe_0;
reg [1:0] dq_oe_n_90_r1;
reg [1:0] dq_oe_270;
wire dqs_oe_0;
reg dqs_oe_270;
reg dqs_oe_n_180_r1;
wire dqs_rst_0;
reg dqs_rst_n_180_r1;
reg dqs_rst_270;
reg ecc_dm_error_r;
reg ecc_dm_error_r1;
reg [(DQ_WIDTH-1):0] init_data_f;
reg [(DQ_WIDTH-1):0] init_data_r;
reg [3:0] init_wdf_cnt_r;
wire odt_0;
reg rst90_r /* synthesis syn_maxfan = 10 */;
reg [10:0] wr_stages ;
reg [(2*DQ_WIDTH)-1:0] wdf_data_r;
reg [(2*DQ_WIDTH/8)-1:0] wdf_mask_r;
wire [(2*DQ_WIDTH/8)-1:0] wdf_ecc_mask;
 
reg [(2*DQ_WIDTH/8)-1:0] wdf_mask_r1;
wire wdf_rden_0;
reg calib_rden_90_r;
reg wdf_rden_90_r;
reg wdf_rden_90_r1;
reg wdf_rden_270;
 
always @(posedge clk90)
rst90_r <= rst90;
 
//***************************************************************************
// Analysis of additional pipeline delays:
// 1. dq_oe (DQ 3-state): 1 CLK90 cyc in IOB 3-state FF
// 2. dqs_oe (DQS 3-state): 1 CLK180 cyc in IOB 3-state FF
// 3. dqs_rst (DQS output value reset): 1 CLK180 cyc in FF + 1 CLK180 cyc
// in IOB DDR
// 4. odt (ODT control): 1 CLK0 cyc in IOB FF
// 5. write data (output two cyc after wdf_rden - output of RAMB_FIFO w/
// output register enabled): 2 CLK90 cyc in OSERDES
//***************************************************************************
 
// DQS 3-state must be asserted one extra clock cycle due b/c of write
// pre- and post-amble (extra half clock cycle for each)
assign dqs_oe_0 = wr_stages[WR_LATENCY-1] | wr_stages[WR_LATENCY-2];
 
// same goes for ODT, need to handle both pre- and post-amble (generate
// ODT only for DDR2)
// ODT generation for DDR2 based on write latency. The MIN write
// latency is 2. Based on the write latency ODT is asserted.
generate
if ((DDR_TYPE != DDR1) && (ODT_TYPE > 0))begin: gen_odt_ddr2
if(ODT_WR_LATENCY > 2)
assign odt_0 =
wr_stages[ODT_WR_LATENCY-1] |
wr_stages[ODT_WR_LATENCY-2] |
wr_stages[ODT_WR_LATENCY-3] ;
else
assign odt_0 =
wr_stages[ODT_WR_LATENCY] |
wr_stages[ODT_WR_LATENCY-1] |
wr_stages[ODT_WR_LATENCY-2] ;
end else
assign odt_0 = 1'b0;
endgenerate
 
assign dq_oe_0[0] = wr_stages[WR_LATENCY-1] | wr_stages[WR_LATENCY];
assign dq_oe_0[1] = wr_stages[WR_LATENCY-1] | wr_stages[WR_LATENCY-2];
assign dqs_rst_0 = ~wr_stages[WR_LATENCY-2];
assign dm_ce_0 = wr_stages[WR_LATENCY] | wr_stages[WR_LATENCY-1]
| wr_stages[WR_LATENCY-2];
 
// write data fifo, read flag assertion
generate
if (DDR_TYPE != DDR1) begin: gen_wdf_ddr2
if (WR_LATENCY > 2)
assign wdf_rden_0 = wr_stages[WR_LATENCY-3];
else
assign wdf_rden_0 = wr_stages[WR_LATENCY-2];
end else begin: gen_wdf_ddr1
assign wdf_rden_0 = wr_stages[WR_LATENCY-2];
end
endgenerate
 
// first stage isn't registered
always @(*)
wr_stages[0] = (phy_init_data_sel) ? ctrl_wren : phy_init_wren;
 
always @(posedge clk0) begin
wr_stages[1] <= wr_stages[0];
wr_stages[2] <= wr_stages[1];
wr_stages[3] <= wr_stages[2];
wr_stages[4] <= wr_stages[3];
wr_stages[5] <= wr_stages[4];
wr_stages[6] <= wr_stages[5];
wr_stages[7] <= wr_stages[6];
wr_stages[8] <= wr_stages[7];
wr_stages[9] <= wr_stages[8];
wr_stages[10] <= wr_stages[9];
end
 
// intermediate synchronization to CLK270
always @(negedge clk90) begin
dq_oe_270 <= dq_oe_0;
dqs_oe_270 <= dqs_oe_0;
dqs_rst_270 <= dqs_rst_0;
wdf_rden_270 <= wdf_rden_0;
end
 
// synchronize DQS signals to CLK180
always @(negedge clk0) begin
dqs_oe_n_180_r1 <= ~dqs_oe_270;
dqs_rst_n_180_r1 <= ~dqs_rst_270;
end
 
// All write data-related signals synced to CLK90
always @(posedge clk90) begin
dq_oe_n_90_r1 <= ~dq_oe_270;
wdf_rden_90_r <= wdf_rden_270;
end
 
// generate for wdf_rden and calib rden. These signals
// are asserted based on write latency. For write
// latency of 2, the extra register stage is taken out.
generate
if (WR_LATENCY > 2) begin
always @(posedge clk90) begin
// assert wdf rden only for non calibration opertations
wdf_rden_90_r1 <= wdf_rden_90_r &
phy_init_data_sel;
// rden for calibration
calib_rden_90_r <= wdf_rden_90_r;
end
end else begin
always @(*) begin
wdf_rden_90_r1 = wdf_rden_90_r
& phy_init_data_sel;
calib_rden_90_r = wdf_rden_90_r;
end
end // else: !if(WR_LATENCY > 2)
endgenerate
 
// dm CE signal to stop dm oscilation
always @(negedge clk90)begin
dm_ce_r <= dm_ce_0;
dm_ce <= dm_ce_r;
end
 
// When in ECC mode the upper byte [71:64] will have the
// ECC parity. Mapping the bytes which have valid data
// to the upper byte in ecc mode. Also in ecc mode there
// is an extra register stage to account for timing.
 
genvar mask_i;
generate
if(ECC_ENABLE) begin
for (mask_i = 0; mask_i < (2*DQ_WIDTH)/72;
mask_i = mask_i+1) begin: gen_mask
assign wdf_ecc_mask[((mask_i*9)+9)-1:(mask_i*9)] =
{&wdf_mask_data[(mask_i*8)+(7+mask_i):mask_i*9],
wdf_mask_data[(mask_i*8)+(7+mask_i):mask_i*9]};
end
end
endgenerate
 
generate
if (ECC_ENABLE) begin:gen_ecc_reg
always @(posedge clk90)begin
if(phy_init_data_sel)
wdf_mask_r <= wdf_ecc_mask;
else
wdf_mask_r <= {(2*DQ_WIDTH/8){1'b0}};
end
end else begin
always@(posedge clk90) begin
if (phy_init_data_sel)
wdf_mask_r <= wdf_mask_data;
else
wdf_mask_r <= {(2*DQ_WIDTH/8){1'b0}};
end
end
endgenerate
 
always @(posedge clk90) begin
if(phy_init_data_sel)
wdf_data_r <= wdf_data;
else
wdf_data_r <={init_data_f,init_data_r};
end
 
// Error generation block during simulation.
// Error will be displayed when all the DM
// bits are not zero. The error will be
// displayed only during the start of the sequence
// for errors that are continous over many cycles.
generate
if (ECC_ENABLE) begin: gen_ecc_error
always @(posedge clk90) begin
//synthesis translate_off
wdf_mask_r1 <= wdf_mask_r;
if(DQ_WIDTH > 72)
ecc_dm_error_r
<= (
(~wdf_mask_r1[35] && (|wdf_mask_r1[34:27])) ||
(~wdf_mask_r1[26] && (|wdf_mask_r1[25:18])) ||
(~wdf_mask_r1[17] && (|wdf_mask_r1[16:9])) ||
(~wdf_mask_r1[8] && (|wdf_mask_r1[7:0]))) && phy_init_data_sel;
else
ecc_dm_error_r
<= ((~wdf_mask_r1[17] && (|wdf_mask_r1[16:9])) ||
(~wdf_mask_r1[8] && (|wdf_mask_r1[7:0]))) && phy_init_data_sel;
ecc_dm_error_r1 <= ecc_dm_error_r ;
if (ecc_dm_error_r && ~ecc_dm_error_r1) // assert the error only once.
$display ("ECC DM ERROR. ");
//synthesis translate_on
end
end
endgenerate
 
//***************************************************************************
// State logic to write calibration training patterns
//***************************************************************************
 
always @(posedge clk90) begin
if (rst90_r) begin
init_wdf_cnt_r <= 4'd0;
init_data_r <= {64{1'bx}};
init_data_f <= {64{1'bx}};
end else begin
init_wdf_cnt_r <= init_wdf_cnt_r + calib_rden_90_r;
casex (init_wdf_cnt_r)
// First stage calibration. Pattern (rise/fall) = 1(r)->0(f)
// The rise data and fall data are already interleaved in the manner
// required for data into the WDF write FIFO
4'b00xx: begin
init_data_r <= {DQ_WIDTH{1'b1}};
init_data_f <= {DQ_WIDTH{1'b0}};
end
// Second stage calibration. Pattern = 1(r)->1(f)->0(r)->0(f)
4'b01x0: begin
init_data_r <= {DQ_WIDTH{1'b1}};
init_data_f <= {DQ_WIDTH{1'b1}};
end
4'b01x1: begin
init_data_r <= {DQ_WIDTH{1'b0}};
init_data_f <= {DQ_WIDTH{1'b0}};
end
// MIG 2.1: Changed Stage 3/4 training pattern
// Third and fourth stage calibration patern =
// 11(r)->ee(f)->ee(r)->11(f)-11(r)->ee(f)->ee(r)->11(f)
4'b1000: begin
init_data_r <= {DQ_WIDTH/4{4'h1}};
init_data_f <= {DQ_WIDTH/4{4'hE}};
end
4'b1001: begin
init_data_r <= {DQ_WIDTH/4{4'hE}};
init_data_f <= {DQ_WIDTH/4{4'h1}};
end
4'b1010: begin
init_data_r <= {(DQ_WIDTH/4){4'h1}};
init_data_f <= {(DQ_WIDTH/4){4'hE}};
end
4'b1011: begin
init_data_r <= {(DQ_WIDTH/4){4'hE}};
init_data_f <= {(DQ_WIDTH/4){4'h1}};
end
default: begin
init_data_f <= {(2*DQ_WIDTH){1'bx}};
init_data_r <= {(2*DQ_WIDTH){1'bx}};
end
endcase
end
end
 
//***************************************************************************
 
always @(posedge clk90)
dq_oe_n <= dq_oe_n_90_r1;
 
always @(negedge clk0)
dqs_oe_n <= dqs_oe_n_180_r1;
 
always @(negedge clk0)
dqs_rst_n <= dqs_rst_n_180_r1;
 
// generate for odt. odt is asserted based on
// write latency. For write latency of 2
// the extra register stage is taken out.
generate
if (ODT_WR_LATENCY > 2) begin
always @(posedge clk0) begin
odt <= 'b0;
odt[0] <= odt_0;
end
end else begin
always @ (*) begin
odt = 'b0;
odt[0] = odt_0;
end
end
endgenerate
 
assign wdf_rden = wdf_rden_90_r1;
 
//***************************************************************************
// Format write data/mask: Data is in format: {fall, rise}
//***************************************************************************
 
assign wr_data_rise = wdf_data_r[DQ_WIDTH-1:0];
assign wr_data_fall = wdf_data_r[(2*DQ_WIDTH)-1:DQ_WIDTH];
assign mask_data_rise = wdf_mask_r[MASK_WIDTH-1:0];
assign mask_data_fall = wdf_mask_r[(2*MASK_WIDTH)-1:MASK_WIDTH];
 
endmodule
/boards/xilinx/ml501/rtl/verilog/xilinx_ddr2/xilinx_ddr2.v
0,0 → 1,214
/*
* Wrapper for Xilinx MIG'd DDR2 controller, allowing 3 masters
* to contol the single interface.
*/
 
module xilinx_ddr2
(
// Inputs
input [31:0] wbm0_adr_i,
input [1:0] wbm0_bte_i,
input [2:0] wbm0_cti_i,
input wbm0_cyc_i,
input [31:0] wbm0_dat_i,
input [3:0] wbm0_sel_i,
input wbm0_stb_i,
input wbm0_we_i,
// Outputs
output wbm0_ack_o,
output wbm0_err_o,
output wbm0_rty_o,
output [31:0] wbm0_dat_o,
// Inputs
input [31:0] wbm1_adr_i,
input [1:0] wbm1_bte_i,
input [2:0] wbm1_cti_i,
input wbm1_cyc_i,
input [31:0] wbm1_dat_i,
input [3:0] wbm1_sel_i,
input wbm1_stb_i,
input wbm1_we_i,
// Outputs
output wbm1_ack_o,
output wbm1_err_o,
output wbm1_rty_o,
output [31:0] wbm1_dat_o,
 
 
// Inputs
input [31:0] wbm2_adr_i,
input [1:0] wbm2_bte_i,
input [2:0] wbm2_cti_i,
input wbm2_cyc_i,
input [31:0] wbm2_dat_i,
input [3:0] wbm2_sel_i,
input wbm2_stb_i,
input wbm2_we_i,
// Outputs
output wbm2_ack_o,
output wbm2_err_o,
output wbm2_rty_o,
output [31:0] wbm2_dat_o,
 
input wb_clk,
input wb_rst,
 
output [12:0] ddr2_a,
output [1:0] ddr2_ba,
output ddr2_ras_n,
output ddr2_cas_n,
output ddr2_we_n,
output [1:0] ddr2_cs_n,
output [1:0] ddr2_odt,
output [1:0] ddr2_cke,
output [7:0] ddr2_dm,
inout [63:0] ddr2_dq,
inout [7:0] ddr2_dqs,
inout [7:0] ddr2_dqs_n,
output [1:0] ddr2_ck,
output [1:0] ddr2_ck_n,
 
input ddr2_if_clk,
input clk200,
input ddr2_if_rst
);
 
// Internal wires to actual RAM
wire [31:0] wbs_ram_adr_i;
wire [1:0] wbs_ram_bte_i;
wire [2:0] wbs_ram_cti_i;
wire wbs_ram_cyc_i;
wire [31:0] wbs_ram_dat_i;
wire [3:0] wbs_ram_sel_i;
wire wbs_ram_stb_i;
wire wbs_ram_we_i;
wire wbs_ram_ack_o;
wire [31:0] wbs_ram_dat_o;
 
reg [2:0] input_select, last_selected;
wire arb_for_wbm0, arb_for_wbm1, arb_for_wbm2;
// Wires allowing selection of new input
assign arb_for_wbm0 = (last_selected[1] | last_selected[2] |
!wbm1_cyc_i | !wbm2_cyc_i) & !(|input_select);
assign arb_for_wbm1 = (last_selected[0] | last_selected[2] |
!wbm0_cyc_i | !wbm2_cyc_i) & !(|input_select);
assign arb_for_wbm2 = (last_selected[0] | last_selected[1] |
!wbm0_cyc_i | !wbm1_cyc_i) & !(|input_select);
// Master select logic
always @(posedge wb_clk)
if (wb_rst)
input_select <= 0;
else if ((input_select[0] & !wbm0_cyc_i) | (input_select[1] & !wbm1_cyc_i)
| (input_select[2] & !wbm2_cyc_i))
input_select <= 0;
else if (!(&input_select) & wbm0_cyc_i & arb_for_wbm0)
input_select <= 3'b001;
else if (!(&input_select) & wbm1_cyc_i & arb_for_wbm1)
input_select <= 3'b010;
else if (!(&input_select) & wbm2_cyc_i & arb_for_wbm2)
input_select <= 3'b100;
always @(posedge wb_clk)
if (wb_rst)
last_selected <= 0;
else if (!(&input_select) & wbm0_cyc_i & arb_for_wbm0)
last_selected <= 3'b001;
else if (!(&input_select) & wbm1_cyc_i & arb_for_wbm1)
last_selected <= 3'b010;
else if (!(&input_select) & wbm2_cyc_i & arb_for_wbm2)
last_selected <= 3'b100;
 
// Mux input signals to RAM (default to wbm0)
assign wbs_ram_adr_i = (input_select[2]) ? wbm2_adr_i :
(input_select[1]) ? wbm1_adr_i :
(input_select[0]) ? wbm0_adr_i : 0;
assign wbs_ram_bte_i = (input_select[2]) ? wbm2_bte_i :
(input_select[1]) ? wbm1_bte_i :
(input_select[0]) ? wbm0_bte_i : 0;
assign wbs_ram_cti_i = (input_select[2]) ? wbm2_cti_i :
(input_select[1]) ? wbm1_cti_i :
(input_select[0]) ? wbm0_cti_i : 0;
assign wbs_ram_cyc_i = (input_select[2]) ? wbm2_cyc_i :
(input_select[1]) ? wbm1_cyc_i :
(input_select[0]) ? wbm0_cyc_i : 0;
assign wbs_ram_dat_i = (input_select[2]) ? wbm2_dat_i :
(input_select[1]) ? wbm1_dat_i :
(input_select[0]) ? wbm0_dat_i : 0;
assign wbs_ram_sel_i = (input_select[2]) ? wbm2_sel_i :
(input_select[1]) ? wbm1_sel_i :
(input_select[0]) ? wbm0_sel_i : 0;
assign wbs_ram_stb_i = (input_select[2]) ? wbm2_stb_i :
(input_select[1]) ? wbm1_stb_i :
(input_select[0]) ? wbm0_stb_i : 0;
assign wbs_ram_we_i = (input_select[2]) ? wbm2_we_i :
(input_select[1]) ? wbm1_we_i :
(input_select[0]) ? wbm0_we_i : 0;
 
// Output from RAM, gate the ACK, ERR, RTY signals appropriately
assign wbm0_dat_o = wbs_ram_dat_o;
assign wbm0_ack_o = wbs_ram_ack_o & input_select[0];
assign wbm0_err_o = 0;
assign wbm0_rty_o = 0;
 
assign wbm1_dat_o = wbs_ram_dat_o;
assign wbm1_ack_o = wbs_ram_ack_o & input_select[1];
assign wbm1_err_o = 0;
assign wbm1_rty_o = 0;
 
assign wbm2_dat_o = wbs_ram_dat_o;
assign wbm2_ack_o = wbs_ram_ack_o & input_select[2];
assign wbm2_err_o = 0;
assign wbm2_rty_o = 0;
 
 
xilinx_ddr2_if xilinx_ddr2_if0
(
 
.wb_dat_o (wbs_ram_dat_o),
.wb_ack_o (wbs_ram_ack_o),
.wb_adr_i (wbs_ram_adr_i[31:0]),
.wb_stb_i (wbs_ram_stb_i),
.wb_cyc_i (wbs_ram_cyc_i),
.wb_we_i (wbs_ram_we_i),
.wb_sel_i (wbs_ram_sel_i[3:0]),
.wb_dat_i (wbs_ram_dat_i[31:0]),
 
.ddr2_a (ddr2_a[12:0]),
.ddr2_ba (ddr2_ba[1:0]),
.ddr2_ras_n (ddr2_ras_n),
.ddr2_cas_n (ddr2_cas_n),
.ddr2_we_n (ddr2_we_n),
.ddr2_cs_n (ddr2_cs_n),
.ddr2_odt (ddr2_odt),
.ddr2_cke (ddr2_cke),
.ddr2_dm (ddr2_dm[7:0]),
.ddr2_ck (ddr2_ck[1:0]),
.ddr2_ck_n (ddr2_ck_n[1:0]),
.ddr2_dq (ddr2_dq[63:0]),
.ddr2_dqs (ddr2_dqs[7:0]),
.ddr2_dqs_n (ddr2_dqs_n[7:0]),
 
.ddr2_if_clk (ddr2_if_clk),
.idly_clk_200 (clk200),
.ddr2_if_rst (ddr2_if_rst),
.wb_clk (wb_clk),
.wb_rst (wb_rst));
 
 
endmodule
 
/boards/xilinx/ml501/rtl/verilog/xilinx_ddr2/xilinx_ddr2_if_cache.v
0,0 → 1,152
/*******************************************************************************
* This file is owned and controlled by Xilinx and must be used *
* solely for design, simulation, implementation and creation of *
* design files limited to Xilinx devices or technologies. Use *
* with non-Xilinx devices or technologies is expressly prohibited *
* and immediately terminates your license. *
* *
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" *
* SOLELY FOR USE IN DEVELOPING PROGRAMS AND SOLUTIONS FOR *
* XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION *
* AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION *
* OR STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS *
* IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT, *
* AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE *
* FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY *
* WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE *
* IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR *
* REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF *
* INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *
* FOR A PARTICULAR PURPOSE. *
* *
* Xilinx products are not intended for use in life support *
* appliances, devices, or systems. Use in such applications are *
* expressly prohibited. *
* *
* (c) Copyright 1995-2009 Xilinx, Inc. *
* All rights reserved. *
*******************************************************************************/
// The synthesis directives "translate_off/translate_on" specified below are
// supported by Xilinx, Mentor Graphics and Synplicity synthesis
// tools. Ensure they are correct for your synthesis tool(s).
 
// You must compile the wrapper file xilinx_ddr2_if_cache.v when simulating
// the core, xilinx_ddr2_if_cache. When compiling the wrapper file, be sure to
// reference the XilinxCoreLib Verilog simulation library. For detailed
// instructions, please refer to the "CORE Generator Help".
 
`timescale 1ns/1ps
 
module xilinx_ddr2_if_cache(
clka,
ena,
wea,
addra,
dina,
douta,
clkb,
enb,
web,
addrb,
dinb,
doutb);
 
 
input clka;
input ena;
input [3 : 0] wea;
input [11 : 0] addra;
input [31 : 0] dina;
output [31 : 0] douta;
input clkb;
input enb;
input [15 : 0] web;
input [9 : 0] addrb;
input [127 : 0] dinb;
output [127 : 0] doutb;
 
// synthesis translate_off
 
BLK_MEM_GEN_V3_1 #(
.C_ADDRA_WIDTH(12),
.C_ADDRB_WIDTH(10),
.C_ALGORITHM(1),
.C_BYTE_SIZE(8),
.C_COMMON_CLK(0),
.C_DEFAULT_DATA("0"),
.C_DISABLE_WARN_BHV_COLL(0),
.C_DISABLE_WARN_BHV_RANGE(0),
.C_FAMILY("virtex5"),
.C_HAS_ENA(1),
.C_HAS_ENB(1),
.C_HAS_INJECTERR(0),
.C_HAS_MEM_OUTPUT_REGS_A(0),
.C_HAS_MEM_OUTPUT_REGS_B(0),
.C_HAS_MUX_OUTPUT_REGS_A(0),
.C_HAS_MUX_OUTPUT_REGS_B(0),
.C_HAS_REGCEA(0),
.C_HAS_REGCEB(0),
.C_HAS_RSTA(0),
.C_HAS_RSTB(0),
.C_INITA_VAL("0"),
.C_INITB_VAL("0"),
.C_INIT_FILE_NAME("no_coe_file_loaded"),
.C_LOAD_INIT_FILE(0),
.C_MEM_TYPE(2),
.C_MUX_PIPELINE_STAGES(0),
.C_PRIM_TYPE(1),
.C_READ_DEPTH_A(4096),
.C_READ_DEPTH_B(1024),
.C_READ_WIDTH_A(32),
.C_READ_WIDTH_B(128),
.C_RSTRAM_A(0),
.C_RSTRAM_B(0),
.C_RST_PRIORITY_A("CE"),
.C_RST_PRIORITY_B("CE"),
.C_RST_TYPE("SYNC"),
.C_SIM_COLLISION_CHECK("ALL"),
.C_USE_BYTE_WEA(1),
.C_USE_BYTE_WEB(1),
.C_USE_DEFAULT_DATA(0),
.C_USE_ECC(0),
.C_WEA_WIDTH(4),
.C_WEB_WIDTH(16),
.C_WRITE_DEPTH_A(4096),
.C_WRITE_DEPTH_B(1024),
.C_WRITE_MODE_A("WRITE_FIRST"),
.C_WRITE_MODE_B("WRITE_FIRST"),
.C_WRITE_WIDTH_A(32),
.C_WRITE_WIDTH_B(128),
.C_XDEVICEFAMILY("virtex5"))
inst (
.CLKA(clka),
.ENA(ena),
.WEA(wea),
.ADDRA(addra),
.DINA(dina),
.DOUTA(douta),
.CLKB(clkb),
.ENB(enb),
.WEB(web),
.ADDRB(addrb),
.DINB(dinb),
.DOUTB(doutb),
.RSTA(),
.REGCEA(),
.RSTB(),
.REGCEB(),
.INJECTSBITERR(),
.INJECTDBITERR(),
.SBITERR(),
.DBITERR(),
.RDADDRECC());
 
 
// synthesis translate_on
 
// XST black box declaration
// box_type "black_box"
// synthesis attribute box_type of ml501_ddr2_if_cache is "black_box"
 
endmodule
 
/boards/xilinx/ml501/rtl/verilog/xilinx_ddr2/ddr2_mig.v
0,0 → 1,618
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007, 2008 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_mig.v
// /___/ /\ Date Last Modified: $Date: 2009/02/03 18:46:29 $
// \ \ / \ Date Created: Wed Aug 16 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR2
//Purpose:
// Top-level module. Simple model for what the user might use
// Typically, the user will only instantiate MEM_INTERFACE_TOP in their
// code, and generate all backend logic (test bench) separately.
// In addition to the memory controller, the module instantiates:
// 1. Clock generation/distribution, reset logic
// 2. IDELAY control block
//Reference:
//Revision History:
// Rev 1.1 - Parameter USE_DM_PORT added. PK. 6/25/08
// Rev 1.2 - Parameter HIGH_PERFORMANCE_MODE added. PK. 7/10/08
// Rev 1.3 - Parameter IODELAY_GRP added. PK. 11/27/08
//*****************************************************************************
 
`timescale 1ns/1ps
 
(* X_CORE_INFO = "mig_v3_0_ddr2_v5, Coregen 11.1" , CORE_GENERATION_INFO = "ddr2_v5,mig_v3_0,{component_name=ddr2_mig, BANK_WIDTH=2, CKE_WIDTH=1, CLK_WIDTH=2, COL_WIDTH=10, CS_NUM=1, CS_WIDTH=1, DM_WIDTH=8, DQ_WIDTH=64, DQ_PER_DQS=8, DQS_WIDTH=8, ODT_WIDTH=1, ROW_WIDTH=13, ADDITIVE_LAT=0, BURST_LEN=4, BURST_TYPE=0, CAS_LAT=4, ECC_ENABLE=0, MULTI_BANK_EN=1, TWO_T_TIME_EN=1, ODT_TYPE=1, REDUCE_DRV=0, REG_ENABLE=0, TREFI_NS=7800, TRAS=40000, TRCD=15000, TRFC=105000, TRP=15000, TRTP=7500, TWR=15000, TWTR=7500, DDR2_CLK_PERIOD=3750, RST_ACT_LOW=1}" *)
module ddr2_mig #
(
parameter BANK_WIDTH = 2,
// # of memory bank addr bits.
parameter CKE_WIDTH = 1,
// # of memory clock enable outputs.
parameter CLK_WIDTH = 2,
// # of clock outputs.
parameter COL_WIDTH = 10,
// # of memory column bits.
parameter CS_NUM = 1,
// # of separate memory chip selects.
parameter CS_WIDTH = 1,
// # of total memory chip selects.
parameter CS_BITS = 0,
// set to log2(CS_NUM) (rounded up).
parameter DM_WIDTH = 8,
// # of data mask bits.
parameter DQ_WIDTH = 64,
// # of data width.
parameter DQ_PER_DQS = 8,
// # of DQ data bits per strobe.
parameter DQS_WIDTH = 8,
// # of DQS strobes.
parameter DQ_BITS = 6,
// set to log2(DQS_WIDTH*DQ_PER_DQS).
parameter DQS_BITS = 3,
// set to log2(DQS_WIDTH).
parameter ODT_WIDTH = 1,
// # of memory on-die term enables.
parameter ROW_WIDTH = 13,
// # of memory row and # of addr bits.
parameter ADDITIVE_LAT = 0,
// additive write latency.
parameter BURST_LEN = 4,
// burst length (in double words).
parameter BURST_TYPE = 0,
// burst type (=0 seq; =1 interleaved).
parameter CAS_LAT = 4,
// CAS latency.
parameter ECC_ENABLE = 0,
// enable ECC (=1 enable).
parameter APPDATA_WIDTH = 128,
// # of usr read/write data bus bits.
parameter MULTI_BANK_EN = 1,
// Keeps multiple banks open. (= 1 enable).
parameter TWO_T_TIME_EN = 1,
// 2t timing for unbuffered dimms.
parameter ODT_TYPE = 1,
// ODT (=0(none),=1(75),=2(150),=3(50)).
parameter REDUCE_DRV = 0,
// reduced strength mem I/O (=1 yes).
parameter REG_ENABLE = 0,
// registered addr/ctrl (=1 yes).
parameter TREFI_NS = 7800,
// auto refresh interval (ns).
parameter TRAS = 40000,
// active->precharge delay.
parameter TRCD = 15000,
// active->read/write delay.
parameter TRFC = 105000,
// refresh->refresh, refresh->active delay.
parameter TRP = 15000,
// precharge->command delay.
parameter TRTP = 7500,
// read->precharge delay.
parameter TWR = 15000,
// used to determine write->precharge.
parameter TWTR = 7500,
// write->read delay.
parameter HIGH_PERFORMANCE_MODE = "TRUE",
// # = TRUE, the IODELAY performance mode is set
// to high.
// # = FALSE, the IODELAY performance mode is set
// to low.
parameter SIM_ONLY = 0,
// = 1 to skip SDRAM power up delay.
parameter DEBUG_EN = 0,
// Enable debug signals/controls.
// When this parameter is changed from 0 to 1,
// make sure to uncomment the coregen commands
// in ise_flow.bat or create_ise.bat files in
// par folder.
parameter CLK_PERIOD = 3750,
// Core/Memory clock period (in ps).
parameter CLK_TYPE = "SINGLE_ENDED",
// # = "DIFFERENTIAL " ->; Differential input clocks ,
// # = "SINGLE_ENDED" -> Single ended input clocks.
parameter DLL_FREQ_MODE = "HIGH",
// DCM Frequency range.
parameter RST_ACT_LOW = 1
// =1 for active low reset, =0 for active high.
)
(
inout [DQ_WIDTH-1:0] ddr2_dq,
output [ROW_WIDTH-1:0] ddr2_a,
output [BANK_WIDTH-1:0] ddr2_ba,
output ddr2_ras_n,
output ddr2_cas_n,
output ddr2_we_n,
output [CS_WIDTH-1:0] ddr2_cs_n,
output [ODT_WIDTH-1:0] ddr2_odt,
output [CKE_WIDTH-1:0] ddr2_cke,
output [DM_WIDTH-1:0] ddr2_dm,
input sys_clk,
input idly_clk_200,
input sys_rst_n,
output phy_init_done,
output rst0_tb,
output clk0_tb,
input usr_clk, // jb
output app_wdf_afull,
output app_af_afull,
output rd_data_valid,
input app_wdf_wren,
input app_af_wren,
input [30:0] app_af_addr,
input [2:0] app_af_cmd,
output [(APPDATA_WIDTH)-1:0] rd_data_fifo_out,
input [(APPDATA_WIDTH)-1:0] app_wdf_data,
input [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data,
inout [DQS_WIDTH-1:0] ddr2_dqs,
inout [DQS_WIDTH-1:0] ddr2_dqs_n,
output [CLK_WIDTH-1:0] ddr2_ck,
output [CLK_WIDTH-1:0] ddr2_ck_n
);
 
//***************************************************************************
// IODELAY Group Name: Replication and placement of IDELAYCTRLs will be
// handled automatically by software tools if IDELAYCTRLs have same refclk,
// reset and rdy nets. Designs with a unique RESET will commonly create a
// unique RDY. Constraint IODELAY_GROUP is associated to a set of IODELAYs
// with an IDELAYCTRL. The parameter IODELAY_GRP value can be any string.
//***************************************************************************
 
localparam IODELAY_GRP = "IODELAY_MIG";
initial
$display("Xilinx DDR2 MIGed controller at %m\n");
 
 
 
wire sys_clk_p;
wire sys_clk_n;
wire clk200_p;
wire clk200_n;
wire rst0;
wire rst90;
wire rstdiv0;
wire rst200;
wire clk0;
wire clk90;
wire clkdiv0;
wire clk200;
wire idelay_ctrl_rdy;
 
 
//Debug signals
 
 
wire [3:0] dbg_calib_done;
wire [3:0] dbg_calib_err;
wire [(6*DQ_WIDTH)-1:0] dbg_calib_dq_tap_cnt;
wire [(6*DQS_WIDTH)-1:0] dbg_calib_dqs_tap_cnt;
wire [(6*DQS_WIDTH)-1:0] dbg_calib_gate_tap_cnt;
wire [DQS_WIDTH-1:0] dbg_calib_rd_data_sel;
wire [(5*DQS_WIDTH)-1:0] dbg_calib_rden_dly;
wire [(5*DQS_WIDTH)-1:0] dbg_calib_gate_dly;
wire dbg_idel_up_all;
wire dbg_idel_down_all;
wire dbg_idel_up_dq;
wire dbg_idel_down_dq;
wire dbg_idel_up_dqs;
wire dbg_idel_down_dqs;
wire dbg_idel_up_gate;
wire dbg_idel_down_gate;
wire [DQ_BITS-1:0] dbg_sel_idel_dq;
wire dbg_sel_all_idel_dq;
wire [DQS_BITS:0] dbg_sel_idel_dqs;
wire dbg_sel_all_idel_dqs;
wire [DQS_BITS:0] dbg_sel_idel_gate;
wire dbg_sel_all_idel_gate;
 
 
// Debug signals (optional use)
 
//***********************************
// PHY Debug Port demo
//***********************************
wire [35:0] cs_control0;
wire [35:0] cs_control1;
wire [35:0] cs_control2;
wire [35:0] cs_control3;
wire [191:0] vio0_in;
wire [95:0] vio1_in;
wire [99:0] vio2_in;
wire [31:0] vio3_out;
 
 
 
 
//***************************************************************************
 
assign rst0_tb = rst0;
assign clk0_tb = clk0;
assign sys_clk_p = 1'b1;
assign sys_clk_n = 1'b0;
assign clk200_p = 1'b1;
assign clk200_n = 1'b0;
 
ddr2_idelay_ctrl #
(
.IODELAY_GRP (IODELAY_GRP)
)
u_ddr2_idelay_ctrl
(
.rst200 (rst200),
.clk200 (clk200),
.idelay_ctrl_rdy (idelay_ctrl_rdy)
);
 
ddr2_infrastructure #
(
.CLK_PERIOD (CLK_PERIOD),
.CLK_TYPE (CLK_TYPE),
.DLL_FREQ_MODE (DLL_FREQ_MODE),
.RST_ACT_LOW (RST_ACT_LOW)
)
u_ddr2_infrastructure
(
.sys_clk_p (sys_clk_p),
.sys_clk_n (sys_clk_n),
.sys_clk (sys_clk),
.clk200_p (clk200_p),
.clk200_n (clk200_n),
.idly_clk_200 (idly_clk_200),
.sys_rst_n (sys_rst_n),
.rst0 (rst0),
.rst90 (rst90),
.rstdiv0 (rstdiv0),
.rst200 (rst200),
.clk0 (clk0),
.clk90 (clk90),
.clkdiv0 (clkdiv0),
.clk200 (clk200),
.idelay_ctrl_rdy (idelay_ctrl_rdy)
);
 
ddr2_top #
(
.BANK_WIDTH (BANK_WIDTH),
.CKE_WIDTH (CKE_WIDTH),
.CLK_WIDTH (CLK_WIDTH),
.COL_WIDTH (COL_WIDTH),
.CS_NUM (CS_NUM),
.CS_WIDTH (CS_WIDTH),
.CS_BITS (CS_BITS),
.DM_WIDTH (DM_WIDTH),
.DQ_WIDTH (DQ_WIDTH),
.DQ_PER_DQS (DQ_PER_DQS),
.DQS_WIDTH (DQS_WIDTH),
.DQ_BITS (DQ_BITS),
.DQS_BITS (DQS_BITS),
.ODT_WIDTH (ODT_WIDTH),
.ROW_WIDTH (ROW_WIDTH),
.ADDITIVE_LAT (ADDITIVE_LAT),
.BURST_LEN (BURST_LEN),
.BURST_TYPE (BURST_TYPE),
.CAS_LAT (CAS_LAT),
.ECC_ENABLE (ECC_ENABLE),
.APPDATA_WIDTH (APPDATA_WIDTH),
.MULTI_BANK_EN (MULTI_BANK_EN),
.TWO_T_TIME_EN (TWO_T_TIME_EN),
.ODT_TYPE (ODT_TYPE),
.REDUCE_DRV (REDUCE_DRV),
.REG_ENABLE (REG_ENABLE),
.TREFI_NS (TREFI_NS),
.TRAS (TRAS),
.TRCD (TRCD),
.TRFC (TRFC),
.TRP (TRP),
.TRTP (TRTP),
.TWR (TWR),
.TWTR (TWTR),
.HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
.IODELAY_GRP (IODELAY_GRP),
.SIM_ONLY (SIM_ONLY),
.DEBUG_EN (DEBUG_EN),
.CLK_PERIOD (CLK_PERIOD),
.FPGA_SPEED_GRADE (1),
.USE_DM_PORT (1)
)
u_ddr2_top_0
(
.ddr2_dq (ddr2_dq),
.ddr2_a (ddr2_a),
.ddr2_ba (ddr2_ba),
.ddr2_ras_n (ddr2_ras_n),
.ddr2_cas_n (ddr2_cas_n),
.ddr2_we_n (ddr2_we_n),
.ddr2_cs_n (ddr2_cs_n),
.ddr2_odt (ddr2_odt),
.ddr2_cke (ddr2_cke),
.ddr2_dm (ddr2_dm),
.phy_init_done (phy_init_done),
.rst0 (rst0),
.rst90 (rst90),
.rstdiv0 (rstdiv0),
.clk0 (clk0),
.usr_clk (usr_clk), // jb
.clk90 (clk90),
.clkdiv0 (clkdiv0),
.app_wdf_afull (app_wdf_afull),
.app_af_afull (app_af_afull),
.rd_data_valid (rd_data_valid),
.app_wdf_wren (app_wdf_wren),
.app_af_wren (app_af_wren),
.app_af_addr (app_af_addr),
.app_af_cmd (app_af_cmd),
.rd_data_fifo_out (rd_data_fifo_out),
.app_wdf_data (app_wdf_data),
.app_wdf_mask_data (app_wdf_mask_data),
.ddr2_dqs (ddr2_dqs),
.ddr2_dqs_n (ddr2_dqs_n),
.ddr2_ck (ddr2_ck),
.rd_ecc_error (),
.ddr2_ck_n (ddr2_ck_n),
 
.dbg_calib_done (dbg_calib_done),
.dbg_calib_err (dbg_calib_err),
.dbg_calib_dq_tap_cnt (dbg_calib_dq_tap_cnt),
.dbg_calib_dqs_tap_cnt (dbg_calib_dqs_tap_cnt),
.dbg_calib_gate_tap_cnt (dbg_calib_gate_tap_cnt),
.dbg_calib_rd_data_sel (dbg_calib_rd_data_sel),
.dbg_calib_rden_dly (dbg_calib_rden_dly),
.dbg_calib_gate_dly (dbg_calib_gate_dly),
.dbg_idel_up_all (dbg_idel_up_all),
.dbg_idel_down_all (dbg_idel_down_all),
.dbg_idel_up_dq (dbg_idel_up_dq),
.dbg_idel_down_dq (dbg_idel_down_dq),
.dbg_idel_up_dqs (dbg_idel_up_dqs),
.dbg_idel_down_dqs (dbg_idel_down_dqs),
.dbg_idel_up_gate (dbg_idel_up_gate),
.dbg_idel_down_gate (dbg_idel_down_gate),
.dbg_sel_idel_dq (dbg_sel_idel_dq),
.dbg_sel_all_idel_dq (dbg_sel_all_idel_dq),
.dbg_sel_idel_dqs (dbg_sel_idel_dqs),
.dbg_sel_all_idel_dqs (dbg_sel_all_idel_dqs),
.dbg_sel_idel_gate (dbg_sel_idel_gate),
.dbg_sel_all_idel_gate (dbg_sel_all_idel_gate)
);
 
//*****************************************************************
// Hooks to prevent sim/syn compilation errors (mainly for VHDL - but
// keep it also in Verilog version of code) w/ floating inputs if
// DEBUG_EN = 0.
//*****************************************************************
 
generate
if (DEBUG_EN == 0) begin: gen_dbg_tie_off
assign dbg_idel_up_all = 'b0;
assign dbg_idel_down_all = 'b0;
assign dbg_idel_up_dq = 'b0;
assign dbg_idel_down_dq = 'b0;
assign dbg_idel_up_dqs = 'b0;
assign dbg_idel_down_dqs = 'b0;
assign dbg_idel_up_gate = 'b0;
assign dbg_idel_down_gate = 'b0;
assign dbg_sel_idel_dq = 'b0;
assign dbg_sel_all_idel_dq = 'b0;
assign dbg_sel_idel_dqs = 'b0;
assign dbg_sel_all_idel_dqs = 'b0;
assign dbg_sel_idel_gate = 'b0;
assign dbg_sel_all_idel_gate = 'b0;
end else begin: gen_dbg_enable
`ifdef XILINX_DDR2_CHIPSCOPE
//*****************************************************************
// PHY Debug Port example - see MIG User's Guide, XAPP858 or
// Answer Record 29443
// This logic supports up to 32 DQ and 8 DQS I/O
// NOTES:
// 1. PHY Debug Port demo connects to 4 VIO modules:
// - 3 VIO modules with only asynchronous inputs
// * Monitor IDELAY taps for DQ, DQS, DQS Gate
// * Calibration status
// - 1 VIO module with synchronous outputs
// * Allow dynamic adjustment o f IDELAY taps
// 2. User may need to modify this code to incorporate other
// chipscope-related modules in their larger design (e.g.
// if they have other ILA/VIO modules, they will need to
// for example instantiate a larger ICON module). In addition
// user may want to instantiate more VIO modules to control
// IDELAY for more DQ, DQS than is shown here
//*****************************************************************
 
icon4 u_icon
(
.control0 (cs_control0),
.control1 (cs_control1),
.control2 (cs_control2),
.control3 (cs_control3)
);
 
//*****************************************************************
// VIO ASYNC input: Display current IDELAY setting for up to 32
// DQ taps (32x6) = 192
//*****************************************************************
 
vio_async_in192 u_vio0
(
.control (cs_control0),
.async_in (vio0_in)
);
 
//*****************************************************************
// VIO ASYNC input: Display current IDELAY setting for up to 8 DQS
// and DQS Gate taps (8x6x2) = 96
//*****************************************************************
 
vio_async_in96 u_vio1
(
.control (cs_control1),
.async_in (vio1_in)
);
 
//*****************************************************************
// VIO ASYNC input: Display other calibration results
//*****************************************************************
 
vio_async_in100 u_vio2
(
.control (cs_control2),
.async_in (vio2_in)
);
//*****************************************************************
// VIO SYNC output: Dynamically change IDELAY taps
//*****************************************************************
vio_sync_out32 u_vio3
(
.control (cs_control3),
.clk (clkdiv0),
.sync_out (vio3_out)
);
 
//*****************************************************************
// Bit assignments:
// NOTE: Not all VIO, ILA inputs/outputs may be used - these will
// be dependent on the user's particular bit width
//*****************************************************************
 
if (DQ_WIDTH <= 32) begin: gen_dq_le_32
assign vio0_in[(6*DQ_WIDTH)-1:0]
= dbg_calib_dq_tap_cnt[(6*DQ_WIDTH)-1:0];
end else begin: gen_dq_gt_32
assign vio0_in = dbg_calib_dq_tap_cnt[191:0];
end
 
if (DQS_WIDTH <= 8) begin: gen_dqs_le_8
assign vio1_in[(6*DQS_WIDTH)-1:0]
= dbg_calib_dqs_tap_cnt[(6*DQS_WIDTH)-1:0];
assign vio1_in[(12*DQS_WIDTH)-1:(6*DQS_WIDTH)]
= dbg_calib_gate_tap_cnt[(6*DQS_WIDTH)-1:0];
end else begin: gen_dqs_gt_32
assign vio1_in[47:0] = dbg_calib_dqs_tap_cnt[47:0];
assign vio1_in[95:48] = dbg_calib_gate_tap_cnt[47:0];
end
//dbg_calib_rd_data_sel
 
if (DQS_WIDTH <= 8) begin: gen_rdsel_le_8
assign vio2_in[(DQS_WIDTH)+7:8]
= dbg_calib_rd_data_sel[(DQS_WIDTH)-1:0];
end else begin: gen_rdsel_gt_32
assign vio2_in[15:8]
= dbg_calib_rd_data_sel[7:0];
end
//dbg_calib_rden_dly
 
if (DQS_WIDTH <= 8) begin: gen_calrd_le_8
assign vio2_in[(5*DQS_WIDTH)+19:20]
= dbg_calib_rden_dly[(5*DQS_WIDTH)-1:0];
end else begin: gen_calrd_gt_32
assign vio2_in[59:20]
= dbg_calib_rden_dly[39:0];
end
 
//dbg_calib_gate_dly
 
if (DQS_WIDTH <= 8) begin: gen_calgt_le_8
assign vio2_in[(5*DQS_WIDTH)+59:60]
= dbg_calib_gate_dly[(5*DQS_WIDTH)-1:0];
end else begin: gen_calgt_gt_32
assign vio2_in[99:60]
= dbg_calib_gate_dly[39:0];
end
 
//dbg_sel_idel_dq
 
if (DQ_BITS <= 5) begin: gen_selid_le_5
assign dbg_sel_idel_dq[DQ_BITS-1:0]
= vio3_out[DQ_BITS+7:8];
end else begin: gen_selid_gt_32
assign dbg_sel_idel_dq[4:0]
= vio3_out[12:8];
end
 
//dbg_sel_idel_dqs
 
if (DQS_BITS <= 3) begin: gen_seldqs_le_3
assign dbg_sel_idel_dqs[DQS_BITS:0]
= vio3_out[(DQS_BITS+16):16];
end else begin: gen_seldqs_gt_32
assign dbg_sel_idel_dqs[3:0]
= vio3_out[19:16];
end
 
//dbg_sel_idel_gate
 
if (DQS_BITS <= 3) begin: gen_gtdqs_le_3
assign dbg_sel_idel_gate[DQS_BITS:0]
= vio3_out[(DQS_BITS+21):21];
end else begin: gen_gtdqs_gt_32
assign dbg_sel_idel_gate[3:0]
= vio3_out[24:21];
end
 
`endif // `ifdef XILINX_DDR2_CHIPSCOPE
assign vio2_in[3:0] = dbg_calib_done;
assign vio2_in[7:4] = dbg_calib_err;
assign dbg_idel_up_all = vio3_out[0];
assign dbg_idel_down_all = vio3_out[1];
assign dbg_idel_up_dq = vio3_out[2];
assign dbg_idel_down_dq = vio3_out[3];
assign dbg_idel_up_dqs = vio3_out[4];
assign dbg_idel_down_dqs = vio3_out[5];
assign dbg_idel_up_gate = vio3_out[6];
assign dbg_idel_down_gate = vio3_out[7];
assign dbg_sel_all_idel_dq = vio3_out[15];
assign dbg_sel_all_idel_dqs = vio3_out[20];
assign dbg_sel_all_idel_gate = vio3_out[25];
end
endgenerate
 
endmodule
/boards/xilinx/ml501/rtl/verilog/xilinx_ddr2/ddr2_chipscope.v
0,0 → 1,114
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_chipscope.v
// /___/ /\ Date Last Modified: $Data$
// \ \ / \ Date Created: 9/14/06
// \___\/\___\
//
//Device: Virtex-5
//Purpose:
// Skeleton Chipscope module declarations - for simulation only
//Reference:
//Revision History:
//
//*****************************************************************************
 
`timescale 1ns/1ps
 
module icon4
(
control0,
control1,
control2,
control3
)
/* synthesis syn_black_box syn_noprune = 1 */;
output [35:0] control0;
output [35:0] control1;
output [35:0] control2;
output [35:0] control3;
endmodule
 
module vio_async_in192
(
control,
async_in
)
/* synthesis syn_black_box syn_noprune = 1 */;
input [35:0] control;
input [191:0] async_in;
endmodule
 
module vio_async_in96
(
control,
async_in
)
/* synthesis syn_black_box syn_noprune = 1 */;
input [35:0] control;
input [95:0] async_in;
endmodule
 
module vio_async_in100
(
control,
async_in
)
/* synthesis syn_black_box syn_noprune = 1 */;
input [35:0] control;
input [99:0] async_in;
endmodule
 
module vio_sync_out32
(
control,
clk,
sync_out
)
/* synthesis syn_black_box syn_noprune = 1 */;
input [35:0] control;
input clk;
output [31:0] sync_out;
endmodule
/boards/xilinx/ml501/rtl/verilog/xilinx_ddr2/ddr2_phy_dq_iob.v
0,0 → 1,592
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007, 2008 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_phy_dq_iob.v
// /___/ /\ Date Last Modified: $Date: 2009/01/15 14:22:14 $
// \ \ / \ Date Created: Wed Aug 16 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR2
//Purpose:
// This module places the data in the IOBs.
//Reference:
//Revision History:
// Rev 1.1 - Parameter HIGH_PERFORMANCE_MODE added. PK. 7/10/08
// Rev 1.2 - DIRT strings removed and modified the code. PK. 11/13/08
// Rev 1.3 - Parameter IODELAY_GRP added and constraint IODELAY_GROUP added
// on IODELAY primitive. PK. 11/27/08
//*****************************************************************************
 
`timescale 1ns/1ps
 
module ddr2_phy_dq_iob #
(
// Following parameters are for 72-bit RDIMM design (for ML561 Reference
// board design). Actual values may be different. Actual parameters values
// are passed from design top module ddr2_mig module. Please refer to
// the ddr2_mig module for actual values.
parameter HIGH_PERFORMANCE_MODE = "TRUE",
parameter IODELAY_GRP = "IODELAY_MIG",
parameter FPGA_SPEED_GRADE = 2
)
(
input clk0,
input clk90,
input clkdiv0,
input rst90,
input dlyinc,
input dlyce,
input dlyrst,
input [1:0] dq_oe_n,
input dqs,
input ce,
input rd_data_sel,
input wr_data_rise,
input wr_data_fall,
output rd_data_rise,
output rd_data_fall,
inout ddr_dq
);
 
wire dq_iddr_clk;
wire dq_idelay;
wire dq_in;
wire dq_oe_n_r;
wire dq_out;
wire stg2a_out_fall;
wire stg2a_out_rise;
(* XIL_PAR_DELAY = "0 ps", XIL_PAR_IP_NAME = "MIG", syn_keep = "1", keep = "TRUE" *)
wire stg2b_out_fall;
(* XIL_PAR_DELAY = "0 ps", XIL_PAR_IP_NAME = "MIG", syn_keep = "1", keep = "TRUE" *)
wire stg2b_out_rise;
wire stg3a_out_fall;
wire stg3a_out_rise;
wire stg3b_out_fall;
wire stg3b_out_rise;
 
//***************************************************************************
// Directed routing constraints for route between IDDR and stage 2 capture
// in fabric.
// Only 2 out of the 12 wire declarations will be used for any given
// instantiation of this module.
// Varies according:
// (1) I/O column (left, center, right) used
// (2) Which I/O in I/O pair (master, slave) used
// Nomenclature: _Xy, X = column (0 = left, 1 = center, 2 = right),
// y = master or slave
//***************************************************************************
 
// MODIFIED, RC, 06/13/08: Remove all references to DIRT, master/slave
 
(* XIL_PAR_DELAY = "500 ps", XIL_PAR_SKEW = "55 ps", XIL_PAR_IP_NAME = "MIG", syn_keep = "1", keep = "TRUE" *)
wire stg1_out_rise_sg3;
(* XIL_PAR_DELAY = "500 ps", XIL_PAR_SKEW = "55 ps", XIL_PAR_IP_NAME = "MIG", syn_keep = "1", keep = "TRUE" *)
wire stg1_out_fall_sg3;
(* XIL_PAR_DELAY = "575 ps", XIL_PAR_SKEW = "65 ps", XIL_PAR_IP_NAME = "MIG", syn_keep = "1", keep = "TRUE" *)
wire stg1_out_rise_sg2;
(* XIL_PAR_DELAY = "575 ps", XIL_PAR_SKEW = "65 ps", XIL_PAR_IP_NAME = "MIG", syn_keep = "1", keep = "TRUE" *)
wire stg1_out_fall_sg2;
(* XIL_PAR_DELAY = "650 ps", XIL_PAR_SKEW = "70 ps", XIL_PAR_IP_NAME = "MIG", syn_keep = "1", keep = "TRUE" *)
wire stg1_out_rise_sg1;
(* XIL_PAR_DELAY = "650 ps", XIL_PAR_SKEW = "70 ps", XIL_PAR_IP_NAME = "MIG", syn_keep = "1", keep = "TRUE" *)
wire stg1_out_fall_sg1;
 
//***************************************************************************
// Bidirectional I/O
//***************************************************************************
 
IOBUF u_iobuf_dq
(
.I (dq_out),
.T (dq_oe_n_r),
.IO (ddr_dq),
.O (dq_in)
);
 
//***************************************************************************
// Write (output) path
//***************************************************************************
 
// on a write, rising edge of DQS corresponds to rising edge of CLK180
// (aka falling edge of CLK0 -> rising edge DQS). We also know:
// 1. data must be driven 1/4 clk cycle before corresponding DQS edge
// 2. first rising DQS edge driven on falling edge of CLK0
// 3. rising data must be driven 1/4 cycle before falling edge of CLK0
// 4. therefore, rising data driven on rising edge of CLK
ODDR #
(
.SRTYPE("SYNC"),
.DDR_CLK_EDGE("SAME_EDGE")
)
u_oddr_dq
(
.Q (dq_out),
.C (clk90),
.CE (1'b1),
.D1 (wr_data_rise),
.D2 (wr_data_fall),
.R (1'b0),
.S (1'b0)
);
 
// make sure output is tri-state during reset (DQ_OE_N_R = 1)
ODDR #
(
.SRTYPE("ASYNC"),
.DDR_CLK_EDGE("SAME_EDGE")
)
u_tri_state_dq
(
.Q (dq_oe_n_r),
.C (clk90),
.CE (1'b1),
.D1 (dq_oe_n[0]),
.D2 (dq_oe_n[1]),
.R (1'b0),
.S (rst90)
);
 
//***************************************************************************
// Read data capture scheme description:
// Data capture consists of 3 ranks of flops, and a MUX
// 1. Rank 1 ("Stage 1"): IDDR captures delayed DDR DQ from memory using
// delayed DQS.
// - Data is split into 2 SDR streams, one each for rise and fall data.
// - BUFIO (DQS) input inverted to IDDR. IDDR configured in SAME_EDGE
// mode. This means that: (1) Q1 = fall data, Q2 = rise data,
// (2) Both rise and fall data are output on falling edge of DQS -
// rather than rise output being output on one edge of DQS, and fall
// data on the other edge if the IDDR were configured in OPPOSITE_EDGE
// mode. This simplifies Stage 2 capture (only one core clock edge
// used, removing effects of duty-cycle-distortion), and saves one
// fabric flop in Rank 3.
// 2. Rank 2 ("Stage 2"): Fabric flops are used to capture output of first
// rank into FPGA clock (CLK) domain. Each rising/falling SDR stream
// from IDDR is feed into two flops, one clocked off rising and one off
// falling edge of CLK. One of these flops is chosen, with the choice
// being the one that reduces # of DQ/DQS taps necessary to align Stage
// 1 and Stage 2. Same edge is used to capture both rise and fall SDR
// streams.
// 3. Rank 3 ("Stage 3"): Removes half-cycle paths in CLK domain from
// output of Rank 2. This stage, like Stage 2, is clocked by CLK. Note
// that Stage 3 can be expanded to also support SERDES functionality
// 4. Output MUX: Selects whether Stage 1 output is aligned to rising or
// falling edge of CLK (i.e. specifically this selects whether IDDR
// rise/fall output is transfered to rising or falling edge of CLK).
// Implementation:
// 1. Rank 1 is implemented using an IDDR primitive
// 2. Rank 2 is implemented using:
// - An RPM to fix the location of the capture flops near the DQ I/O.
// The exact RPM used depends on which I/O column (left, center,
// right) the DQ I/O is placed at - this affects the optimal location
// of the slice flops (or does it - can we always choose the two
// columns to slices to the immediate right of the I/O to use, no
// matter what the column?). The origin of the RPM must be set in the
// UCF file using the RLOC_ORIGIN constraint (where the original is
// based on the DQ I/O location).
// - Directed Routing Constraints ("DIRT strings") to fix the routing
// to the rank 2 fabric flops. This is done to minimize: (1) total
// route delay (and therefore minimize voltage/temperature-related
// variations), and (2) minimize skew both within each rising and
// falling data net, as well as between the rising and falling nets.
// The exact DIRT string used depends on: (1) which I/O column the
// DQ I/O is placed, and (2) whether the DQ I/O is placed on the
// "Master" or "Slave" I/O of a diff pair (DQ is not differential, but
// the routing will be affected by which of each I/O pair is used)
// 3. Rank 3 is implemented using fabric flops. No LOC or DIRT contraints
// are used, tools are expected to place these and meet PERIOD timing
// without constraints (constraints may be necessary for "full" designs,
// in this case, user may need to add LOC constraints - if this is the
// case, there are no constraints - other than meeting PERIOD timing -
// for rank 3 flops.
//***************************************************************************
 
//***************************************************************************
// MIG 2.2: Define AREA_GROUP = "DDR_CAPTURE_FFS" contain all RPM flops in
// design. In UCF file, add constraint:
// AREA_GROUP "DDR_CAPTURE_FFS" GROUP = CLOSED;
// This is done to prevent MAP from packing unrelated logic into
// the slices used by the RPMs. Doing so may cause the DIRT strings
// that define the IDDR -> fabric flop routing to later become
// unroutable during PAR because the unrelated logic placed by MAP
// may use routing resources required by the DIRT strings. MAP
// does not currently take into account DIRT strings when placing
// logic
//***************************************************************************
 
// IDELAY to delay incoming data for synchronization purposes
(* IODELAY_GROUP = IODELAY_GRP *) IODELAY #
(
.DELAY_SRC ("I"),
.IDELAY_TYPE ("VARIABLE"),
.HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
.IDELAY_VALUE (0),
.ODELAY_VALUE (0)
)
u_idelay_dq
(
.DATAOUT (dq_idelay),
.C (clkdiv0),
.CE (dlyce),
.DATAIN (),
.IDATAIN (dq_in),
.INC (dlyinc),
.ODATAIN (),
.RST (dlyrst),
.T ()
);
 
//***************************************************************************
// Rank 1 capture: Use IDDR to generate two SDR outputs
//***************************************************************************
 
// invert clock to IDDR in order to use SAME_EDGE mode (otherwise, we "run
// out of clocks" because DQS is not continuous
assign dq_iddr_clk = ~dqs;
 
//***************************************************************************
// Rank 2 capture: Use fabric flops to capture Rank 1 output. Use RPM and
// DIRT strings here.
// BEL ("Basic Element of Logic") and relative location constraints for
// second stage capture. C
// Varies according:
// (1) I/O column (left, center, right) used
// (2) Which I/O in I/O pair (master, slave) used
//***************************************************************************
 
// MODIFIED, RC, 06/13/08: Remove all references to DIRT, master/slave
// Take out generate statements - collapses to a single case
 
generate
if (FPGA_SPEED_GRADE == 3) begin: gen_stg2_sg3
IDDR #
(
.DDR_CLK_EDGE ("SAME_EDGE")
)
u_iddr_dq
(
.Q1 (stg1_out_fall_sg3),
.Q2 (stg1_out_rise_sg3),
.C (dq_iddr_clk),
.CE (ce),
.D (dq_idelay),
.R (1'b0),
.S (1'b0)
);
 
//*********************************************************
// Slice #1 (posedge CLK): Used for:
// 1. IDDR transfer to CLK0 rising edge domain ("stg2a")
// 2. stg2 falling edge -> stg3 rising edge transfer
//*********************************************************
 
// Stage 2 capture
FDRSE u_ff_stg2a_fall
(
.Q (stg2a_out_fall),
.C (clk0),
.CE (1'b1),
.D (stg1_out_fall_sg3),
.R (1'b0),
.S (1'b0)
)/* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
FDRSE u_ff_stg2a_rise
(
.Q (stg2a_out_rise),
.C (clk0),
.CE (1'b1),
.D (stg1_out_rise_sg3),
.R (1'b0),
.S (1'b0)
)/* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
// Stage 3 falling -> rising edge translation
FDRSE u_ff_stg3b_fall
(
.Q (stg3b_out_fall),
.C (clk0),
.CE (1'b1),
.D (stg2b_out_fall),
.R (1'b0),
.S (1'b0)
)/* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
FDRSE u_ff_stg3b_rise
(
.Q (stg3b_out_rise),
.C (clk0),
.CE (1'b1),
.D (stg2b_out_rise),
.R (1'b0),
.S (1'b0)
)/* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
 
//*********************************************************
// Slice #2 (posedge CLK): Used for:
// 1. IDDR transfer to CLK0 falling edge domain ("stg2b")
//*********************************************************
 
FDRSE_1 u_ff_stg2b_fall
(
.Q (stg2b_out_fall),
.C (clk0),
.CE (1'b1),
.D (stg1_out_fall_sg3),
.R (1'b0),
.S (1'b0)
)/* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
 
FDRSE_1 u_ff_stg2b_rise
(
.Q (stg2b_out_rise),
.C (clk0),
.CE (1'b1),
.D (stg1_out_rise_sg3),
.R (1'b0),
.S (1'b0)
)/* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
end else if (FPGA_SPEED_GRADE == 2) begin: gen_stg2_sg2
IDDR #
(
.DDR_CLK_EDGE ("SAME_EDGE")
)
u_iddr_dq
(
.Q1 (stg1_out_fall_sg2),
.Q2 (stg1_out_rise_sg2),
.C (dq_iddr_clk),
.CE (ce),
.D (dq_idelay),
.R (1'b0),
.S (1'b0)
);
 
//*********************************************************
// Slice #1 (posedge CLK): Used for:
// 1. IDDR transfer to CLK0 rising edge domain ("stg2a")
// 2. stg2 falling edge -> stg3 rising edge transfer
//*********************************************************
 
// Stage 2 capture
FDRSE u_ff_stg2a_fall
(
.Q (stg2a_out_fall),
.C (clk0),
.CE (1'b1),
.D (stg1_out_fall_sg2),
.R (1'b0),
.S (1'b0)
)/* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
FDRSE u_ff_stg2a_rise
(
.Q (stg2a_out_rise),
.C (clk0),
.CE (1'b1),
.D (stg1_out_rise_sg2),
.R (1'b0),
.S (1'b0)
)/* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
// Stage 3 falling -> rising edge translation
FDRSE u_ff_stg3b_fall
(
.Q (stg3b_out_fall),
.C (clk0),
.CE (1'b1),
.D (stg2b_out_fall),
.R (1'b0),
.S (1'b0)
)/* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
FDRSE u_ff_stg3b_rise
(
.Q (stg3b_out_rise),
.C (clk0),
.CE (1'b1),
.D (stg2b_out_rise),
.R (1'b0),
.S (1'b0)
)/* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
 
//*********************************************************
// Slice #2 (posedge CLK): Used for:
// 1. IDDR transfer to CLK0 falling edge domain ("stg2b")
//*********************************************************
 
FDRSE_1 u_ff_stg2b_fall
(
.Q (stg2b_out_fall),
.C (clk0),
.CE (1'b1),
.D (stg1_out_fall_sg2),
.R (1'b0),
.S (1'b0)
)/* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
 
FDRSE_1 u_ff_stg2b_rise
(
.Q (stg2b_out_rise),
.C (clk0),
.CE (1'b1),
.D (stg1_out_rise_sg2),
.R (1'b0),
.S (1'b0)
)/* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
end else if (FPGA_SPEED_GRADE == 1) begin: gen_stg2_sg1
IDDR #
(
.DDR_CLK_EDGE ("SAME_EDGE")
)
u_iddr_dq
(
.Q1 (stg1_out_fall_sg1),
.Q2 (stg1_out_rise_sg1),
.C (dq_iddr_clk),
.CE (ce),
.D (dq_idelay),
.R (1'b0),
.S (1'b0)
);
 
//*********************************************************
// Slice #1 (posedge CLK): Used for:
// 1. IDDR transfer to CLK0 rising edge domain ("stg2a")
// 2. stg2 falling edge -> stg3 rising edge transfer
//*********************************************************
 
// Stage 2 capture
FDRSE u_ff_stg2a_fall
(
.Q (stg2a_out_fall),
.C (clk0),
.CE (1'b1),
.D (stg1_out_fall_sg1),
.R (1'b0),
.S (1'b0)
)/* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
FDRSE u_ff_stg2a_rise
(
.Q (stg2a_out_rise),
.C (clk0),
.CE (1'b1),
.D (stg1_out_rise_sg1),
.R (1'b0),
.S (1'b0)
)/* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
// Stage 3 falling -> rising edge translation
FDRSE u_ff_stg3b_fall
(
.Q (stg3b_out_fall),
.C (clk0),
.CE (1'b1),
.D (stg2b_out_fall),
.R (1'b0),
.S (1'b0)
)/* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
FDRSE u_ff_stg3b_rise
(
.Q (stg3b_out_rise),
.C (clk0),
.CE (1'b1),
.D (stg2b_out_rise),
.R (1'b0),
.S (1'b0)
)/* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
 
//*********************************************************
// Slice #2 (posedge CLK): Used for:
// 1. IDDR transfer to CLK0 falling edge domain ("stg2b")
//*********************************************************
 
FDRSE_1 u_ff_stg2b_fall
(
.Q (stg2b_out_fall),
.C (clk0),
.CE (1'b1),
.D (stg1_out_fall_sg1),
.R (1'b0),
.S (1'b0)
)/* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
 
FDRSE_1 u_ff_stg2b_rise
(
.Q (stg2b_out_rise),
.C (clk0),
.CE (1'b1),
.D (stg1_out_rise_sg1),
.R (1'b0),
.S (1'b0)
)/* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
end
endgenerate
 
//***************************************************************************
// Second stage flops clocked by posedge CLK0 don't need another layer of
// registering
//***************************************************************************
 
assign stg3a_out_rise = stg2a_out_rise;
assign stg3a_out_fall = stg2a_out_fall;
 
//*******************************************************************
 
assign rd_data_rise = (rd_data_sel) ? stg3a_out_rise : stg3b_out_rise;
assign rd_data_fall = (rd_data_sel) ? stg3a_out_fall : stg3b_out_fall;
 
endmodule
/boards/xilinx/ml501/rtl/verilog/xilinx_ddr2/README
0,0 → 1,17
Xilinx DDR2 controller with Wishbone interface
 
This is a Xilinx technology-dependent DDR2 memory controller, based on a
controller from Xilinx's memory interface generator (MIG), with a small cache
memory and Wishbone wrapper.
 
The xilinx_ddr2_wb_if.v is a 3-master arbiter for the controller.
The xilinx_ddr2_if.v is the actual interface between the Wishbone bus and
Xilinx MIG control interface.
 
When synthesizing, take note of the xilinx_ddr2_if_cache module, that is a
dual-port memory, with different aspects on each size, and cannot be inferred.
The NGC should be in the appropriate place in the synthesis or backend
directories.
 
Wishbone B3-compliant bursting is yet to be implemented.
 
/boards/xilinx/ml501/rtl/verilog/xilinx_ddr2/ddr2_mem_if_top.v
0,0 → 1,382
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007, 2008 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_mem_if_top.v
// /___/ /\ Date Last Modified: $Date: 2009/01/15 14:22:14 $
// \ \ / \ Date Created: Wed Aug 16 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR/DDR2
//Purpose:
// Top-level for parameterizable (DDR or DDR2) memory interface
//Reference:
//Revision History:
// Rev 1.1 - Parameter USE_DM_PORT added. PK. 6/25/08
// Rev 1.2 - Parameter HIGH_PERFORMANCE_MODE added. PK. 7/10/08
// Rev 1.3 - Parameter CS_BITS added. PK. 10/8/08
// Rev 1.4 - Parameter IODELAY_GRP added. PK. 11/27/08
//*****************************************************************************
 
`timescale 1ns/1ps
 
module ddr2_mem_if_top #
(
// Following parameters are for 72-bit RDIMM design (for ML561 Reference
// board design). Actual values may be different. Actual parameters values
// are passed from design top module ddr2_mig module. Please refer to
// the ddr2_mig module for actual values.
parameter BANK_WIDTH = 2,
parameter CKE_WIDTH = 1,
parameter CLK_WIDTH = 1,
parameter COL_WIDTH = 10,
parameter CS_BITS = 0,
parameter CS_NUM = 1,
parameter CS_WIDTH = 1,
parameter USE_DM_PORT = 1,
parameter DM_WIDTH = 9,
parameter DQ_WIDTH = 72,
parameter DQ_BITS = 7,
parameter DQ_PER_DQS = 8,
parameter DQS_BITS = 4,
parameter DQS_WIDTH = 9,
parameter HIGH_PERFORMANCE_MODE = "TRUE",
parameter IODELAY_GRP = "IODELAY_MIG",
parameter ODT_WIDTH = 1,
parameter ROW_WIDTH = 14,
parameter APPDATA_WIDTH = 144,
parameter ADDITIVE_LAT = 0,
parameter BURST_LEN = 4,
parameter BURST_TYPE = 0,
parameter CAS_LAT = 5,
parameter ECC_ENABLE = 0,
parameter MULTI_BANK_EN = 1,
parameter TWO_T_TIME_EN = 0,
parameter ODT_TYPE = 1,
parameter DDR_TYPE = 1,
parameter REDUCE_DRV = 0,
parameter REG_ENABLE = 1,
parameter TREFI_NS = 7800,
parameter TRAS = 40000,
parameter TRCD = 15000,
parameter TRFC = 105000,
parameter TRP = 15000,
parameter TRTP = 7500,
parameter TWR = 15000,
parameter TWTR = 10000,
parameter CLK_PERIOD = 3000,
parameter SIM_ONLY = 0,
parameter DEBUG_EN = 0,
parameter FPGA_SPEED_GRADE = 2
)
(
input clk0,
input usr_clk, // jb
input clk90,
input clkdiv0,
input rst0,
input rst90,
input rstdiv0,
input [2:0] app_af_cmd,
input [30:0] app_af_addr,
input app_af_wren,
input app_wdf_wren,
input [APPDATA_WIDTH-1:0] app_wdf_data,
input [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data,
output [1:0] rd_ecc_error,
output app_af_afull,
output app_wdf_afull,
output rd_data_valid,
output [APPDATA_WIDTH-1:0] rd_data_fifo_out,
output phy_init_done,
output [CLK_WIDTH-1:0] ddr_ck,
output [CLK_WIDTH-1:0] ddr_ck_n,
output [ROW_WIDTH-1:0] ddr_addr,
output [BANK_WIDTH-1:0] ddr_ba,
output ddr_ras_n,
output ddr_cas_n,
output ddr_we_n,
output [CS_WIDTH-1:0] ddr_cs_n,
output [CKE_WIDTH-1:0] ddr_cke,
output [ODT_WIDTH-1:0] ddr_odt,
output [DM_WIDTH-1:0] ddr_dm,
inout [DQS_WIDTH-1:0] ddr_dqs,
inout [DQS_WIDTH-1:0] ddr_dqs_n,
inout [DQ_WIDTH-1:0] ddr_dq,
// Debug signals (optional use)
input dbg_idel_up_all,
input dbg_idel_down_all,
input dbg_idel_up_dq,
input dbg_idel_down_dq,
input dbg_idel_up_dqs,
input dbg_idel_down_dqs,
input dbg_idel_up_gate,
input dbg_idel_down_gate,
input [DQ_BITS-1:0] dbg_sel_idel_dq,
input dbg_sel_all_idel_dq,
input [DQS_BITS:0] dbg_sel_idel_dqs,
input dbg_sel_all_idel_dqs,
input [DQS_BITS:0] dbg_sel_idel_gate,
input dbg_sel_all_idel_gate,
output [3:0] dbg_calib_done,
output [3:0] dbg_calib_err,
output [(6*DQ_WIDTH)-1:0] dbg_calib_dq_tap_cnt,
output [(6*DQS_WIDTH)-1:0] dbg_calib_dqs_tap_cnt,
output [(6*DQS_WIDTH)-1:0] dbg_calib_gate_tap_cnt,
output [DQS_WIDTH-1:0] dbg_calib_rd_data_sel,
output [(5*DQS_WIDTH)-1:0] dbg_calib_rden_dly,
output [(5*DQS_WIDTH)-1:0] dbg_calib_gate_dly
);
 
wire [30:0] af_addr;
wire [2:0] af_cmd;
wire af_empty;
wire [ROW_WIDTH-1:0] ctrl_addr;
wire ctrl_af_rden;
wire [BANK_WIDTH-1:0] ctrl_ba;
wire ctrl_cas_n;
wire [CS_NUM-1:0] ctrl_cs_n;
wire ctrl_ras_n;
wire ctrl_rden;
wire ctrl_ref_flag;
wire ctrl_we_n;
wire ctrl_wren;
wire [DQS_WIDTH-1:0] phy_calib_rden;
wire [DQS_WIDTH-1:0] phy_calib_rden_sel;
wire [DQ_WIDTH-1:0] rd_data_fall;
wire [DQ_WIDTH-1:0] rd_data_rise;
wire [(2*DQ_WIDTH)-1:0] wdf_data;
wire [((2*DQ_WIDTH)/8)-1:0] wdf_mask_data;
wire wdf_rden;
 
//***************************************************************************
 
ddr2_phy_top #
(
.BANK_WIDTH (BANK_WIDTH),
.CKE_WIDTH (CKE_WIDTH),
.CLK_WIDTH (CLK_WIDTH),
.COL_WIDTH (COL_WIDTH),
.CS_BITS (CS_BITS),
.CS_NUM (CS_NUM),
.CS_WIDTH (CS_WIDTH),
.USE_DM_PORT (USE_DM_PORT),
.DM_WIDTH (DM_WIDTH),
.DQ_WIDTH (DQ_WIDTH),
.DQ_BITS (DQ_BITS),
.DQ_PER_DQS (DQ_PER_DQS),
.DQS_BITS (DQS_BITS),
.DQS_WIDTH (DQS_WIDTH),
.HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
.IODELAY_GRP (IODELAY_GRP),
.ODT_WIDTH (ODT_WIDTH),
.ROW_WIDTH (ROW_WIDTH),
.TWO_T_TIME_EN (TWO_T_TIME_EN),
.ADDITIVE_LAT (ADDITIVE_LAT),
.BURST_LEN (BURST_LEN),
.BURST_TYPE (BURST_TYPE),
.CAS_LAT (CAS_LAT),
.ECC_ENABLE (ECC_ENABLE),
.ODT_TYPE (ODT_TYPE),
.DDR_TYPE (DDR_TYPE),
.REDUCE_DRV (REDUCE_DRV),
.REG_ENABLE (REG_ENABLE),
.TWR (TWR),
.CLK_PERIOD (CLK_PERIOD),
.SIM_ONLY (SIM_ONLY),
.DEBUG_EN (DEBUG_EN),
.FPGA_SPEED_GRADE (FPGA_SPEED_GRADE)
)
u_phy_top
(
.clk0 (clk0),
.clk90 (clk90),
.clkdiv0 (clkdiv0),
.rst0 (rst0),
.rst90 (rst90),
.rstdiv0 (rstdiv0),
.ctrl_wren (ctrl_wren),
.ctrl_addr (ctrl_addr),
.ctrl_ba (ctrl_ba),
.ctrl_ras_n (ctrl_ras_n),
.ctrl_cas_n (ctrl_cas_n),
.ctrl_we_n (ctrl_we_n),
.ctrl_cs_n (ctrl_cs_n),
.ctrl_rden (ctrl_rden),
.ctrl_ref_flag (ctrl_ref_flag),
.wdf_data (wdf_data),
.wdf_mask_data (wdf_mask_data),
.wdf_rden (wdf_rden),
.phy_init_done (phy_init_done),
.phy_calib_rden (phy_calib_rden),
.phy_calib_rden_sel (phy_calib_rden_sel),
.rd_data_rise (rd_data_rise),
.rd_data_fall (rd_data_fall),
.ddr_ck (ddr_ck),
.ddr_ck_n (ddr_ck_n),
.ddr_addr (ddr_addr),
.ddr_ba (ddr_ba),
.ddr_ras_n (ddr_ras_n),
.ddr_cas_n (ddr_cas_n),
.ddr_we_n (ddr_we_n),
.ddr_cs_n (ddr_cs_n),
.ddr_cke (ddr_cke),
.ddr_odt (ddr_odt),
.ddr_dm (ddr_dm),
.ddr_dqs (ddr_dqs),
.ddr_dqs_n (ddr_dqs_n),
.ddr_dq (ddr_dq),
.dbg_idel_up_all (dbg_idel_up_all),
.dbg_idel_down_all (dbg_idel_down_all),
.dbg_idel_up_dq (dbg_idel_up_dq),
.dbg_idel_down_dq (dbg_idel_down_dq),
.dbg_idel_up_dqs (dbg_idel_up_dqs),
.dbg_idel_down_dqs (dbg_idel_down_dqs),
.dbg_idel_up_gate (dbg_idel_up_gate),
.dbg_idel_down_gate (dbg_idel_down_gate),
.dbg_sel_idel_dq (dbg_sel_idel_dq),
.dbg_sel_all_idel_dq (dbg_sel_all_idel_dq),
.dbg_sel_idel_dqs (dbg_sel_idel_dqs),
.dbg_sel_all_idel_dqs (dbg_sel_all_idel_dqs),
.dbg_sel_idel_gate (dbg_sel_idel_gate),
.dbg_sel_all_idel_gate (dbg_sel_all_idel_gate),
.dbg_calib_done (dbg_calib_done),
.dbg_calib_err (dbg_calib_err),
.dbg_calib_dq_tap_cnt (dbg_calib_dq_tap_cnt),
.dbg_calib_dqs_tap_cnt (dbg_calib_dqs_tap_cnt),
.dbg_calib_gate_tap_cnt (dbg_calib_gate_tap_cnt),
.dbg_calib_rd_data_sel (dbg_calib_rd_data_sel),
.dbg_calib_rden_dly (dbg_calib_rden_dly),
.dbg_calib_gate_dly (dbg_calib_gate_dly)
);
 
ddr2_usr_top #
(
.BANK_WIDTH (BANK_WIDTH),
.COL_WIDTH (COL_WIDTH),
.CS_BITS (CS_BITS),
.DQ_WIDTH (DQ_WIDTH),
.DQ_PER_DQS (DQ_PER_DQS),
.DQS_WIDTH (DQS_WIDTH),
.APPDATA_WIDTH (APPDATA_WIDTH),
.ECC_ENABLE (ECC_ENABLE),
.ROW_WIDTH (ROW_WIDTH)
)
u_usr_top
(
.clk0 (clk0),
.usr_clk (usr_clk), //jb
.clk90 (clk90),
.rst0 (rst0),
.rd_data_in_rise (rd_data_rise),
.rd_data_in_fall (rd_data_fall),
.phy_calib_rden (phy_calib_rden),
.phy_calib_rden_sel(phy_calib_rden_sel),
.rd_data_valid (rd_data_valid),
.rd_ecc_error (rd_ecc_error),
.rd_data_fifo_out (rd_data_fifo_out),
.app_af_cmd (app_af_cmd),
.app_af_addr (app_af_addr),
.app_af_wren (app_af_wren),
.ctrl_af_rden (ctrl_af_rden),
.af_cmd (af_cmd),
.af_addr (af_addr),
.af_empty (af_empty),
.app_af_afull (app_af_afull),
.app_wdf_wren (app_wdf_wren),
.app_wdf_data (app_wdf_data),
.app_wdf_mask_data (app_wdf_mask_data),
.wdf_rden (wdf_rden),
.app_wdf_afull (app_wdf_afull),
.wdf_data (wdf_data),
.wdf_mask_data (wdf_mask_data)
);
 
 
ddr2_ctrl #
(
.BANK_WIDTH (BANK_WIDTH),
.COL_WIDTH (COL_WIDTH),
.CS_BITS (CS_BITS),
.CS_NUM (CS_NUM),
.ROW_WIDTH (ROW_WIDTH),
.ADDITIVE_LAT (ADDITIVE_LAT),
.BURST_LEN (BURST_LEN),
.CAS_LAT (CAS_LAT),
.ECC_ENABLE (ECC_ENABLE),
.REG_ENABLE (REG_ENABLE),
.MULTI_BANK_EN (MULTI_BANK_EN),
.TWO_T_TIME_EN (TWO_T_TIME_EN),
.TREFI_NS (TREFI_NS),
.TRAS (TRAS),
.TRCD (TRCD),
.TRFC (TRFC),
.TRP (TRP),
.TRTP (TRTP),
.TWR (TWR),
.TWTR (TWTR),
.CLK_PERIOD (CLK_PERIOD),
.DDR_TYPE (DDR_TYPE)
)
u_ctrl
(
.clk (clk0),
.rst (rst0),
.af_cmd (af_cmd),
.af_addr (af_addr),
.af_empty (af_empty),
.phy_init_done (phy_init_done),
.ctrl_ref_flag (ctrl_ref_flag),
.ctrl_af_rden (ctrl_af_rden),
.ctrl_wren (ctrl_wren),
.ctrl_rden (ctrl_rden),
.ctrl_addr (ctrl_addr),
.ctrl_ba (ctrl_ba),
.ctrl_ras_n (ctrl_ras_n),
.ctrl_cas_n (ctrl_cas_n),
.ctrl_we_n (ctrl_we_n),
.ctrl_cs_n (ctrl_cs_n)
);
 
endmodule
/boards/xilinx/ml501/rtl/verilog/xilinx_ddr2/ddr2_infrastructure.v
0,0 → 1,352
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007, 2008 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_infrastructure.v
// /___/ /\ Date Last Modified: $Date: 2008/12/23 14:26:00 $
// \ \ / \ Date Created: Wed Aug 16 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR2
//Purpose:
// Clock generation/distribution and reset synchronization
//Reference:
//Revision History:
// Rev 1.1 - Parameter CLK_TYPE added and logic for DIFFERENTIAL and
// SINGLE_ENDED added. PK. 6/20/08
// Rev 1.2 - Loacalparam CLK_GENERATOR added and logic for clocks generation
// using PLL or DCM added as generic code. PK. 10/14/08
//*****************************************************************************
 
`timescale 1ns/1ps
 
module ddr2_infrastructure #
(
// Following parameters are for 72-bit RDIMM design (for ML561 Reference
// board design). Actual values may be different. Actual parameters values
// are passed from design top module ddr2_mig module. Please refer to
// the ddr2_mig module for actual values.
parameter CLK_PERIOD = 3000,
parameter CLK_TYPE = "DIFFERENTIAL",
parameter DLL_FREQ_MODE = "HIGH",
parameter RST_ACT_LOW = 1
)
(
input sys_clk_p,
input sys_clk_n,
input sys_clk,
input clk200_p,
input clk200_n,
input idly_clk_200,
output clk0,
output clk90,
output clk200,
output clkdiv0,
input sys_rst_n,
input idelay_ctrl_rdy,
output rst0,
output rst90,
output rst200,
output rstdiv0
);
 
// # of clock cycles to delay deassertion of reset. Needs to be a fairly
// high number not so much for metastability protection, but to give time
// for reset (i.e. stable clock cycles) to propagate through all state
// machines and to all control signals (i.e. not all control signals have
// resets, instead they rely on base state logic being reset, and the effect
// of that reset propagating through the logic). Need this because we may not
// be getting stable clock cycles while reset asserted (i.e. since reset
// depends on PLL/DCM lock status)
localparam RST_SYNC_NUM = 25;
localparam CLK_PERIOD_NS = CLK_PERIOD / 1000.0;
localparam CLK_PERIOD_INT = CLK_PERIOD/1000;
 
// By default this Parameter (CLK_GENERATOR) value is "PLL". If this
// Parameter is set to "PLL", PLL is used to generate the design clocks.
// If this Parameter is set to "DCM",
// DCM is used to generate the design clocks.
localparam CLK_GENERATOR = "PLL";
 
wire clk0_bufg;
wire clk0_bufg_in;
wire clk90_bufg;
wire clk90_bufg_in;
wire clk200_bufg;
wire clk200_ibufg;
wire clkdiv0_bufg;
wire clkdiv0_bufg_in;
wire clkfbout_clkfbin;
wire locked;
reg [RST_SYNC_NUM-1:0] rst0_sync_r /* synthesis syn_maxfan = 10 */;
reg [RST_SYNC_NUM-1:0] rst200_sync_r /* synthesis syn_maxfan = 10 */;
reg [RST_SYNC_NUM-1:0] rst90_sync_r /* synthesis syn_maxfan = 10 */;
reg [(RST_SYNC_NUM/2)-1:0] rstdiv0_sync_r /* synthesis syn_maxfan = 10 */;
wire rst_tmp;
wire sys_clk_ibufg;
wire sys_rst;
 
assign sys_rst = RST_ACT_LOW ? ~sys_rst_n: sys_rst_n;
 
assign clk0 = clk0_bufg;
assign clk90 = clk90_bufg;
assign clk200 = clk200_bufg;
assign clkdiv0 = clkdiv0_bufg;
 
generate
if(CLK_TYPE == "DIFFERENTIAL") begin : DIFF_ENDED_CLKS_INST
//***************************************************************************
// Differential input clock input buffers
//***************************************************************************
 
IBUFGDS_LVPECL_25 SYS_CLK_INST
(
.I (sys_clk_p),
.IB (sys_clk_n),
.O (sys_clk_ibufg)
);
 
IBUFGDS_LVPECL_25 IDLY_CLK_INST
(
.I (clk200_p),
.IB (clk200_n),
.O (clk200_ibufg)
);
 
end/* else if(CLK_TYPE == "SINGLE_ENDED") begin : SINGLE_ENDED_CLKS_INST
//**************************************************************************
// Single ended input clock input buffers
//**************************************************************************
 
IBUFG SYS_CLK_INST
(
.I (sys_clk),
.O (sys_clk_ibufg)
);
 
IBUFG IDLY_CLK_INST
(
.I (idly_clk_200),
.O (clk200_ibufg)
);
// This is being instantiated inside another design. these signals are properly generated elsewhere -- jb
end*/
endgenerate
assign sys_clk_ibufg = sys_clk;
//assign idly_clk_200 = clk200_ibufg;
assign clk200_bufg = idly_clk_200;
/*
BUFG CLK_200_BUFG
(
.O (clk200_bufg),
.I (clk200_ibufg)
);
*/
//***************************************************************************
// Global clock generation and distribution
//***************************************************************************
 
generate
if (CLK_GENERATOR == "PLL") begin : gen_pll_adv
PLL_ADV #
(
.BANDWIDTH ("OPTIMIZED"),
.CLKIN1_PERIOD (CLK_PERIOD_NS),
.CLKIN2_PERIOD (10.000),
.CLKOUT0_DIVIDE (CLK_PERIOD_INT),
.CLKOUT1_DIVIDE (CLK_PERIOD_INT),
.CLKOUT2_DIVIDE (CLK_PERIOD_INT*2),
.CLKOUT3_DIVIDE (1),
.CLKOUT4_DIVIDE (1),
.CLKOUT5_DIVIDE (1),
.CLKOUT0_PHASE (0.000),
.CLKOUT1_PHASE (90.000),
.CLKOUT2_PHASE (0.000),
.CLKOUT3_PHASE (0.000),
.CLKOUT4_PHASE (0.000),
.CLKOUT5_PHASE (0.000),
.CLKOUT0_DUTY_CYCLE (0.500),
.CLKOUT1_DUTY_CYCLE (0.500),
.CLKOUT2_DUTY_CYCLE (0.500),
.CLKOUT3_DUTY_CYCLE (0.500),
.CLKOUT4_DUTY_CYCLE (0.500),
.CLKOUT5_DUTY_CYCLE (0.500),
.COMPENSATION ("SYSTEM_SYNCHRONOUS"),
.DIVCLK_DIVIDE (1),
.CLKFBOUT_MULT (CLK_PERIOD_INT),
.CLKFBOUT_PHASE (0.0),
.REF_JITTER (0.005000)
)
u_pll_adv
(
.CLKFBIN (clkfbout_clkfbin),
.CLKINSEL (1'b1),
.CLKIN1 (sys_clk_ibufg),
.CLKIN2 (1'b0),
.DADDR (5'b0),
.DCLK (1'b0),
.DEN (1'b0),
.DI (16'b0),
.DWE (1'b0),
.REL (1'b0),
.RST (sys_rst),
.CLKFBDCM (),
.CLKFBOUT (clkfbout_clkfbin),
.CLKOUTDCM0 (),
.CLKOUTDCM1 (),
.CLKOUTDCM2 (),
.CLKOUTDCM3 (),
.CLKOUTDCM4 (),
.CLKOUTDCM5 (),
.CLKOUT0 (clk0_bufg_in),
.CLKOUT1 (clk90_bufg_in),
.CLKOUT2 (clkdiv0_bufg_in),
.CLKOUT3 (),
.CLKOUT4 (),
.CLKOUT5 (),
.DO (),
.DRDY (),
.LOCKED (locked)
);
end else if (CLK_GENERATOR == "DCM") begin: gen_dcm_base
DCM_BASE #
(
.CLKIN_PERIOD (CLK_PERIOD_NS),
.CLKDV_DIVIDE (2.0),
.DLL_FREQUENCY_MODE (DLL_FREQ_MODE),
.DUTY_CYCLE_CORRECTION ("TRUE"),
.FACTORY_JF (16'hF0F0)
)
u_dcm_base
(
.CLK0 (clk0_bufg_in),
.CLK180 (),
.CLK270 (),
.CLK2X (),
.CLK2X180 (),
.CLK90 (clk90_bufg_in),
.CLKDV (clkdiv0_bufg_in),
.CLKFX (),
.CLKFX180 (),
.LOCKED (locked),
.CLKFB (clk0_bufg),
.CLKIN (sys_clk_ibufg),
.RST (sys_rst)
);
end
endgenerate
 
BUFG U_BUFG_CLK0
(
.O (clk0_bufg),
.I (clk0_bufg_in)
);
 
BUFG U_BUFG_CLK90
(
.O (clk90_bufg),
.I (clk90_bufg_in)
);
 
BUFG U_BUFG_CLKDIV0
(
.O (clkdiv0_bufg),
.I (clkdiv0_bufg_in)
);
 
 
//***************************************************************************
// Reset synchronization
// NOTES:
// 1. shut down the whole operation if the PLL/ DCM hasn't yet locked (and
// by inference, this means that external SYS_RST_IN has been asserted -
// PLL/DCM deasserts LOCKED as soon as SYS_RST_IN asserted)
// 2. In the case of all resets except rst200, also assert reset if the
// IDELAY master controller is not yet ready
// 3. asynchronously assert reset. This was we can assert reset even if
// there is no clock (needed for things like 3-stating output buffers).
// reset deassertion is synchronous.
//***************************************************************************
 
assign rst_tmp = sys_rst | ~locked | ~idelay_ctrl_rdy;
 
// synthesis attribute max_fanout of rst0_sync_r is 10
always @(posedge clk0_bufg or posedge rst_tmp)
if (rst_tmp)
rst0_sync_r <= {RST_SYNC_NUM{1'b1}};
else
// logical left shift by one (pads with 0)
rst0_sync_r <= rst0_sync_r << 1;
 
// synthesis attribute max_fanout of rstdiv0_sync_r is 10
always @(posedge clkdiv0_bufg or posedge rst_tmp)
if (rst_tmp)
rstdiv0_sync_r <= {(RST_SYNC_NUM/2){1'b1}};
else
// logical left shift by one (pads with 0)
rstdiv0_sync_r <= rstdiv0_sync_r << 1;
 
// synthesis attribute max_fanout of rst90_sync_r is 10
always @(posedge clk90_bufg or posedge rst_tmp)
if (rst_tmp)
rst90_sync_r <= {RST_SYNC_NUM{1'b1}};
else
rst90_sync_r <= rst90_sync_r << 1;
 
// make sure CLK200 doesn't depend on IDELAY_CTRL_RDY, else chicken n' egg
// synthesis attribute max_fanout of rst200_sync_r is 10
always @(posedge clk200_bufg or negedge locked)
if (!locked)
rst200_sync_r <= {RST_SYNC_NUM{1'b1}};
else
rst200_sync_r <= rst200_sync_r << 1;
 
 
assign rst0 = rst0_sync_r[RST_SYNC_NUM-1];
assign rst90 = rst90_sync_r[RST_SYNC_NUM-1];
assign rst200 = rst200_sync_r[RST_SYNC_NUM-1];
assign rstdiv0 = rstdiv0_sync_r[(RST_SYNC_NUM/2)-1];
 
endmodule
/boards/xilinx/ml501/rtl/verilog/xilinx_ddr2/ddr2_usr_wr.v
0,0 → 1,338
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_usr_wr.v
// /___/ /\ Date Last Modified: $Date: 2008/12/23 14:26:01 $
// \ \ / \ Date Created: Mon Aug 28 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR/DDR2
//Purpose:
// This module instantiates the modules containing internal FIFOs
//Reference:
//Revision History:
//*****************************************************************************
 
`timescale 1ns/1ps
 
module ddr2_usr_wr #
(
// Following parameters are for 72-bit RDIMM design (for ML561 Reference
// board design). Actual values may be different. Actual parameters values
// are passed from design top module ddr2_mig module. Please refer to
// the ddr2_mig module for actual values.
parameter BANK_WIDTH = 2,
parameter COL_WIDTH = 10,
parameter CS_BITS = 0,
parameter DQ_WIDTH = 72,
parameter APPDATA_WIDTH = 144,
parameter ECC_ENABLE = 0,
parameter ROW_WIDTH = 14
)
(
input clk0,
input usr_clk, // jb
input clk90,
input rst0,
// Write data FIFO interface
input app_wdf_wren,
input [APPDATA_WIDTH-1:0] app_wdf_data,
input [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data,
input wdf_rden,
output app_wdf_afull,
output [(2*DQ_WIDTH)-1:0] wdf_data,
output [((2*DQ_WIDTH)/8)-1:0] wdf_mask_data
);
 
// determine number of FIFO72's to use based on data width
// round up to next integer value when determining WDF_FIFO_NUM
localparam WDF_FIFO_NUM = (ECC_ENABLE) ? (APPDATA_WIDTH+63)/64 :
((2*DQ_WIDTH)+63)/64;
// MASK_WIDTH = number of bytes in data bus
localparam MASK_WIDTH = DQ_WIDTH/8;
 
wire [WDF_FIFO_NUM-1:0] i_wdf_afull;
wire [DQ_WIDTH-1:0] i_wdf_data_fall_in;
wire [DQ_WIDTH-1:0] i_wdf_data_fall_out;
wire [(64*WDF_FIFO_NUM)-1:0] i_wdf_data_in;
wire [(64*WDF_FIFO_NUM)-1:0] i_wdf_data_out;
wire [DQ_WIDTH-1:0] i_wdf_data_rise_in;
wire [DQ_WIDTH-1:0] i_wdf_data_rise_out;
wire [MASK_WIDTH-1:0] i_wdf_mask_data_fall_in;
wire [MASK_WIDTH-1:0] i_wdf_mask_data_fall_out;
wire [(8*WDF_FIFO_NUM)-1:0] i_wdf_mask_data_in;
wire [(8*WDF_FIFO_NUM)-1:0] i_wdf_mask_data_out;
wire [MASK_WIDTH-1:0] i_wdf_mask_data_rise_in;
wire [MASK_WIDTH-1:0] i_wdf_mask_data_rise_out;
reg rst_r;
 
// ECC signals
wire [(2*DQ_WIDTH)-1:0] i_wdf_data_out_ecc;
wire [((2*DQ_WIDTH)/8)-1:0] i_wdf_mask_data_out_ecc;
wire [63:0] i_wdf_mask_data_out_ecc_wire;
wire [((2*DQ_WIDTH)/8)-1:0] mask_data_in_ecc;
wire [63:0] mask_data_in_ecc_wire;
 
//***************************************************************************
 
assign app_wdf_afull = i_wdf_afull[0];
 
always @(posedge clk0 )
rst_r <= rst0;
 
genvar wdf_di_i;
genvar wdf_do_i;
genvar mask_i;
genvar wdf_i;
generate
if(ECC_ENABLE) begin // ECC code
 
assign wdf_data = i_wdf_data_out_ecc;
 
// the byte 9 dm is always held to 0
assign wdf_mask_data = i_wdf_mask_data_out_ecc;
 
 
 
// generate for write data fifo .
for (wdf_i = 0; wdf_i < WDF_FIFO_NUM; wdf_i = wdf_i + 1) begin: gen_wdf
 
FIFO36_72 #
(
.ALMOST_EMPTY_OFFSET (9'h007),
.ALMOST_FULL_OFFSET (9'h00F),
.DO_REG (1), // extra CC output delay
.EN_ECC_WRITE ("TRUE"),
.EN_ECC_READ ("FALSE"),
.EN_SYN ("FALSE"),
.FIRST_WORD_FALL_THROUGH ("FALSE")
)
u_wdf_ecc
(
.ALMOSTEMPTY (),
.ALMOSTFULL (i_wdf_afull[wdf_i]),
.DBITERR (),
.DO (i_wdf_data_out_ecc[((64*(wdf_i+1))+(wdf_i *8))-1:
(64*wdf_i)+(wdf_i *8)]),
.DOP (i_wdf_data_out_ecc[(72*(wdf_i+1))-1:
(64*(wdf_i+1))+ (8*wdf_i) ]),
.ECCPARITY (),
.EMPTY (),
.FULL (),
.RDCOUNT (),
.RDERR (),
.SBITERR (),
.WRCOUNT (),
.WRERR (),
.DI (app_wdf_data[(64*(wdf_i+1))-1:
(64*wdf_i)]),
.DIP (),
.RDCLK (clk90),
.RDEN (wdf_rden),
.RST (rst_r), // or can use rst0
.WRCLK (clk0),
// .WRCLK (usr_clk), //jb
.WREN (app_wdf_wren)
);
end
 
// remapping the mask data. The mask data from user i/f does not have
// the mask for the ECC byte. Assigning 0 to the ECC mask byte.
for (mask_i = 0; mask_i < (DQ_WIDTH)/36;
mask_i = mask_i +1) begin: gen_mask
assign mask_data_in_ecc[((8*(mask_i+1))+ mask_i)-1:((8*mask_i)+mask_i)]
= app_wdf_mask_data[(8*(mask_i+1))-1:8*(mask_i)] ;
assign mask_data_in_ecc[((8*(mask_i+1))+mask_i)] = 1'd0;
end
 
// assign ecc bits to temp variables to avoid
// sim warnings. Not all the 64 bits of the fifo
// are used in ECC mode.
assign mask_data_in_ecc_wire[((2*DQ_WIDTH)/8)-1:0] = mask_data_in_ecc;
assign mask_data_in_ecc_wire[63:((2*DQ_WIDTH)/8)] =
{(64-((2*DQ_WIDTH)/8)){1'b0}};
assign i_wdf_mask_data_out_ecc =
i_wdf_mask_data_out_ecc_wire[((2*DQ_WIDTH)/8)-1:0];
 
 
FIFO36_72 #
(
.ALMOST_EMPTY_OFFSET (9'h007),
.ALMOST_FULL_OFFSET (9'h00F),
.DO_REG (1), // extra CC output delay
.EN_ECC_WRITE ("TRUE"),
.EN_ECC_READ ("FALSE"),
.EN_SYN ("FALSE"),
.FIRST_WORD_FALL_THROUGH ("FALSE")
)
u_wdf_ecc_mask
(
.ALMOSTEMPTY (),
.ALMOSTFULL (),
.DBITERR (),
.DO (i_wdf_mask_data_out_ecc_wire),
.DOP (),
.ECCPARITY (),
.EMPTY (),
.FULL (),
.RDCOUNT (),
.RDERR (),
.SBITERR (),
.WRCOUNT (),
.WRERR (),
.DI (mask_data_in_ecc_wire),
.DIP (),
.RDCLK (clk90),
.RDEN (wdf_rden),
.RST (rst_r), // or can use rst0
.WRCLK (clk0),
// .WRCLK (usr_clk), // jb
.WREN (app_wdf_wren)
);
end else begin
 
//***********************************************************************
 
// Define intermediate buses:
assign i_wdf_data_rise_in
= app_wdf_data[DQ_WIDTH-1:0];
assign i_wdf_data_fall_in
= app_wdf_data[(2*DQ_WIDTH)-1:DQ_WIDTH];
assign i_wdf_mask_data_rise_in
= app_wdf_mask_data[MASK_WIDTH-1:0];
assign i_wdf_mask_data_fall_in
= app_wdf_mask_data[(2*MASK_WIDTH)-1:MASK_WIDTH];
 
//***********************************************************************
// Write data FIFO Input:
// Arrange DQ's so that the rise data and fall data are interleaved.
// the data arrives at the input of the wdf fifo as {fall,rise}.
// It is remapped as:
// {...fall[15:8],rise[15:8],fall[7:0],rise[7:0]}
// This is done to avoid having separate fifo's for rise and fall data
// and to keep rise/fall data for the same DQ's on same FIFO
// Data masks are interleaved in a similar manner
// NOTE: Initialization data from PHY_INIT module does not need to be
// interleaved - it's already in the correct format - and the same
// initialization pattern from PHY_INIT is sent to all write FIFOs
//***********************************************************************
 
for (wdf_di_i = 0; wdf_di_i < MASK_WIDTH;
wdf_di_i = wdf_di_i + 1) begin: gen_wdf_data_in
assign i_wdf_data_in[(16*wdf_di_i)+15:(16*wdf_di_i)]
= {i_wdf_data_fall_in[(8*wdf_di_i)+7:(8*wdf_di_i)],
i_wdf_data_rise_in[(8*wdf_di_i)+7:(8*wdf_di_i)]};
assign i_wdf_mask_data_in[(2*wdf_di_i)+1:(2*wdf_di_i)]
= {i_wdf_mask_data_fall_in[wdf_di_i],
i_wdf_mask_data_rise_in[wdf_di_i]};
end
 
//***********************************************************************
// Write data FIFO Output:
// FIFO DQ and mask outputs must be untangled and put in the standard
// format of {fall,rise}. Same goes for mask output
//***********************************************************************
 
for (wdf_do_i = 0; wdf_do_i < MASK_WIDTH;
wdf_do_i = wdf_do_i + 1) begin: gen_wdf_data_out
assign i_wdf_data_rise_out[(8*wdf_do_i)+7:(8*wdf_do_i)]
= i_wdf_data_out[(16*wdf_do_i)+7:(16*wdf_do_i)];
assign i_wdf_data_fall_out[(8*wdf_do_i)+7:(8*wdf_do_i)]
= i_wdf_data_out[(16*wdf_do_i)+15:(16*wdf_do_i)+8];
assign i_wdf_mask_data_rise_out[wdf_do_i]
= i_wdf_mask_data_out[2*wdf_do_i];
assign i_wdf_mask_data_fall_out[wdf_do_i]
= i_wdf_mask_data_out[(2*wdf_do_i)+1];
end
 
assign wdf_data = {i_wdf_data_fall_out,
i_wdf_data_rise_out};
 
assign wdf_mask_data = {i_wdf_mask_data_fall_out,
i_wdf_mask_data_rise_out};
 
//***********************************************************************
 
for (wdf_i = 0; wdf_i < WDF_FIFO_NUM; wdf_i = wdf_i + 1) begin: gen_wdf
 
FIFO36_72 #
(
.ALMOST_EMPTY_OFFSET (9'h007),
.ALMOST_FULL_OFFSET (9'h00F),
.DO_REG (1), // extra CC output delay
.EN_ECC_WRITE ("FALSE"),
.EN_ECC_READ ("FALSE"),
.EN_SYN ("FALSE"),
.FIRST_WORD_FALL_THROUGH ("FALSE")
)
u_wdf
(
.ALMOSTEMPTY (),
.ALMOSTFULL (i_wdf_afull[wdf_i]),
.DBITERR (),
.DO (i_wdf_data_out[(64*(wdf_i+1))-1:64*wdf_i]),
.DOP (i_wdf_mask_data_out[(8*(wdf_i+1))-1:8*wdf_i]),
.ECCPARITY (),
.EMPTY (),
.FULL (),
.RDCOUNT (),
.RDERR (),
.SBITERR (),
.WRCOUNT (),
.WRERR (),
.DI (i_wdf_data_in[(64*(wdf_i+1))-1:64*wdf_i]),
.DIP (i_wdf_mask_data_in[(8*(wdf_i+1))-1:8*wdf_i]),
.RDCLK (clk90),
.RDEN (wdf_rden),
.RST (rst_r), // or can use rst0
.WRCLK (clk0),
// .WRCLK (usr_clk), //jb
.WREN (app_wdf_wren)
);
end
end
endgenerate
 
endmodule
/boards/xilinx/ml501/rtl/verilog/xilinx_ddr2/ddr2_phy_top.v
0,0 → 1,395
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007, 2008 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_phy_top.v
// /___/ /\ Date Last Modified: $Date: 2009/02/03 18:50:12 $
// \ \ / \ Date Created: Wed Aug 16 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR2
//Purpose:
// Top-level for memory physical layer (PHY) interface
//Reference:
//Revision History:
// Rev 1.1 - Parameter USE_DM_PORT added. PK. 6/25/08
// Rev 1.2 - Parameter HIGH_PERFORMANCE_MODE added. PK. 7/10/08
// Rev 1.3 - Parameter CS_BITS added. PK. 10/8/08
// Rev 1.4 - Parameter IODELAY_GRP added. PK. 11/27/08
//*****************************************************************************
 
`timescale 1ns/1ps
 
(* X_CORE_INFO = "mig_v3_0_ddr2_sdram_v5, Coregen 11.1" , CORE_GENERATION_INFO = "ddr2_sdram_v5,mig_v3_0,{component_name=ddr2_phy_top, BANK_WIDTH=2, CKE_WIDTH=1, CLK_WIDTH=2, COL_WIDTH=10, CS_NUM=1, CS_WIDTH=1, DM_WIDTH=8, DQ_WIDTH=64, DQ_PER_DQS=8, DQS_WIDTH=8, ODT_WIDTH=1, ROW_WIDTH=13, ADDITIVE_LAT=0, BURST_LEN=4, BURST_TYPE=0, CAS_LAT=4, ECC_ENABLE=0, MULTI_BANK_EN=1, TWO_T_TIME_EN=1, ODT_TYPE=1, REDUCE_DRV=0, REG_ENABLE=0, TREFI_NS=7800, TRAS=40000, TRCD=15000, TRFC=105000, TRP=15000, TRTP=7500, TWR=15000, TWTR=7500, DDR2_CLK_PERIOD=3750, RST_ACT_LOW=1}" *)
module ddr2_phy_top #
(
// Following parameters are for 72-bit RDIMM design (for ML561 Reference
// board design). Actual values may be different. Actual parameters values
// are passed from design top module ddr2_mig module. Please refer to
// the ddr2_mig module for actual values.
parameter BANK_WIDTH = 2,
parameter CLK_WIDTH = 1,
parameter CKE_WIDTH = 1,
parameter COL_WIDTH = 10,
parameter CS_BITS = 0,
parameter CS_NUM = 1,
parameter CS_WIDTH = 1,
parameter USE_DM_PORT = 1,
parameter DM_WIDTH = 9,
parameter DQ_WIDTH = 72,
parameter DQ_BITS = 7,
parameter DQ_PER_DQS = 8,
parameter DQS_WIDTH = 9,
parameter DQS_BITS = 4,
parameter HIGH_PERFORMANCE_MODE = "TRUE",
parameter IODELAY_GRP = "IODELAY_MIG",
parameter ODT_WIDTH = 1,
parameter ROW_WIDTH = 14,
parameter ADDITIVE_LAT = 0,
parameter TWO_T_TIME_EN = 0,
parameter BURST_LEN = 4,
parameter BURST_TYPE = 0,
parameter CAS_LAT = 5,
parameter TWR = 15000,
parameter ECC_ENABLE = 0,
parameter ODT_TYPE = 1,
parameter DDR_TYPE = 1,
parameter REDUCE_DRV = 0,
parameter REG_ENABLE = 1,
parameter CLK_PERIOD = 3000,
parameter SIM_ONLY = 0,
parameter DEBUG_EN = 0,
parameter FPGA_SPEED_GRADE = 2
)
(
input clk0,
input clk90,
input clkdiv0,
input rst0,
input rst90,
input rstdiv0,
input ctrl_wren,
input [ROW_WIDTH-1:0] ctrl_addr,
input [BANK_WIDTH-1:0] ctrl_ba,
input ctrl_ras_n,
input ctrl_cas_n,
input ctrl_we_n,
input [CS_NUM-1:0] ctrl_cs_n,
input ctrl_rden,
input ctrl_ref_flag,
input [(2*DQ_WIDTH)-1:0] wdf_data,
input [(2*DQ_WIDTH/8)-1:0] wdf_mask_data,
output wdf_rden,
output phy_init_done,
output [DQS_WIDTH-1:0] phy_calib_rden,
output [DQS_WIDTH-1:0] phy_calib_rden_sel,
output [DQ_WIDTH-1:0] rd_data_rise,
output [DQ_WIDTH-1:0] rd_data_fall,
output [CLK_WIDTH-1:0] ddr_ck,
output [CLK_WIDTH-1:0] ddr_ck_n,
output [ROW_WIDTH-1:0] ddr_addr,
output [BANK_WIDTH-1:0] ddr_ba,
output ddr_ras_n,
output ddr_cas_n,
output ddr_we_n,
output [CS_WIDTH-1:0] ddr_cs_n,
output [CKE_WIDTH-1:0] ddr_cke,
output [ODT_WIDTH-1:0] ddr_odt,
output [DM_WIDTH-1:0] ddr_dm,
inout [DQS_WIDTH-1:0] ddr_dqs,
inout [DQS_WIDTH-1:0] ddr_dqs_n,
inout [DQ_WIDTH-1:0] ddr_dq,
// Debug signals (optional use)
input dbg_idel_up_all,
input dbg_idel_down_all,
input dbg_idel_up_dq,
input dbg_idel_down_dq,
input dbg_idel_up_dqs,
input dbg_idel_down_dqs,
input dbg_idel_up_gate,
input dbg_idel_down_gate,
input [DQ_BITS-1:0] dbg_sel_idel_dq,
input dbg_sel_all_idel_dq,
input [DQS_BITS:0] dbg_sel_idel_dqs,
input dbg_sel_all_idel_dqs,
input [DQS_BITS:0] dbg_sel_idel_gate,
input dbg_sel_all_idel_gate,
output [3:0] dbg_calib_done,
output [3:0] dbg_calib_err,
output [(6*DQ_WIDTH)-1:0] dbg_calib_dq_tap_cnt,
output [(6*DQS_WIDTH)-1:0] dbg_calib_dqs_tap_cnt,
output [(6*DQS_WIDTH)-1:0] dbg_calib_gate_tap_cnt,
output [DQS_WIDTH-1:0] dbg_calib_rd_data_sel,
output [(5*DQS_WIDTH)-1:0] dbg_calib_rden_dly,
output [(5*DQS_WIDTH)-1:0] dbg_calib_gate_dly
);
 
wire [3:0] calib_done;
wire calib_ref_done;
wire calib_ref_req;
wire [3:0] calib_start;
wire dm_ce;
wire [1:0] dq_oe_n;
wire dqs_oe_n;
wire dqs_rst_n;
wire [(DQ_WIDTH/8)-1:0] mask_data_fall;
wire [(DQ_WIDTH/8)-1:0] mask_data_rise;
wire [CS_NUM-1:0] odt;
wire [ROW_WIDTH-1:0] phy_init_addr;
wire [BANK_WIDTH-1:0] phy_init_ba;
wire phy_init_cas_n;
wire [CKE_WIDTH-1:0] phy_init_cke;
wire [CS_NUM-1:0] phy_init_cs_n;
wire phy_init_data_sel;
wire phy_init_ras_n;
wire phy_init_rden;
wire phy_init_we_n;
wire phy_init_wren;
wire [DQ_WIDTH-1:0] wr_data_fall;
wire [DQ_WIDTH-1:0] wr_data_rise;
 
//***************************************************************************
 
ddr2_phy_write #
(
.DQ_WIDTH (DQ_WIDTH),
.CS_NUM (CS_NUM),
.ADDITIVE_LAT (ADDITIVE_LAT),
.CAS_LAT (CAS_LAT),
.ECC_ENABLE (ECC_ENABLE),
.ODT_TYPE (ODT_TYPE),
.REG_ENABLE (REG_ENABLE),
.DDR_TYPE (DDR_TYPE)
)
u_phy_write
(
.clk0 (clk0),
.clk90 (clk90),
.rst90 (rst90),
.wdf_data (wdf_data),
.wdf_mask_data (wdf_mask_data),
.ctrl_wren (ctrl_wren),
.phy_init_wren (phy_init_wren),
.phy_init_data_sel (phy_init_data_sel),
.dm_ce (dm_ce),
.dq_oe_n (dq_oe_n),
.dqs_oe_n (dqs_oe_n),
.dqs_rst_n (dqs_rst_n),
.wdf_rden (wdf_rden),
.odt (odt),
.wr_data_rise (wr_data_rise),
.wr_data_fall (wr_data_fall),
.mask_data_rise (mask_data_rise),
.mask_data_fall (mask_data_fall)
);
 
ddr2_phy_io #
(
.CLK_WIDTH (CLK_WIDTH),
.USE_DM_PORT (USE_DM_PORT),
.DM_WIDTH (DM_WIDTH),
.DQ_WIDTH (DQ_WIDTH),
.DQ_BITS (DQ_BITS),
.DQ_PER_DQS (DQ_PER_DQS),
.DQS_BITS (DQS_BITS),
.DQS_WIDTH (DQS_WIDTH),
.HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
.IODELAY_GRP (IODELAY_GRP),
.ODT_WIDTH (ODT_WIDTH),
.ADDITIVE_LAT (ADDITIVE_LAT),
.CAS_LAT (CAS_LAT),
.REG_ENABLE (REG_ENABLE),
.CLK_PERIOD (CLK_PERIOD),
.DDR_TYPE (DDR_TYPE),
.SIM_ONLY (SIM_ONLY),
.DEBUG_EN (DEBUG_EN),
.FPGA_SPEED_GRADE (FPGA_SPEED_GRADE)
)
u_phy_io
(
.clk0 (clk0),
.clk90 (clk90),
.clkdiv0 (clkdiv0),
.rst0 (rst0),
.rst90 (rst90),
.rstdiv0 (rstdiv0),
.dm_ce (dm_ce),
.dq_oe_n (dq_oe_n),
.dqs_oe_n (dqs_oe_n),
.dqs_rst_n (dqs_rst_n),
.calib_start (calib_start),
.ctrl_rden (ctrl_rden),
.phy_init_rden (phy_init_rden),
.calib_ref_done (calib_ref_done),
.calib_done (calib_done),
.calib_ref_req (calib_ref_req),
.calib_rden (phy_calib_rden),
.calib_rden_sel (phy_calib_rden_sel),
.wr_data_rise (wr_data_rise),
.wr_data_fall (wr_data_fall),
.mask_data_rise (mask_data_rise),
.mask_data_fall (mask_data_fall),
.rd_data_rise (rd_data_rise),
.rd_data_fall (rd_data_fall),
.ddr_ck (ddr_ck),
.ddr_ck_n (ddr_ck_n),
.ddr_dm (ddr_dm),
.ddr_dqs (ddr_dqs),
.ddr_dqs_n (ddr_dqs_n),
.ddr_dq (ddr_dq),
.dbg_idel_up_all (dbg_idel_up_all),
.dbg_idel_down_all (dbg_idel_down_all),
.dbg_idel_up_dq (dbg_idel_up_dq),
.dbg_idel_down_dq (dbg_idel_down_dq),
.dbg_idel_up_dqs (dbg_idel_up_dqs),
.dbg_idel_down_dqs (dbg_idel_down_dqs),
.dbg_idel_up_gate (dbg_idel_up_gate),
.dbg_idel_down_gate (dbg_idel_down_gate),
.dbg_sel_idel_dq (dbg_sel_idel_dq),
.dbg_sel_all_idel_dq (dbg_sel_all_idel_dq),
.dbg_sel_idel_dqs (dbg_sel_idel_dqs),
.dbg_sel_all_idel_dqs (dbg_sel_all_idel_dqs),
.dbg_sel_idel_gate (dbg_sel_idel_gate),
.dbg_sel_all_idel_gate (dbg_sel_all_idel_gate),
.dbg_calib_done (dbg_calib_done),
.dbg_calib_err (dbg_calib_err),
.dbg_calib_dq_tap_cnt (dbg_calib_dq_tap_cnt),
.dbg_calib_dqs_tap_cnt (dbg_calib_dqs_tap_cnt),
.dbg_calib_gate_tap_cnt (dbg_calib_gate_tap_cnt),
.dbg_calib_rd_data_sel (dbg_calib_rd_data_sel),
.dbg_calib_rden_dly (dbg_calib_rden_dly),
.dbg_calib_gate_dly (dbg_calib_gate_dly)
);
 
ddr2_phy_ctl_io #
(
.BANK_WIDTH (BANK_WIDTH),
.CKE_WIDTH (CKE_WIDTH),
.COL_WIDTH (COL_WIDTH),
.CS_NUM (CS_NUM),
.CS_WIDTH (CS_WIDTH),
.TWO_T_TIME_EN (TWO_T_TIME_EN),
.ODT_WIDTH (ODT_WIDTH),
.ROW_WIDTH (ROW_WIDTH),
.DDR_TYPE (DDR_TYPE)
)
u_phy_ctl_io
(
.clk0 (clk0),
.clk90 (clk90),
.rst0 (rst0),
.rst90 (rst90),
.ctrl_addr (ctrl_addr),
.ctrl_ba (ctrl_ba),
.ctrl_ras_n (ctrl_ras_n),
.ctrl_cas_n (ctrl_cas_n),
.ctrl_we_n (ctrl_we_n),
.ctrl_cs_n (ctrl_cs_n),
.phy_init_addr (phy_init_addr),
.phy_init_ba (phy_init_ba),
.phy_init_ras_n (phy_init_ras_n),
.phy_init_cas_n (phy_init_cas_n),
.phy_init_we_n (phy_init_we_n),
.phy_init_cs_n (phy_init_cs_n),
.phy_init_cke (phy_init_cke),
.phy_init_data_sel (phy_init_data_sel),
.odt (odt),
.ddr_addr (ddr_addr),
.ddr_ba (ddr_ba),
.ddr_ras_n (ddr_ras_n),
.ddr_cas_n (ddr_cas_n),
.ddr_we_n (ddr_we_n),
.ddr_cke (ddr_cke),
.ddr_cs_n (ddr_cs_n),
.ddr_odt (ddr_odt)
);
 
ddr2_phy_init #
(
.BANK_WIDTH (BANK_WIDTH),
.CKE_WIDTH (CKE_WIDTH),
.COL_WIDTH (COL_WIDTH),
.CS_BITS (CS_BITS),
.CS_NUM (CS_NUM),
.DQ_WIDTH (DQ_WIDTH),
.ODT_WIDTH (ODT_WIDTH),
.ROW_WIDTH (ROW_WIDTH),
.ADDITIVE_LAT (ADDITIVE_LAT),
.BURST_LEN (BURST_LEN),
.BURST_TYPE (BURST_TYPE),
.TWO_T_TIME_EN(TWO_T_TIME_EN),
.CAS_LAT (CAS_LAT),
.ODT_TYPE (ODT_TYPE),
.REDUCE_DRV (REDUCE_DRV),
.REG_ENABLE (REG_ENABLE),
.TWR (TWR),
.CLK_PERIOD (CLK_PERIOD),
.DDR_TYPE (DDR_TYPE),
.SIM_ONLY (SIM_ONLY)
)
u_phy_init
(
.clk0 (clk0),
.clkdiv0 (clkdiv0),
.rst0 (rst0),
.rstdiv0 (rstdiv0),
.calib_done (calib_done),
.ctrl_ref_flag (ctrl_ref_flag),
.calib_ref_req (calib_ref_req),
.calib_start (calib_start),
.calib_ref_done (calib_ref_done),
.phy_init_wren (phy_init_wren),
.phy_init_rden (phy_init_rden),
.phy_init_addr (phy_init_addr),
.phy_init_ba (phy_init_ba),
.phy_init_ras_n (phy_init_ras_n),
.phy_init_cas_n (phy_init_cas_n),
.phy_init_we_n (phy_init_we_n),
.phy_init_cs_n (phy_init_cs_n),
.phy_init_cke (phy_init_cke),
.phy_init_done (phy_init_done),
.phy_init_data_sel (phy_init_data_sel)
);
 
endmodule
/boards/xilinx/ml501/rtl/verilog/xilinx_ddr2/ddr2_phy_init.v
0,0 → 1,1189
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007, 2008 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_phy_init.v
// /___/ /\ Date Last Modified: $Date: 2008/12/23 14:26:00 $
// \ \ / \ Date Created: Thu Aug 24 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR2
//Purpose:
//Reference:
// This module is the intialization control logic of the memory interface.
// All commands are issued from here acoording to the burst, CAS Latency and
// the user commands.
//Revision History:
// Rev 1.1 - Localparam WR_RECOVERY added and mapped to
// load mode register. PK. 14/7/08
// Rev 1.2 - To issue an Auto Refresh command to each chip during various
// calibration stages logic modified. PK. 08/10/08
//*****************************************************************************
 
`timescale 1ns/1ps
 
module ddr2_phy_init #
(
// Following parameters are for 72-bit RDIMM design (for ML561 Reference
// board design). Actual values may be different. Actual parameters values
// are passed from design top module ddr2_mig module. Please refer to
// the ddr2_mig module for actual values.
parameter BANK_WIDTH = 2,
parameter CKE_WIDTH = 1,
parameter COL_WIDTH = 10,
parameter CS_BITS = 0,
parameter CS_NUM = 1,
parameter DQ_WIDTH = 72,
parameter ODT_WIDTH = 1,
parameter ROW_WIDTH = 14,
parameter ADDITIVE_LAT = 0,
parameter BURST_LEN = 4,
parameter TWO_T_TIME_EN = 0,
parameter BURST_TYPE = 0,
parameter CAS_LAT = 5,
parameter ODT_TYPE = 1,
parameter REDUCE_DRV = 0,
parameter REG_ENABLE = 1,
parameter TWR = 15000,
parameter CLK_PERIOD = 3000,
parameter DDR_TYPE = 1,
parameter SIM_ONLY = 0
)
(
input clk0,
input clkdiv0,
input rst0,
input rstdiv0,
input [3:0] calib_done,
input ctrl_ref_flag,
input calib_ref_req,
output reg [3:0] calib_start,
output reg calib_ref_done,
output reg phy_init_wren,
output reg phy_init_rden,
output [ROW_WIDTH-1:0] phy_init_addr,
output [BANK_WIDTH-1:0] phy_init_ba,
output phy_init_ras_n,
output phy_init_cas_n,
output phy_init_we_n,
output [CS_NUM-1:0] phy_init_cs_n,
output [CKE_WIDTH-1:0] phy_init_cke,
output reg phy_init_done,
output phy_init_data_sel
);
 
// time to wait between consecutive commands in PHY_INIT - this is a
// generic number, and must be large enough to account for worst case
// timing parameter (tRFC - refresh-to-active) across all memory speed
// grades and operating frequencies. Expressed in CLKDIV clock cycles.
localparam CNTNEXT_CMD = 7'b1111111;
// time to wait between read and read or precharge for stage 3 & 4
// the larger CNTNEXT_CMD can also be used, use smaller number to
// speed up calibration - avoid tRAS violation, and speeds up simulation
localparam CNTNEXT_RD = 4'b1111;
 
// Write recovery (WR) time - is defined by
// tWR (in nanoseconds) by tCK (in nanoseconds) and rounding up a
// noninteger value to the next integer
localparam integer WR_RECOVERY = ((TWR + CLK_PERIOD) - 1)/CLK_PERIOD;
localparam CS_BITS_FIX = (CS_BITS == 0) ? 1 : CS_BITS;
 
localparam INIT_CAL1_READ = 5'h00;
localparam INIT_CAL2_READ = 5'h01;
localparam INIT_CAL3_READ = 5'h02;
localparam INIT_CAL4_READ = 5'h03;
localparam INIT_CAL1_WRITE = 5'h04;
localparam INIT_CAL2_WRITE = 5'h05;
localparam INIT_CAL3_WRITE = 5'h06;
localparam INIT_DUMMY_ACTIVE_WAIT = 5'h07;
localparam INIT_PRECHARGE = 5'h08;
localparam INIT_LOAD_MODE = 5'h09;
localparam INIT_AUTO_REFRESH = 5'h0A;
localparam INIT_IDLE = 5'h0B;
localparam INIT_CNT_200 = 5'h0C;
localparam INIT_CNT_200_WAIT = 5'h0D;
localparam INIT_PRECHARGE_WAIT = 5'h0E;
localparam INIT_MODE_REGISTER_WAIT = 5'h0F;
localparam INIT_AUTO_REFRESH_WAIT = 5'h10;
localparam INIT_DEEP_MEMORY_ST = 5'h11;
localparam INIT_DUMMY_ACTIVE = 5'h12;
localparam INIT_CAL1_WRITE_READ = 5'h13;
localparam INIT_CAL1_READ_WAIT = 5'h14;
localparam INIT_CAL2_WRITE_READ = 5'h15;
localparam INIT_CAL2_READ_WAIT = 5'h16;
localparam INIT_CAL3_WRITE_READ = 5'h17;
localparam INIT_CAL3_READ_WAIT = 5'h18;
localparam INIT_CAL4_READ_WAIT = 5'h19;
localparam INIT_CALIB_REF = 5'h1A;
localparam INIT_ZQCL = 5'h1B;
localparam INIT_WAIT_DLLK_ZQINIT = 5'h1C;
 
localparam INIT_CNTR_INIT = 4'h0;
localparam INIT_CNTR_PRECH_1 = 4'h1;
localparam INIT_CNTR_EMR2_INIT = 4'h2;
localparam INIT_CNTR_EMR3_INIT = 4'h3;
localparam INIT_CNTR_EMR_EN_DLL = 4'h4;
localparam INIT_CNTR_MR_RST_DLL = 4'h5;
localparam INIT_CNTR_CNT_200_WAIT = 4'h6;
localparam INIT_CNTR_PRECH_2 = 4'h7;
localparam INIT_CNTR_AR_1 = 4'h8;
localparam INIT_CNTR_AR_2 = 4'h9;
localparam INIT_CNTR_MR_ACT_DLL = 4'hA;
localparam INIT_CNTR_EMR_DEF_OCD = 4'hB;
localparam INIT_CNTR_EMR_EXIT_OCD = 4'hC;
localparam INIT_CNTR_DEEP_MEM = 4'hD;
localparam INIT_CNTR_PRECH_3 = 4'hE;
localparam INIT_CNTR_DONE = 4'hF;
 
localparam DDR1 = 0;
localparam DDR2 = 1;
localparam DDR3 = 2;
 
reg [CS_BITS_FIX :0] auto_cnt_r;
reg [1:0] burst_addr_r;
reg [1:0] burst_cnt_r;
wire [1:0] burst_val;
wire cal_read;
wire cal_write;
wire cal_write_read;
reg cal1_started_r;
reg cal2_started_r;
reg cal4_started_r;
reg [3:0] calib_done_r;
reg calib_ref_req_posedge;
reg calib_ref_req_r;
reg [15:0] calib_start_shift0_r;
reg [15:0] calib_start_shift1_r;
reg [15:0] calib_start_shift2_r;
reg [15:0] calib_start_shift3_r;
reg [1:0] chip_cnt_r;
reg [4:0] cke_200us_cnt_r;
reg cke_200us_cnt_en_r;
reg [7:0] cnt_200_cycle_r;
reg cnt_200_cycle_done_r;
reg [6:0] cnt_cmd_r;
reg cnt_cmd_ok_r;
reg [3:0] cnt_rd_r;
reg cnt_rd_ok_r;
reg ctrl_ref_flag_r;
reg done_200us_r;
reg [ROW_WIDTH-1:0] ddr_addr_r;
reg [ROW_WIDTH-1:0] ddr_addr_r1;
reg [BANK_WIDTH-1:0] ddr_ba_r;
reg [BANK_WIDTH-1:0] ddr_ba_r1;
reg ddr_cas_n_r;
reg ddr_cas_n_r1;
reg [CKE_WIDTH-1:0] ddr_cke_r;
reg [CS_NUM-1:0] ddr_cs_n_r;
reg [CS_NUM-1:0] ddr_cs_n_r1;
reg [CS_NUM-1:0] ddr_cs_disable_r;
reg ddr_ras_n_r;
reg ddr_ras_n_r1;
reg ddr_we_n_r;
reg ddr_we_n_r1;
wire [15:0] ext_mode_reg;
reg [3:0] init_cnt_r;
reg init_done_r;
reg [4:0] init_next_state;
reg [4:0] init_state_r;
reg [4:0] init_state_r1;
reg [4:0] init_state_r1_2t;
reg [4:0] init_state_r2;
wire [15:0] load_mode_reg;
wire [15:0] load_mode_reg0;
wire [15:0] load_mode_reg1;
wire [15:0] load_mode_reg2;
wire [15:0] load_mode_reg3;
reg phy_init_done_r;
reg phy_init_done_r1;
reg phy_init_done_r2;
reg phy_init_done_r3;
reg refresh_req;
wire [3:0] start_cal;
 
//***************************************************************************
 
//*****************************************************************
// DDR1 and DDR2 Load mode register
// Mode Register (MR):
// [15:14] - unused - 00
// [13] - reserved - 0
// [12] - Power-down mode - 0 (normal)
// [11:9] - write recovery - for Auto Precharge (tWR/tCK)
// [8] - DLL reset - 0 or 1
// [7] - Test Mode - 0 (normal)
// [6:4] - CAS latency - CAS_LAT
// [3] - Burst Type - BURST_TYPE
// [2:0] - Burst Length - BURST_LEN
//*****************************************************************
 
generate
if (DDR_TYPE == DDR2) begin: gen_load_mode_reg_ddr2
assign load_mode_reg[2:0] = (BURST_LEN == 8) ? 3'b011 :
((BURST_LEN == 4) ? 3'b010 : 3'b111);
assign load_mode_reg[3] = BURST_TYPE;
assign load_mode_reg[6:4] = (CAS_LAT == 3) ? 3'b011 :
((CAS_LAT == 4) ? 3'b100 :
((CAS_LAT == 5) ? 3'b101 : 3'b111));
assign load_mode_reg[7] = 1'b0;
assign load_mode_reg[8] = 1'b0; // init value only (DLL not reset)
assign load_mode_reg[11:9] = (WR_RECOVERY == 6) ? 3'b101 :
((WR_RECOVERY == 5) ? 3'b100 :
((WR_RECOVERY == 4) ? 3'b011 :
((WR_RECOVERY == 3) ? 3'b010 :
3'b001)));
assign load_mode_reg[15:12] = 4'b000;
end else if (DDR_TYPE == DDR1)begin: gen_load_mode_reg_ddr1
assign load_mode_reg[2:0] = (BURST_LEN == 8) ? 3'b011 :
((BURST_LEN == 4) ? 3'b010 :
((BURST_LEN == 2) ? 3'b001 : 3'b111));
assign load_mode_reg[3] = BURST_TYPE;
assign load_mode_reg[6:4] = (CAS_LAT == 2) ? 3'b010 :
((CAS_LAT == 3) ? 3'b011 :
((CAS_LAT == 25) ? 3'b110 : 3'b111));
assign load_mode_reg[12:7] = 6'b000000; // init value only
assign load_mode_reg[15:13] = 3'b000;
end
endgenerate
 
//*****************************************************************
// DDR1 and DDR2 ext mode register
// Extended Mode Register (MR):
// [15:14] - unused - 00
// [13] - reserved - 0
// [12] - output enable - 0 (enabled)
// [11] - RDQS enable - 0 (disabled)
// [10] - DQS# enable - 0 (enabled)
// [9:7] - OCD Program - 111 or 000 (first 111, then 000 during init)
// [6] - RTT[1] - RTT[1:0] = 0(no ODT), 1(75), 2(150), 3(50)
// [5:3] - Additive CAS - ADDITIVE_CAS
// [2] - RTT[0]
// [1] - Output drive - REDUCE_DRV (= 0(full), = 1 (reduced)
// [0] - DLL enable - 0 (normal)
//*****************************************************************
 
generate
if (DDR_TYPE == DDR2) begin: gen_ext_mode_reg_ddr2
assign ext_mode_reg[0] = 1'b0;
assign ext_mode_reg[1] = REDUCE_DRV;
assign ext_mode_reg[2] = ((ODT_TYPE == 1) || (ODT_TYPE == 3)) ?
1'b1 : 1'b0;
assign ext_mode_reg[5:3] = (ADDITIVE_LAT == 0) ? 3'b000 :
((ADDITIVE_LAT == 1) ? 3'b001 :
((ADDITIVE_LAT == 2) ? 3'b010 :
((ADDITIVE_LAT == 3) ? 3'b011 :
((ADDITIVE_LAT == 4) ? 3'b100 :
3'b111))));
assign ext_mode_reg[6] = ((ODT_TYPE == 2) || (ODT_TYPE == 3)) ?
1'b1 : 1'b0;
assign ext_mode_reg[9:7] = 3'b000;
assign ext_mode_reg[10] = 1'b0;
assign ext_mode_reg[15:10] = 6'b000000;
end else if (DDR_TYPE == DDR1)begin: gen_ext_mode_reg_ddr1
assign ext_mode_reg[0] = 1'b0;
assign ext_mode_reg[1] = REDUCE_DRV;
assign ext_mode_reg[12:2] = 11'b00000000000;
assign ext_mode_reg[15:13] = 3'b000;
end
endgenerate
 
//*****************************************************************
// DDR3 Load mode reg0
// Mode Register (MR0):
// [15:13] - unused - 000
// [12] - Precharge Power-down DLL usage - 0 (DLL frozen, slow-exit),
// 1 (DLL maintained)
// [11:9] - write recovery for Auto Precharge (tWR/tCK = 6)
// [8] - DLL reset - 0 or 1
// [7] - Test Mode - 0 (normal)
// [6:4],[2] - CAS latency - CAS_LAT
// [3] - Burst Type - BURST_TYPE
// [1:0] - Burst Length - BURST_LEN
//*****************************************************************
 
generate
if (DDR_TYPE == DDR3) begin: gen_load_mode_reg0_ddr3
assign load_mode_reg0[1:0] = (BURST_LEN == 8) ? 2'b00 :
((BURST_LEN == 4) ? 2'b10 : 2'b11);
// Part of CAS latency. This bit is '0' for all CAS latencies
assign load_mode_reg0[2] = 1'b0;
assign load_mode_reg0[3] = BURST_TYPE;
assign load_mode_reg0[6:4] = (CAS_LAT == 5) ? 3'b001 :
(CAS_LAT == 6) ? 3'b010 : 3'b111;
assign load_mode_reg0[7] = 1'b0;
// init value only (DLL reset)
assign load_mode_reg0[8] = 1'b1;
assign load_mode_reg0[11:9] = 3'b010;
// Precharge Power-Down DLL 'slow-exit'
assign load_mode_reg0[12] = 1'b0;
assign load_mode_reg0[15:13] = 3'b000;
end
endgenerate
 
//*****************************************************************
// DDR3 Load mode reg1
// Mode Register (MR1):
// [15:13] - unused - 00
// [12] - output enable - 0 (enabled for DQ, DQS, DQS#)
// [11] - TDQS enable - 0 (TDQS disabled and DM enabled)
// [10] - reserved - 0 (must be '0')
// [9] - RTT[2] - 0
// [8] - reserved - 0 (must be '0')
// [7] - write leveling - 0 (disabled), 1 (enabled)
// [6] - RTT[1] - RTT[1:0] = 0(no ODT), 1(75), 2(150), 3(50)
// [5] - Output driver impedance[1] - 0 (RZQ/6 and RZQ/7)
// [4:3] - Additive CAS - ADDITIVE_CAS
// [2] - RTT[0]
// [1] - Output driver impedance[0] - 0(RZQ/6), or 1 (RZQ/7)
// [0] - DLL enable - 0 (normal)
//*****************************************************************
 
generate
if (DDR_TYPE == DDR3) begin: gen_ext_mode_reg1_ddr3
// DLL enabled during Imitialization
assign load_mode_reg1[0] = 1'b0;
// RZQ/6
assign load_mode_reg1[1] = REDUCE_DRV;
assign load_mode_reg1[2] = ((ODT_TYPE == 1) || (ODT_TYPE == 3)) ?
1'b1 : 1'b0;
assign load_mode_reg1[4:3] = (ADDITIVE_LAT == 0) ? 2'b00 :
((ADDITIVE_LAT == 1) ? 2'b01 :
((ADDITIVE_LAT == 2) ? 2'b10 :
3'b111));
// RZQ/6
assign load_mode_reg1[5] = 1'b0;
assign load_mode_reg1[6] = ((ODT_TYPE == 2) || (ODT_TYPE == 3)) ?
1'b1 : 1'b0;
// Make zero WRITE_LEVEL
assign load_mode_reg1[7] = 0;
assign load_mode_reg1[8] = 1'b0;
assign load_mode_reg1[9] = 1'b0;
assign load_mode_reg1[10] = 1'b0;
assign load_mode_reg1[15:11] = 5'b00000;
end
endgenerate
 
//*****************************************************************
// DDR3 Load mode reg2
// Mode Register (MR2):
// [15:11] - unused - 00
// [10:9] - RTT_WR - 00 (Dynamic ODT off)
// [8] - reserved - 0 (must be '0')
// [7] - self-refresh temperature range -
// 0 (normal), 1 (extended)
// [6] - Auto Self-Refresh - 0 (manual), 1(auto)
// [5:3] - CAS Write Latency (CWL) -
// 000 (5 for 400 MHz device),
// 001 (6 for 400 MHz to 533 MHz devices),
// 010 (7 for 533 MHz to 667 MHz devices),
// 011 (8 for 667 MHz to 800 MHz)
// [2:0] - Partial Array Self-Refresh (Optional) -
// 000 (full array)
//*****************************************************************
 
generate
if (DDR_TYPE == DDR3) begin: gen_ext_mode_reg2_ddr3
assign load_mode_reg2[2:0] = 3'b000;
assign load_mode_reg2[5:3] = (CAS_LAT == 5) ? 3'b000 :
(CAS_LAT == 6) ? 3'b001 : 3'b111;
assign load_mode_reg2[6] = 1'b0; // Manual Self-Refresh
assign load_mode_reg2[7] = 1'b0;
assign load_mode_reg2[8] = 1'b0;
assign load_mode_reg2[10:9] = 2'b00;
assign load_mode_reg2[15:11] = 5'b00000;
end
endgenerate
 
//*****************************************************************
// DDR3 Load mode reg3
// Mode Register (MR3):
// [15:3] - unused - All zeros
// [2] - MPR Operation - 0(normal operation), 1(data flow from MPR)
// [1:0] - MPR location - 00 (Predefined pattern)
//*****************************************************************
 
generate
if (DDR_TYPE == DDR3)begin: gen_ext_mode_reg3_ddr3
assign load_mode_reg3[1:0] = 2'b00;
assign load_mode_reg3[2] = 1'b0;
assign load_mode_reg3[15:3] = 13'b0000000000000;
end
endgenerate
 
//***************************************************************************
// Logic for calibration start, and for auto-refresh during cal request
// CALIB_REF_REQ is used by calibration logic to request auto-refresh
// durign calibration (used to avoid tRAS violation is certain calibration
// stages take a long time). Once the auto-refresh is complete and cal can
// be resumed, CALIB_REF_DONE is asserted by PHY_INIT.
//***************************************************************************
 
// generate pulse for each of calibration start controls
assign start_cal[0] = ((init_state_r1 == INIT_CAL1_READ) &&
(init_state_r2 != INIT_CAL1_READ));
assign start_cal[1] = ((init_state_r1 == INIT_CAL2_READ) &&
(init_state_r2 != INIT_CAL2_READ));
assign start_cal[2] = ((init_state_r1 == INIT_CAL3_READ) &&
(init_state_r2 == INIT_CAL3_WRITE_READ));
assign start_cal[3] = ((init_state_r1 == INIT_CAL4_READ) &&
(init_state_r2 == INIT_DUMMY_ACTIVE_WAIT));
 
// Generate positive-edge triggered, latched signal to force initialization
// to pause calibration, and to issue auto-refresh. Clear flag as soon as
// refresh initiated
always @(posedge clkdiv0)
if (rstdiv0) begin
calib_ref_req_r <= 1'b0;
calib_ref_req_posedge <= 1'b0;
refresh_req <= 1'b0;
end else begin
calib_ref_req_r <= calib_ref_req;
calib_ref_req_posedge <= calib_ref_req & ~calib_ref_req_r;
if (init_state_r1 == INIT_AUTO_REFRESH)
refresh_req <= 1'b0;
else if (calib_ref_req_posedge)
refresh_req <= 1'b1;
end
 
// flag to tell cal1 calibration was started.
// This flag is used for cal1 auto refreshes
// some of these bits may not be needed - only needed for those stages that
// need refreshes within the stage (i.e. very long stages)
always @(posedge clkdiv0)
if (rstdiv0) begin
cal1_started_r <= 1'b0;
cal2_started_r <= 1'b0;
cal4_started_r <= 1'b0;
end else begin
if (calib_start[0])
cal1_started_r <= 1'b1;
if (calib_start[1])
cal2_started_r <= 1'b1;
if (calib_start[3])
cal4_started_r <= 1'b1;
end
 
// Delay start of each calibration by 16 clock cycles to
// ensure that when calibration logic begins, that read data is already
// appearing on the bus. Don't really need it, it's more for simulation
// purposes. Each circuit should synthesize using an SRL16.
// In first stage of calibration periodic auto refreshes
// will be issued to meet memory timing. calib_start_shift0_r[15] will be
// asserted more than once.calib_start[0] is anded with cal1_started_r so
// that it is asserted only once. cal1_refresh_done is anded with
// cal1_started_r so that it is asserted after the auto refreshes.
always @(posedge clkdiv0) begin
calib_start_shift0_r <= {calib_start_shift0_r[14:0], start_cal[0]};
calib_start_shift1_r <= {calib_start_shift1_r[14:0], start_cal[1]};
calib_start_shift2_r <= {calib_start_shift2_r[14:0], start_cal[2]};
calib_start_shift3_r <= {calib_start_shift3_r[14:0], start_cal[3]};
calib_start[0] <= calib_start_shift0_r[15] & ~cal1_started_r;
calib_start[1] <= calib_start_shift1_r[15] & ~cal2_started_r;
calib_start[2] <= calib_start_shift2_r[15];
calib_start[3] <= calib_start_shift3_r[15] & ~cal4_started_r;
calib_ref_done <= calib_start_shift0_r[15] |
calib_start_shift1_r[15] |
calib_start_shift3_r[15];
end
 
// generate delay for various states that require it (no maximum delay
// requirement, make sure that terminal count is large enough to cover
// all cases)
always @(posedge clkdiv0) begin
case (init_state_r)
INIT_PRECHARGE_WAIT,
INIT_MODE_REGISTER_WAIT,
INIT_AUTO_REFRESH_WAIT,
INIT_DUMMY_ACTIVE_WAIT,
INIT_CAL1_WRITE_READ,
INIT_CAL1_READ_WAIT,
INIT_CAL2_WRITE_READ,
INIT_CAL2_READ_WAIT,
INIT_CAL3_WRITE_READ:
cnt_cmd_r <= cnt_cmd_r + 1;
default:
cnt_cmd_r <= 7'b0000000;
endcase
end
 
// assert when count reaches the value
always @(posedge clkdiv0) begin
if(cnt_cmd_r == CNTNEXT_CMD)
cnt_cmd_ok_r <= 1'b1;
else
cnt_cmd_ok_r <= 1'b0;
end
 
always @(posedge clkdiv0) begin
case (init_state_r)
INIT_CAL3_READ_WAIT,
INIT_CAL4_READ_WAIT:
cnt_rd_r <= cnt_rd_r + 1;
default:
cnt_rd_r <= 4'b0000;
endcase
end
 
always @(posedge clkdiv0) begin
if(cnt_rd_r == CNTNEXT_RD)
cnt_rd_ok_r <= 1'b1;
else
cnt_rd_ok_r <= 1'b0;
end
 
//***************************************************************************
// Initial delay after power-on
//***************************************************************************
 
// register the refresh flag from the controller.
// The refresh flag is in full frequency domain - so a pulsed version must
// be generated for half freq domain using 2 consecutive full clk cycles
// The registered version is used for the 200us counter
always @(posedge clk0)
ctrl_ref_flag_r <= ctrl_ref_flag;
always @(posedge clkdiv0)
cke_200us_cnt_en_r <= ctrl_ref_flag || ctrl_ref_flag_r;
 
// 200us counter for cke
always @(posedge clkdiv0)
if (rstdiv0) begin
// skip power-up count if only simulating
if (SIM_ONLY)
cke_200us_cnt_r <= 5'b00001;
else
cke_200us_cnt_r <= 5'd27;
end else if (cke_200us_cnt_en_r)
cke_200us_cnt_r <= cke_200us_cnt_r - 1;
 
always @(posedge clkdiv0)
if (rstdiv0)
done_200us_r <= 1'b0;
else if (!done_200us_r)
done_200us_r <= (cke_200us_cnt_r == 5'b00000);
 
// 200 clocks counter - count value : h'64 required for initialization
// Counts 100 divided by two clocks
always @(posedge clkdiv0)
if (rstdiv0 || (init_state_r == INIT_CNT_200))
cnt_200_cycle_r <= 8'h64;
else if (init_state_r == INIT_ZQCL) // ddr3
cnt_200_cycle_r <= 8'hC8;
else if (cnt_200_cycle_r != 8'h00)
cnt_200_cycle_r <= cnt_200_cycle_r - 1;
 
always @(posedge clkdiv0)
if (rstdiv0 || (init_state_r == INIT_CNT_200)
|| (init_state_r == INIT_ZQCL))
cnt_200_cycle_done_r <= 1'b0;
else if (cnt_200_cycle_r == 8'h00)
cnt_200_cycle_done_r <= 1'b1;
 
//*****************************************************************
// handle deep memory configuration:
// During initialization: Repeat initialization sequence once for each
// chip select. Note that we could perform initalization for all chip
// selects simulataneously. Probably fine - any potential SI issues with
// auto refreshing all chip selects at once?
// Once initialization complete, assert only CS[1] for calibration.
//*****************************************************************
 
always @(posedge clkdiv0)
if (rstdiv0) begin
chip_cnt_r <= 2'b00;
end else if (init_state_r == INIT_DEEP_MEMORY_ST) begin
if (chip_cnt_r != CS_NUM)
chip_cnt_r <= chip_cnt_r + 1;
else
chip_cnt_r <= 2'b00;
// MIG 2.4: Modified to issue an Auto Refresh commmand
// to each chip select during various calibration stages
end else if (init_state_r == INIT_PRECHARGE && init_done_r) begin
chip_cnt_r <= 2'b00;
end else if (init_state_r1 == INIT_AUTO_REFRESH && init_done_r) begin
if (chip_cnt_r < (CS_NUM-1))
chip_cnt_r <= chip_cnt_r + 1;
end
 
// keep track of which chip selects got auto-refreshed (avoid auto-refreshing
// all CS's at once to avoid current spike)
always @(posedge clkdiv0)begin
if (rstdiv0 || init_state_r == INIT_PRECHARGE)
auto_cnt_r <= 'd0;
else if (init_state_r == INIT_AUTO_REFRESH && init_done_r) begin
if (auto_cnt_r < CS_NUM)
auto_cnt_r <= auto_cnt_r + 1;
end
end
 
always @(posedge clkdiv0)
if (rstdiv0) begin
ddr_cs_n_r <= {CS_NUM{1'b1}};
end else begin
ddr_cs_n_r <= {CS_NUM{1'b1}};
if ((init_state_r == INIT_DUMMY_ACTIVE) ||
((init_state_r == INIT_PRECHARGE) && (~init_done_r))||
(init_state_r == INIT_LOAD_MODE) ||
(init_state_r == INIT_AUTO_REFRESH) ||
(init_state_r == INIT_ZQCL ) ||
(((init_state_r == INIT_CAL1_READ) ||
(init_state_r == INIT_CAL2_READ) ||
(init_state_r == INIT_CAL3_READ) ||
(init_state_r == INIT_CAL4_READ) ||
(init_state_r == INIT_CAL1_WRITE) ||
(init_state_r == INIT_CAL2_WRITE) ||
(init_state_r == INIT_CAL3_WRITE)) && (burst_cnt_r == 2'b00)))
ddr_cs_n_r[chip_cnt_r] <= 1'b0;
else if (init_state_r == INIT_PRECHARGE)
ddr_cs_n_r <= {CS_NUM{1'b0}};
else
ddr_cs_n_r[chip_cnt_r] <= 1'b1;
end
 
//***************************************************************************
// Write/read burst logic
//***************************************************************************
 
assign cal_write = ((init_state_r == INIT_CAL1_WRITE) ||
(init_state_r == INIT_CAL2_WRITE) ||
(init_state_r == INIT_CAL3_WRITE));
assign cal_read = ((init_state_r == INIT_CAL1_READ) ||
(init_state_r == INIT_CAL2_READ) ||
(init_state_r == INIT_CAL3_READ) ||
(init_state_r == INIT_CAL4_READ));
assign cal_write_read = ((init_state_r == INIT_CAL1_READ) ||
(init_state_r == INIT_CAL2_READ) ||
(init_state_r == INIT_CAL3_READ) ||
(init_state_r == INIT_CAL4_READ) ||
(init_state_r == INIT_CAL1_WRITE) ||
(init_state_r == INIT_CAL2_WRITE) ||
(init_state_r == INIT_CAL3_WRITE));
 
assign burst_val = (BURST_LEN == 4) ? 2'b00 :
(BURST_LEN == 8) ? 2'b01 : 2'b00;
 
// keep track of current address - need this if burst length < 8 for
// stage 2-4 calibration writes and reads. Make sure value always gets
// initialized to 0 before we enter write/read state. This is used to
// keep track of when another burst must be issued
always @(posedge clkdiv0)
if (cal_write_read)
burst_addr_r <= burst_addr_r + 2;
else
burst_addr_r <= 2'b00;
 
// write/read burst count
always @(posedge clkdiv0)
if (cal_write_read)
if (burst_cnt_r == 2'b00)
burst_cnt_r <= burst_val;
else // SHOULD THIS BE -2 CHECK THIS LOGIC
burst_cnt_r <= burst_cnt_r - 1;
else
burst_cnt_r <= 2'b00;
 
// indicate when a write is occurring
always @(posedge clkdiv0)
// MIG 2.1: Remove (burst_addr_r<4) term - not used
// phy_init_wren <= cal_write && (burst_addr_r < 3'd4);
phy_init_wren <= cal_write;
 
// used for read enable calibration, pulse to indicate when read issued
always @(posedge clkdiv0)
// MIG 2.1: Remove (burst_addr_r<4) term - not used
// phy_init_rden <= cal_read && (burst_addr_r < 3'd4);
phy_init_rden <= cal_read;
 
//***************************************************************************
// Initialization state machine
//***************************************************************************
 
always @(posedge clkdiv0)
// every time we need to initialize another rank of memory, need to
// reset init count, and repeat the entire initialization (but not
// calibration) sequence
if (rstdiv0 || (init_state_r == INIT_DEEP_MEMORY_ST))
init_cnt_r <= INIT_CNTR_INIT;
else if ((DDR_TYPE == DDR1) && (init_state_r == INIT_PRECHARGE) &&
(init_cnt_r == INIT_CNTR_PRECH_1))
// skip EMR(2) and EMR(3) register loads
init_cnt_r <= INIT_CNTR_EMR_EN_DLL;
else if ((DDR_TYPE == DDR1) && (init_state_r == INIT_LOAD_MODE) &&
(init_cnt_r == INIT_CNTR_MR_ACT_DLL))
// skip OCD calibration for DDR1
init_cnt_r <= INIT_CNTR_DEEP_MEM;
else if ((DDR_TYPE == DDR3) && (init_state_r == INIT_ZQCL))
// skip states for DDR3
init_cnt_r <= INIT_CNTR_DEEP_MEM;
else if ((init_state_r == INIT_LOAD_MODE) ||
((init_state_r == INIT_PRECHARGE)
&& (init_state_r1 != INIT_CALIB_REF))||
((init_state_r == INIT_AUTO_REFRESH)
&& (~init_done_r))||
(init_state_r == INIT_CNT_200))
init_cnt_r <= init_cnt_r + 1;
 
always @(posedge clkdiv0) begin
if ((init_state_r == INIT_IDLE) && (init_cnt_r == INIT_CNTR_DONE)) begin
phy_init_done_r <= 1'b1;
end else
phy_init_done_r <= 1'b0;
end
 
// phy_init_done to the controller and the user interface.
// It is delayed by four clocks to account for the
// multi cycle path constraint to the (phy_init_data_sel)
// to the phy layer.
always @(posedge clkdiv0)begin
phy_init_done_r1 <= phy_init_done_r;
phy_init_done_r2 <= phy_init_done_r1;
phy_init_done_r3 <= phy_init_done_r2;
phy_init_done <= phy_init_done_r3;
end
 
// Instantiate primitive to allow this flop to be attached to multicycle
// path constraint in UCF. This signal goes to PHY_WRITE and PHY_CTL_IO
// datapath logic only. Because it is a multi-cycle path, it can be
// clocked by either CLKDIV0 or CLK0.
FDRSE u_ff_phy_init_data_sel
(
.Q (phy_init_data_sel),
.C (clkdiv0),
.CE (1'b1),
.D (phy_init_done_r1),
.R (1'b0),
.S (1'b0)
) /* synthesis syn_preserve=1 */
/* synthesis syn_replicate = 0 */;
 
//synthesis translate_off
always @(posedge calib_done[0])
$display ("First Stage Calibration completed at time %t", $time);
 
always @(posedge calib_done[1])
$display ("Second Stage Calibration completed at time %t", $time);
 
always @(posedge calib_done[2]) begin
$display ("Third Stage Calibration completed at time %t", $time);
end
 
always @(posedge calib_done[3]) begin
$display ("Fourth Stage Calibration completed at time %t", $time);
$display ("Calibration completed at time %t", $time);
end
//synthesis translate_on
 
always @(posedge clkdiv0) begin
if ((init_cnt_r >= INIT_CNTR_DEEP_MEM))begin
init_done_r <= 1'b1;
end else
init_done_r <= 1'b0;
end
 
//*****************************************************************
 
always @(posedge clkdiv0)
if (rstdiv0) begin
init_state_r <= INIT_IDLE;
init_state_r1 <= INIT_IDLE;
init_state_r2 <= INIT_IDLE;
calib_done_r <= 4'b0000;
end else begin
init_state_r <= init_next_state;
init_state_r1 <= init_state_r;
init_state_r2 <= init_state_r1;
calib_done_r <= calib_done; // register for timing
end
 
always @(*) begin
init_next_state = init_state_r;
(* full_case, parallel_case *) case (init_state_r)
INIT_IDLE: begin
if (done_200us_r) begin
(* parallel_case *) case (init_cnt_r)
INIT_CNTR_INIT:
init_next_state = INIT_CNT_200;
INIT_CNTR_PRECH_1:
init_next_state = INIT_PRECHARGE;
INIT_CNTR_EMR2_INIT:
init_next_state = INIT_LOAD_MODE; // EMR(2)
INIT_CNTR_EMR3_INIT:
init_next_state = INIT_LOAD_MODE; // EMR(3);
INIT_CNTR_EMR_EN_DLL:
init_next_state = INIT_LOAD_MODE; // EMR, enable DLL
INIT_CNTR_MR_RST_DLL:
init_next_state = INIT_LOAD_MODE; // MR, reset DLL
INIT_CNTR_CNT_200_WAIT:begin
if(DDR_TYPE == DDR3)
init_next_state = INIT_ZQCL; // DDR3
else
// Wait 200cc after reset DLL
init_next_state = INIT_CNT_200;
end
INIT_CNTR_PRECH_2:
init_next_state = INIT_PRECHARGE;
INIT_CNTR_AR_1:
init_next_state = INIT_AUTO_REFRESH;
INIT_CNTR_AR_2:
init_next_state = INIT_AUTO_REFRESH;
INIT_CNTR_MR_ACT_DLL:
init_next_state = INIT_LOAD_MODE; // MR, unreset DLL
INIT_CNTR_EMR_DEF_OCD:
init_next_state = INIT_LOAD_MODE; // EMR, OCD default
INIT_CNTR_EMR_EXIT_OCD:
init_next_state = INIT_LOAD_MODE; // EMR, enable OCD exit
INIT_CNTR_DEEP_MEM: begin
if ((chip_cnt_r < CS_NUM-1))
init_next_state = INIT_DEEP_MEMORY_ST;
else if (cnt_200_cycle_done_r)
init_next_state = INIT_DUMMY_ACTIVE;
else
init_next_state = INIT_IDLE;
end
INIT_CNTR_PRECH_3:
init_next_state = INIT_PRECHARGE;
INIT_CNTR_DONE:
init_next_state = INIT_IDLE;
default :
init_next_state = INIT_IDLE;
endcase
end
end
INIT_CNT_200:
init_next_state = INIT_CNT_200_WAIT;
INIT_CNT_200_WAIT:
if (cnt_200_cycle_done_r)
init_next_state = INIT_IDLE;
INIT_PRECHARGE:
init_next_state = INIT_PRECHARGE_WAIT;
INIT_PRECHARGE_WAIT:
if (cnt_cmd_ok_r)begin
if (init_done_r && (!(&calib_done_r)))
init_next_state = INIT_AUTO_REFRESH;
else
init_next_state = INIT_IDLE;
end
INIT_ZQCL:
init_next_state = INIT_WAIT_DLLK_ZQINIT;
INIT_WAIT_DLLK_ZQINIT:
if (cnt_200_cycle_done_r)
init_next_state = INIT_IDLE;
INIT_LOAD_MODE:
init_next_state = INIT_MODE_REGISTER_WAIT;
INIT_MODE_REGISTER_WAIT:
if (cnt_cmd_ok_r)
init_next_state = INIT_IDLE;
INIT_AUTO_REFRESH:
init_next_state = INIT_AUTO_REFRESH_WAIT;
INIT_AUTO_REFRESH_WAIT:
// MIG 2.4: Modified to issue an Auto Refresh commmand
// to each chip select during various calibration stages
if (auto_cnt_r < CS_NUM && init_done_r) begin
if (cnt_cmd_ok_r)
init_next_state = INIT_AUTO_REFRESH;
end else if (cnt_cmd_ok_r)begin
if(init_done_r)
init_next_state = INIT_DUMMY_ACTIVE;
else
init_next_state = INIT_IDLE;
end
INIT_DEEP_MEMORY_ST:
init_next_state = INIT_IDLE;
// single row activate. All subsequent calibration writes and
// read will take place in this row
INIT_DUMMY_ACTIVE:
init_next_state = INIT_DUMMY_ACTIVE_WAIT;
INIT_DUMMY_ACTIVE_WAIT:
if (cnt_cmd_ok_r)begin
if (~calib_done_r[0]) begin
// if returning to stg1 after refresh, don't need to write
if (cal1_started_r)
init_next_state = INIT_CAL1_READ;
// if first entering stg1, need to write training pattern
else
init_next_state = INIT_CAL1_WRITE;
end else if (~calib_done[1]) begin
if (cal2_started_r)
init_next_state = INIT_CAL2_READ;
else
init_next_state = INIT_CAL2_WRITE;
end else if (~calib_done_r[2])
init_next_state = INIT_CAL3_WRITE;
else
init_next_state = INIT_CAL4_READ;
end
// Stage 1 calibration (write and continuous read)
INIT_CAL1_WRITE:
if (burst_addr_r == 2'b10)
init_next_state = INIT_CAL1_WRITE_READ;
INIT_CAL1_WRITE_READ:
if (cnt_cmd_ok_r)
init_next_state = INIT_CAL1_READ;
INIT_CAL1_READ:
// Stage 1 requires inter-stage auto-refresh
if (calib_done_r[0] || refresh_req)
init_next_state = INIT_CAL1_READ_WAIT;
INIT_CAL1_READ_WAIT:
if (cnt_cmd_ok_r)
init_next_state = INIT_CALIB_REF;
// Stage 2 calibration (write and continuous read)
INIT_CAL2_WRITE:
if (burst_addr_r == 2'b10)
init_next_state = INIT_CAL2_WRITE_READ;
INIT_CAL2_WRITE_READ:
if (cnt_cmd_ok_r)
init_next_state = INIT_CAL2_READ;
INIT_CAL2_READ:
// Stage 2 requires inter-stage auto-refresh
if (calib_done_r[1] || refresh_req)
init_next_state = INIT_CAL2_READ_WAIT;
INIT_CAL2_READ_WAIT:
if(cnt_cmd_ok_r)
init_next_state = INIT_CALIB_REF;
// Stage 3 calibration (write and continuous read)
INIT_CAL3_WRITE:
if (burst_addr_r == 2'b10)
init_next_state = INIT_CAL3_WRITE_READ;
INIT_CAL3_WRITE_READ:
if (cnt_cmd_ok_r)
init_next_state = INIT_CAL3_READ;
INIT_CAL3_READ:
if (burst_addr_r == 2'b10)
init_next_state = INIT_CAL3_READ_WAIT;
INIT_CAL3_READ_WAIT: begin
if (cnt_rd_ok_r)
if (calib_done_r[2]) begin
init_next_state = INIT_CALIB_REF;
end else
init_next_state = INIT_CAL3_READ;
end
// Stage 4 calibration (continuous read only, same pattern as stage 3)
// only used if DQS_GATE supported
INIT_CAL4_READ:
if (burst_addr_r == 2'b10)
init_next_state = INIT_CAL4_READ_WAIT;
INIT_CAL4_READ_WAIT: begin
if (cnt_rd_ok_r)
// Stage 4 requires inter-stage auto-refresh
if (calib_done_r[3] || refresh_req)
init_next_state = INIT_PRECHARGE;
else
init_next_state = INIT_CAL4_READ;
end
INIT_CALIB_REF:
init_next_state = INIT_PRECHARGE;
endcase
end
 
//***************************************************************************
// Memory control/address
//***************************************************************************
 
always @(posedge clkdiv0)
if ((init_state_r == INIT_DUMMY_ACTIVE) ||
(init_state_r == INIT_PRECHARGE) ||
(init_state_r == INIT_LOAD_MODE) ||
(init_state_r == INIT_AUTO_REFRESH)) begin
ddr_ras_n_r <= 1'b0;
end else begin
ddr_ras_n_r <= 1'b1;
end
 
always @(posedge clkdiv0)
if ((init_state_r == INIT_LOAD_MODE) ||
(init_state_r == INIT_AUTO_REFRESH) ||
(cal_write_read && (burst_cnt_r == 2'b00))) begin
ddr_cas_n_r <= 1'b0;
end else begin
ddr_cas_n_r <= 1'b1;
end
 
always @(posedge clkdiv0)
if ((init_state_r == INIT_LOAD_MODE) ||
(init_state_r == INIT_PRECHARGE) ||
(init_state_r == INIT_ZQCL) ||
(cal_write && (burst_cnt_r == 2'b00)))begin
ddr_we_n_r <= 1'b0;
end else begin
ddr_we_n_r <= 1'b1;
end
 
//*****************************************************************
// memory address during init
//*****************************************************************
 
always @(posedge clkdiv0) begin
if ((init_state_r == INIT_PRECHARGE)
|| (init_state_r == INIT_ZQCL))begin
// Precharge all - set A10 = 1
ddr_addr_r <= {ROW_WIDTH{1'b0}};
ddr_addr_r[10] <= 1'b1;
ddr_ba_r <= {BANK_WIDTH{1'b0}};
end else if (init_state_r == INIT_LOAD_MODE) begin
ddr_ba_r <= {BANK_WIDTH{1'b0}};
ddr_addr_r <= {ROW_WIDTH{1'b0}};
case (init_cnt_r)
// EMR (2)
INIT_CNTR_EMR2_INIT: begin
ddr_ba_r[1:0] <= 2'b10;
ddr_addr_r <= {ROW_WIDTH{1'b0}};
end
// EMR (3)
INIT_CNTR_EMR3_INIT: begin
ddr_ba_r[1:0] <= 2'b11;
if(DDR_TYPE == DDR3)
ddr_addr_r <= load_mode_reg3[ROW_WIDTH-1:0];
else
ddr_addr_r <= {ROW_WIDTH{1'b0}};
end
// EMR write - A0 = 0 for DLL enable
INIT_CNTR_EMR_EN_DLL: begin
ddr_ba_r[1:0] <= 2'b01;
if(DDR_TYPE == DDR3)
ddr_addr_r <= load_mode_reg1[ROW_WIDTH-1:0];
else
ddr_addr_r <= ext_mode_reg[ROW_WIDTH-1:0];
end
// MR write, reset DLL (A8=1)
INIT_CNTR_MR_RST_DLL: begin
if(DDR_TYPE == DDR3)
ddr_addr_r <= load_mode_reg0[ROW_WIDTH-1:0];
else
ddr_addr_r <= load_mode_reg[ROW_WIDTH-1:0];
ddr_ba_r[1:0] <= 2'b00;
ddr_addr_r[8] <= 1'b1;
end
// MR write, unreset DLL (A8=0)
INIT_CNTR_MR_ACT_DLL: begin
ddr_ba_r[1:0] <= 2'b00;
ddr_addr_r <= load_mode_reg[ROW_WIDTH-1:0];
end
// EMR write, OCD default state
INIT_CNTR_EMR_DEF_OCD: begin
ddr_ba_r[1:0] <= 2'b01;
ddr_addr_r <= ext_mode_reg[ROW_WIDTH-1:0];
ddr_addr_r[9:7] <= 3'b111;
end
// EMR write - OCD exit
INIT_CNTR_EMR_EXIT_OCD: begin
ddr_ba_r[1:0] <= 2'b01;
ddr_addr_r <= ext_mode_reg[ROW_WIDTH-1:0];
end
default: begin
ddr_ba_r <= {BANK_WIDTH{1'bx}};
ddr_addr_r <= {ROW_WIDTH{1'bx}};
end
endcase
end else if (cal_write_read) begin
// when writing or reading for Stages 2-4, since training pattern is
// either 4 (stage 2) or 8 (stage 3-4) long, if BURST LEN < 8, then
// need to issue multiple bursts to read entire training pattern
ddr_addr_r[ROW_WIDTH-1:3] <= {ROW_WIDTH-4{1'b0}};
ddr_addr_r[2:0] <= {burst_addr_r, 1'b0};
ddr_ba_r <= {BANK_WIDTH-1{1'b0}};
end else if (init_state_r == INIT_DUMMY_ACTIVE) begin
// all calibration writing read takes place in row 0x0 only
ddr_ba_r <= {BANK_WIDTH{1'b0}};
ddr_addr_r <= {ROW_WIDTH{1'b0}};
end else begin
// otherwise, cry me a river
ddr_ba_r <= {BANK_WIDTH{1'bx}};
ddr_addr_r <= {ROW_WIDTH{1'bx}};
end
end
 
// Keep CKE asserted after initial power-on delay
always @(posedge clkdiv0)
ddr_cke_r <= {CKE_WIDTH{done_200us_r}};
 
// register commands to memory. Two clock cycle delay from state -> output
always @(posedge clk0) begin
ddr_addr_r1 <= ddr_addr_r;
ddr_ba_r1 <= ddr_ba_r;
ddr_cas_n_r1 <= ddr_cas_n_r;
ddr_ras_n_r1 <= ddr_ras_n_r;
ddr_we_n_r1 <= ddr_we_n_r;
ddr_cs_n_r1 <= ddr_cs_n_r;
end // always @ (posedge clk0)
 
always @(posedge clk0)
init_state_r1_2t <= init_state_r1;
 
// logic to toggle chip select. The chip_select is
// clocked of clkdiv0 and will be asserted for
// two clock cycles.
always @(posedge clk0) begin
if(rst0)
ddr_cs_disable_r <= {CS_NUM{1'b0}};
else begin
if(| ddr_cs_disable_r)
ddr_cs_disable_r <= {CS_NUM{1'b0}};
else begin
if (TWO_T_TIME_EN) begin
if (init_state_r1_2t == INIT_PRECHARGE && init_done_r)
ddr_cs_disable_r <= 'd3;
else
ddr_cs_disable_r[chip_cnt_r] <= ~ddr_cs_n_r1[chip_cnt_r];
end
else begin
if (init_state_r1 == INIT_PRECHARGE && init_done_r)
ddr_cs_disable_r <= 'd3;
else
ddr_cs_disable_r[chip_cnt_r] <= ~ddr_cs_n_r[chip_cnt_r];
end
end
end
end
 
 
assign phy_init_addr = ddr_addr_r;
assign phy_init_ba = ddr_ba_r;
assign phy_init_cas_n = ddr_cas_n_r;
assign phy_init_cke = ddr_cke_r;
assign phy_init_ras_n = ddr_ras_n_r;
assign phy_init_we_n = ddr_we_n_r;
assign phy_init_cs_n = (TWO_T_TIME_EN) ?
ddr_cs_n_r1 | ddr_cs_disable_r
: ddr_cs_n_r| ddr_cs_disable_r;
 
endmodule
/boards/xilinx/ml501/rtl/verilog/xilinx_ddr2/ddr2_phy_io.v
0,0 → 1,353
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007, 2008 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_phy_io.v
// /___/ /\ Date Last Modified: $Date: 2009/01/15 14:22:14 $
// \ \ / \ Date Created: Wed Aug 16 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR2
//Purpose:
// This module instantiates calibration logic, data, data strobe and the
// data mask iobs.
//Reference:
//Revision History:
// Rev 1.1 - DM_IOB instance made based on USE_DM_PORT value . PK. 25/6/08
// Rev 1.2 - Parameter HIGH_PERFORMANCE_MODE added. PK. 7/10/08
// Rev 1.3 - Parameter IODELAY_GRP added. PK. 11/27/08
//*****************************************************************************
 
`timescale 1ns/1ps
 
module ddr2_phy_io #
(
// Following parameters are for 72-bit RDIMM design (for ML561 Reference
// board design). Actual values may be different. Actual parameters values
// are passed from design top module ddr2_mig module. Please refer to
// the ddr2_mig module for actual values.
parameter CLK_WIDTH = 1,
parameter USE_DM_PORT = 1,
parameter DM_WIDTH = 9,
parameter DQ_WIDTH = 72,
parameter DQ_BITS = 7,
parameter DQ_PER_DQS = 8,
parameter DQS_BITS = 4,
parameter DQS_WIDTH = 9,
parameter HIGH_PERFORMANCE_MODE = "TRUE",
parameter IODELAY_GRP = "IODELAY_MIG",
parameter ODT_WIDTH = 1,
parameter ADDITIVE_LAT = 0,
parameter CAS_LAT = 5,
parameter REG_ENABLE = 1,
parameter CLK_PERIOD = 3000,
parameter DDR_TYPE = 1,
parameter SIM_ONLY = 0,
parameter DEBUG_EN = 0,
parameter FPGA_SPEED_GRADE = 2
)
(
input clk0,
input clk90,
input clkdiv0,
input rst0,
input rst90,
input rstdiv0,
input dm_ce,
input [1:0] dq_oe_n,
input dqs_oe_n,
input dqs_rst_n,
input [3:0] calib_start,
input ctrl_rden,
input phy_init_rden,
input calib_ref_done,
output [3:0] calib_done,
output calib_ref_req,
output [DQS_WIDTH-1:0] calib_rden,
output [DQS_WIDTH-1:0] calib_rden_sel,
input [DQ_WIDTH-1:0] wr_data_rise,
input [DQ_WIDTH-1:0] wr_data_fall,
input [(DQ_WIDTH/8)-1:0] mask_data_rise,
input [(DQ_WIDTH/8)-1:0] mask_data_fall,
output [(DQ_WIDTH)-1:0] rd_data_rise,
output [(DQ_WIDTH)-1:0] rd_data_fall,
output [CLK_WIDTH-1:0] ddr_ck,
output [CLK_WIDTH-1:0] ddr_ck_n,
output [DM_WIDTH-1:0] ddr_dm,
inout [DQS_WIDTH-1:0] ddr_dqs,
inout [DQS_WIDTH-1:0] ddr_dqs_n,
inout [DQ_WIDTH-1:0] ddr_dq,
// Debug signals (optional use)
input dbg_idel_up_all,
input dbg_idel_down_all,
input dbg_idel_up_dq,
input dbg_idel_down_dq,
input dbg_idel_up_dqs,
input dbg_idel_down_dqs,
input dbg_idel_up_gate,
input dbg_idel_down_gate,
input [DQ_BITS-1:0] dbg_sel_idel_dq,
input dbg_sel_all_idel_dq,
input [DQS_BITS:0] dbg_sel_idel_dqs,
input dbg_sel_all_idel_dqs,
input [DQS_BITS:0] dbg_sel_idel_gate,
input dbg_sel_all_idel_gate,
output [3:0] dbg_calib_done,
output [3:0] dbg_calib_err,
output [(6*DQ_WIDTH)-1:0] dbg_calib_dq_tap_cnt,
output [(6*DQS_WIDTH)-1:0] dbg_calib_dqs_tap_cnt,
output [(6*DQS_WIDTH)-1:0] dbg_calib_gate_tap_cnt,
output [DQS_WIDTH-1:0] dbg_calib_rd_data_sel,
output [(5*DQS_WIDTH)-1:0] dbg_calib_rden_dly,
output [(5*DQS_WIDTH)-1:0] dbg_calib_gate_dly
);
 
// ratio of # of physical DM outputs to bytes in data bus
// may be different - e.g. if using x4 components
localparam DM_TO_BYTE_RATIO = DM_WIDTH / (DQ_WIDTH/8);
 
wire [CLK_WIDTH-1:0] ddr_ck_q;
wire [DQS_WIDTH-1:0] delayed_dqs;
wire [DQ_WIDTH-1:0] dlyce_dq;
wire [DQS_WIDTH-1:0] dlyce_dqs;
wire [DQS_WIDTH-1:0] dlyce_gate;
wire [DQ_WIDTH-1:0] dlyinc_dq;
wire [DQS_WIDTH-1:0] dlyinc_dqs;
wire [DQS_WIDTH-1:0] dlyinc_gate;
wire dlyrst_dq;
wire dlyrst_dqs;
wire [DQS_WIDTH-1:0] dlyrst_gate;
wire [DQS_WIDTH-1:0] dq_ce;
(* KEEP = "TRUE" *) wire [DQS_WIDTH-1:0] en_dqs /* synthesis syn_keep = 1 */;
wire [DQS_WIDTH-1:0] rd_data_sel;
 
//***************************************************************************
 
ddr2_phy_calib #
(
.DQ_WIDTH (DQ_WIDTH),
.DQ_BITS (DQ_BITS),
.DQ_PER_DQS (DQ_PER_DQS),
.DQS_BITS (DQS_BITS),
.DQS_WIDTH (DQS_WIDTH),
.ADDITIVE_LAT (ADDITIVE_LAT),
.CAS_LAT (CAS_LAT),
.REG_ENABLE (REG_ENABLE),
.CLK_PERIOD (CLK_PERIOD),
.SIM_ONLY (SIM_ONLY),
.DEBUG_EN (DEBUG_EN)
)
u_phy_calib
(
.clk (clk0),
.clkdiv (clkdiv0),
.rstdiv (rstdiv0),
.calib_start (calib_start),
.ctrl_rden (ctrl_rden),
.phy_init_rden (phy_init_rden),
.rd_data_rise (rd_data_rise),
.rd_data_fall (rd_data_fall),
.calib_ref_done (calib_ref_done),
.calib_done (calib_done),
.calib_ref_req (calib_ref_req),
.calib_rden (calib_rden),
.calib_rden_sel (calib_rden_sel),
.dlyrst_dq (dlyrst_dq),
.dlyce_dq (dlyce_dq),
.dlyinc_dq (dlyinc_dq),
.dlyrst_dqs (dlyrst_dqs),
.dlyce_dqs (dlyce_dqs),
.dlyinc_dqs (dlyinc_dqs),
.dlyrst_gate (dlyrst_gate),
.dlyce_gate (dlyce_gate),
.dlyinc_gate (dlyinc_gate),
.en_dqs (en_dqs),
.rd_data_sel (rd_data_sel),
.dbg_idel_up_all (dbg_idel_up_all),
.dbg_idel_down_all (dbg_idel_down_all),
.dbg_idel_up_dq (dbg_idel_up_dq),
.dbg_idel_down_dq (dbg_idel_down_dq),
.dbg_idel_up_dqs (dbg_idel_up_dqs),
.dbg_idel_down_dqs (dbg_idel_down_dqs),
.dbg_idel_up_gate (dbg_idel_up_gate),
.dbg_idel_down_gate (dbg_idel_down_gate),
.dbg_sel_idel_dq (dbg_sel_idel_dq),
.dbg_sel_all_idel_dq (dbg_sel_all_idel_dq),
.dbg_sel_idel_dqs (dbg_sel_idel_dqs),
.dbg_sel_all_idel_dqs (dbg_sel_all_idel_dqs),
.dbg_sel_idel_gate (dbg_sel_idel_gate),
.dbg_sel_all_idel_gate (dbg_sel_all_idel_gate),
.dbg_calib_done (dbg_calib_done),
.dbg_calib_err (dbg_calib_err),
.dbg_calib_dq_tap_cnt (dbg_calib_dq_tap_cnt),
.dbg_calib_dqs_tap_cnt (dbg_calib_dqs_tap_cnt),
.dbg_calib_gate_tap_cnt (dbg_calib_gate_tap_cnt),
.dbg_calib_rd_data_sel (dbg_calib_rd_data_sel),
.dbg_calib_rden_dly (dbg_calib_rden_dly),
.dbg_calib_gate_dly (dbg_calib_gate_dly)
);
 
//***************************************************************************
// Memory clock generation
//***************************************************************************
 
genvar ck_i;
generate
for(ck_i = 0; ck_i < CLK_WIDTH; ck_i = ck_i+1) begin: gen_ck
ODDR #
(
.SRTYPE ("SYNC"),
.DDR_CLK_EDGE ("OPPOSITE_EDGE")
)
u_oddr_ck_i
(
.Q (ddr_ck_q[ck_i]),
.C (clk0),
.CE (1'b1),
.D1 (1'b0),
.D2 (1'b1),
.R (1'b0),
.S (1'b0)
);
// Can insert ODELAY here if required
OBUFDS u_obuf_ck_i
(
.I (ddr_ck_q[ck_i]),
.O (ddr_ck[ck_i]),
.OB (ddr_ck_n[ck_i])
);
end
endgenerate
 
//***************************************************************************
// DQS instances
//***************************************************************************
 
genvar dqs_i;
generate
for(dqs_i = 0; dqs_i < DQS_WIDTH; dqs_i = dqs_i+1) begin: gen_dqs
ddr2_phy_dqs_iob #
(
.DDR_TYPE (DDR_TYPE),
.HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
.IODELAY_GRP (IODELAY_GRP)
)
u_iob_dqs
(
.clk0 (clk0),
.clkdiv0 (clkdiv0),
.rst0 (rst0),
.dlyinc_dqs (dlyinc_dqs[dqs_i]),
.dlyce_dqs (dlyce_dqs[dqs_i]),
.dlyrst_dqs (dlyrst_dqs),
.dlyinc_gate (dlyinc_gate[dqs_i]),
.dlyce_gate (dlyce_gate[dqs_i]),
.dlyrst_gate (dlyrst_gate[dqs_i]),
.dqs_oe_n (dqs_oe_n),
.dqs_rst_n (dqs_rst_n),
.en_dqs (en_dqs[dqs_i]),
.ddr_dqs (ddr_dqs[dqs_i]),
.ddr_dqs_n (ddr_dqs_n[dqs_i]),
.dq_ce (dq_ce[dqs_i]),
.delayed_dqs (delayed_dqs[dqs_i])
);
end
endgenerate
 
//***************************************************************************
// DM instances
//***************************************************************************
 
genvar dm_i;
generate
if (USE_DM_PORT) begin: gen_dm_inst
for(dm_i = 0; dm_i < DM_WIDTH; dm_i = dm_i+1) begin: gen_dm
ddr2_phy_dm_iob u_iob_dm
(
.clk90 (clk90),
.dm_ce (dm_ce),
.mask_data_rise (mask_data_rise[dm_i/DM_TO_BYTE_RATIO]),
.mask_data_fall (mask_data_fall[dm_i/DM_TO_BYTE_RATIO]),
.ddr_dm (ddr_dm[dm_i])
);
end
end
endgenerate
 
//***************************************************************************
// DQ IOB instances
//***************************************************************************
 
genvar dq_i;
generate
for(dq_i = 0; dq_i < DQ_WIDTH; dq_i = dq_i+1) begin: gen_dq
ddr2_phy_dq_iob #
(
.HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
.IODELAY_GRP (IODELAY_GRP),
.FPGA_SPEED_GRADE (FPGA_SPEED_GRADE)
)
u_iob_dq
(
.clk0 (clk0),
.clk90 (clk90),
.clkdiv0 (clkdiv0),
.rst90 (rst90),
.dlyinc (dlyinc_dq[dq_i]),
.dlyce (dlyce_dq[dq_i]),
.dlyrst (dlyrst_dq),
.dq_oe_n (dq_oe_n),
.dqs (delayed_dqs[dq_i/DQ_PER_DQS]),
.ce (dq_ce[dq_i/DQ_PER_DQS]),
.rd_data_sel (rd_data_sel[dq_i/DQ_PER_DQS]),
.wr_data_rise (wr_data_rise[dq_i]),
.wr_data_fall (wr_data_fall[dq_i]),
.rd_data_rise (rd_data_rise[dq_i]),
.rd_data_fall (rd_data_fall[dq_i]),
.ddr_dq (ddr_dq[dq_i])
);
end
endgenerate
 
endmodule
/boards/xilinx/ml501/rtl/verilog/xilinx_ddr2/ddr2_phy_ctl_io.v
0,0 → 1,302
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007, 2008 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_phy_ctl_io.v
// /___/ /\ Date Last Modified: $Date: 2008/12/23 14:26:00 $
// \ \ / \ Date Created: Thu Aug 24 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR2
//Purpose:
// This module puts the memory control signals like address, bank address,
// row address strobe, column address strobe, write enable and clock enable
// in the IOBs.
//Reference:
//Revision History:
//*****************************************************************************
 
`timescale 1ns/1ps
 
module ddr2_phy_ctl_io #
(
// Following parameters are for 72-bit RDIMM design (for ML561 Reference
// board design). Actual values may be different. Actual parameters values
// are passed from design top module ddr2_mig module. Please refer to
// the ddr2_mig module for actual values.
parameter BANK_WIDTH = 2,
parameter CKE_WIDTH = 1,
parameter COL_WIDTH = 10,
parameter CS_NUM = 1,
parameter TWO_T_TIME_EN = 0,
parameter CS_WIDTH = 1,
parameter ODT_WIDTH = 1,
parameter ROW_WIDTH = 14,
parameter DDR_TYPE = 1
)
(
input clk0,
input clk90,
input rst0,
input rst90,
input [ROW_WIDTH-1:0] ctrl_addr,
input [BANK_WIDTH-1:0] ctrl_ba,
input ctrl_ras_n,
input ctrl_cas_n,
input ctrl_we_n,
input [CS_NUM-1:0] ctrl_cs_n,
input [ROW_WIDTH-1:0] phy_init_addr,
input [BANK_WIDTH-1:0] phy_init_ba,
input phy_init_ras_n,
input phy_init_cas_n,
input phy_init_we_n,
input [CS_NUM-1:0] phy_init_cs_n,
input [CKE_WIDTH-1:0] phy_init_cke,
input phy_init_data_sel,
input [CS_NUM-1:0] odt,
output [ROW_WIDTH-1:0] ddr_addr,
output [BANK_WIDTH-1:0] ddr_ba,
output ddr_ras_n,
output ddr_cas_n,
output ddr_we_n,
output [CKE_WIDTH-1:0] ddr_cke,
output [CS_WIDTH-1:0] ddr_cs_n,
output [ODT_WIDTH-1:0] ddr_odt
);
 
reg [ROW_WIDTH-1:0] addr_mux;
reg [BANK_WIDTH-1:0] ba_mux;
reg cas_n_mux;
reg [CS_NUM-1:0] cs_n_mux;
reg ras_n_mux;
reg we_n_mux;
 
 
 
//***************************************************************************
 
 
 
 
// MUX to choose from either PHY or controller for SDRAM control
 
generate // in 2t timing mode the extra register stage cannot be used.
if(TWO_T_TIME_EN) begin // the control signals are asserted for two cycles
always @(*)begin
if (phy_init_data_sel) begin
addr_mux = ctrl_addr;
ba_mux = ctrl_ba;
cas_n_mux = ctrl_cas_n;
cs_n_mux = ctrl_cs_n;
ras_n_mux = ctrl_ras_n;
we_n_mux = ctrl_we_n;
end else begin
addr_mux = phy_init_addr;
ba_mux = phy_init_ba;
cas_n_mux = phy_init_cas_n;
cs_n_mux = phy_init_cs_n;
ras_n_mux = phy_init_ras_n;
we_n_mux = phy_init_we_n;
end
end
end else begin
always @(posedge clk0)begin // register the signals in non 2t mode
if (phy_init_data_sel) begin
addr_mux <= ctrl_addr;
ba_mux <= ctrl_ba;
cas_n_mux <= ctrl_cas_n;
cs_n_mux <= ctrl_cs_n;
ras_n_mux <= ctrl_ras_n;
we_n_mux <= ctrl_we_n;
end else begin
addr_mux <= phy_init_addr;
ba_mux <= phy_init_ba;
cas_n_mux <= phy_init_cas_n;
cs_n_mux <= phy_init_cs_n;
ras_n_mux <= phy_init_ras_n;
we_n_mux <= phy_init_we_n;
end
end
end
endgenerate
 
//***************************************************************************
// Output flop instantiation
// NOTE: Make sure all control/address flops are placed in IOBs
//***************************************************************************
 
// RAS: = 1 at reset
(* IOB = "FORCE" *) FDCPE u_ff_ras_n
(
.Q (ddr_ras_n),
.C (clk0),
.CE (1'b1),
.CLR (1'b0),
.D (ras_n_mux),
.PRE (rst0)
) /* synthesis syn_useioff = 1 */;
 
// CAS: = 1 at reset
(* IOB = "FORCE" *) FDCPE u_ff_cas_n
(
.Q (ddr_cas_n),
.C (clk0),
.CE (1'b1),
.CLR (1'b0),
.D (cas_n_mux),
.PRE (rst0)
) /* synthesis syn_useioff = 1 */;
 
// WE: = 1 at reset
(* IOB = "FORCE" *) FDCPE u_ff_we_n
(
.Q (ddr_we_n),
.C (clk0),
.CE (1'b1),
.CLR (1'b0),
.D (we_n_mux),
.PRE (rst0)
) /* synthesis syn_useioff = 1 */;
 
// CKE: = 0 at reset
genvar cke_i;
generate
for (cke_i = 0; cke_i < CKE_WIDTH; cke_i = cke_i + 1) begin: gen_cke
(* IOB = "FORCE" *) FDCPE u_ff_cke
(
.Q (ddr_cke[cke_i]),
.C (clk0),
.CE (1'b1),
.CLR (rst0),
.D (phy_init_cke[cke_i]),
.PRE (1'b0)
) /* synthesis syn_useioff = 1 */;
end
endgenerate
 
// chip select: = 1 at reset
// For unbuffered dimms the loading will be high. The chip select
// can be asserted early if the loading is very high. The
// code as is uses clock 0. If needed clock 270 can be used to
// toggle chip select 1/4 clock cycle early. The code has
// the clock 90 input for the early assertion of chip select.
 
genvar cs_i;
generate
for(cs_i = 0; cs_i < CS_WIDTH; cs_i = cs_i + 1) begin: gen_cs_n
if(TWO_T_TIME_EN) begin
(* IOB = "FORCE" *) FDCPE u_ff_cs_n
(
.Q (ddr_cs_n[cs_i]),
.C (clk0),
.CE (1'b1),
.CLR (1'b0),
.D (cs_n_mux[(cs_i*CS_NUM)/CS_WIDTH]),
.PRE (rst0)
) /* synthesis syn_useioff = 1 */;
end else begin // if (TWO_T_TIME_EN)
(* IOB = "FORCE" *) FDCPE u_ff_cs_n
(
.Q (ddr_cs_n[cs_i]),
.C (clk0),
.CE (1'b1),
.CLR (1'b0),
.D (cs_n_mux[(cs_i*CS_NUM)/CS_WIDTH]),
.PRE (rst0)
) /* synthesis syn_useioff = 1 */;
end // else: !if(TWO_T_TIME_EN)
end
endgenerate
 
// address: = X at reset
genvar addr_i;
generate
for (addr_i = 0; addr_i < ROW_WIDTH; addr_i = addr_i + 1) begin: gen_addr
(* IOB = "FORCE" *) FDCPE u_ff_addr
(
.Q (ddr_addr[addr_i]),
.C (clk0),
.CE (1'b1),
.CLR (1'b0),
.D (addr_mux[addr_i]),
.PRE (1'b0)
) /* synthesis syn_useioff = 1 */;
end
endgenerate
 
// bank address = X at reset
genvar ba_i;
generate
for (ba_i = 0; ba_i < BANK_WIDTH; ba_i = ba_i + 1) begin: gen_ba
(* IOB = "FORCE" *) FDCPE u_ff_ba
(
.Q (ddr_ba[ba_i]),
.C (clk0),
.CE (1'b1),
.CLR (1'b0),
.D (ba_mux[ba_i]),
.PRE (1'b0)
) /* synthesis syn_useioff = 1 */;
end
endgenerate
 
// ODT control = 0 at reset
genvar odt_i;
generate
if (DDR_TYPE > 0) begin: gen_odt_ddr2
for (odt_i = 0; odt_i < ODT_WIDTH; odt_i = odt_i + 1) begin: gen_odt
(* IOB = "FORCE" *) FDCPE u_ff_odt
(
.Q (ddr_odt[odt_i]),
.C (clk0),
.CE (1'b1),
.CLR (rst0),
.D (odt[(odt_i*CS_NUM)/ODT_WIDTH]),
.PRE (1'b0)
) /* synthesis syn_useioff = 1 */;
end
end
endgenerate
 
endmodule
/boards/xilinx/ml501/rtl/verilog/xilinx_ddr2/xilinx_ddr2_if.v
0,0 → 1,488
//////////////////////////////////////////////////////////////////////
//// ////
//// Xilinx DDR2 controller Wishbone Interface ////
//// ////
//// Description ////
//// Simple interface to the Xilinx MIG generated DDR2 controller////
//// ////
//// To Do: ////
//// Increase usage of cache BRAM to maximum (currently only ////
//// 256 bytes out of about 8192) ////
//// Make this a Wishbone B3 registered feedback burst friendly ////
//// server. ////
//// ////
//// Author(s): ////
//// - Julius Baxter, julius.baxter@orsoc.se ////
//// ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2010 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
/*
* The controller is design to stream lots of data out at the DDR2 controller's
* rate. All we implement here is enough to do the simplest accesses into a
* small cache, which eases the domain crossing headaches.
*
* This was originally written to handle a DDR2 part which is doing burst length
* of 4 as a minimum via a databus which is 64-bits wide.
*
* This means the smallest accesses is 4*64=256-bits or 32-bytes.
*
* We are bridging to a 32-bit wide system bus, so this means we must handle
* accesses in 8-word lots.
*
* A simple cache mechanism has been implemented, meaning we check if the cached
* data has been written to, and therefore needs writing back to the main memory
* before any other access can occur.
*
* Cache memory:
* The cache memory is a core-generated module, instantiating something out
* of the XilinxCoreLib. The reason is because an arrangement or RAMB36s with
* different sized A and B data in/out ports can't be instantiated directly
* for some reason.
* What we have is side A with 32-bits, and side B with 128-bits wide.
*
* TODO:
* This only supports 8-words for now but can easily be expanded, although
* multiple way/associativity caching will require some extra work to handle
* multiple cached addresses.
*
* But it should be easy enough to make this thing cache as much as its RAMB
* resources allow (4-RAMB16s becuase due to the 128-bit DDR2-side interface)
* which is about 8Kbyte.
*
* Multi-cycle paths:
* Write:
* To indicate that a writeback is occuring, a system-bus domain (wishbone, in
* this case) signal is set, and then sampled in the controller domain whenever
* a system-bus domain clock edge is detected. This register is "do_writeback"
* and then the controller domain register "ddr2_write_done" is asserted when
* the data has been written out of the RAMs and into the controller's fifos.
* "ddr2_write_done" is then sampled by the system-bus domain and "do_writeback"
* So there are paths between:
* ( register -> (sampled by) -> register )
* wb_clk:do_writeback -> ddr2_clk:do_writeback_ddr2_shifter
* wb_clk:do_writeback -> ddr2_clk:ddr2_write_done
* ddr2_clk:ddr2_write_done -> wb_clk:do_writeback
*
* Read:
* The only signal crossing we have here is the one indicating the read data
* has arrived into the cache RAM from the controller. The controller domain
* register "ddr2_read_done" is set, and sampled in the system-bus domain by the
* logic controlling the "do_readfrom" register. "ddr2_read_done" is cleared
* when the controller domain sees that "do_readfrom" has been de-asserted.
* So there are paths between:
* ( register -> (sampled by) -> register )
* ddr2_clk:ddr2_read_done -> wb_clk:do_readfrom
* wb_clk:do_readfrom -> ddr2_clk:ddr2_read_done
*
*/
module xilinx_ddr2_if (
input [31:0] wb_adr_i,
input wb_stb_i,
input wb_cyc_i,
input wb_we_i,
input [3:0] wb_sel_i,
input [31:0] wb_dat_i,
output [31:0] wb_dat_o,
output reg wb_ack_o,
 
output [12:0] ddr2_a,
output [1:0] ddr2_ba,
output ddr2_ras_n,
output ddr2_cas_n,
output ddr2_we_n,
output [1:0] ddr2_cs_n,
output [1:0] ddr2_odt,
output [1:0] ddr2_cke,
output [7:0] ddr2_dm,
 
inout [63:0] ddr2_dq,
inout [7:0] ddr2_dqs,
inout [7:0] ddr2_dqs_n,
output [1:0] ddr2_ck,
output [1:0] ddr2_ck_n,
 
input ddr2_if_clk,
input ddr2_if_rst,
input idly_clk_200,
input wb_clk,
input wb_rst);
`include "xilinx_ddr2_params.v"
 
wire ddr2_clk; // DDR2 iface domain clock.
wire ddr2_rst; // reset from the ddr2 module
wire wb_req;
reg wb_req_r;
reg wb_ack_o_r;
wire wb_req_new;
reg wb_req_new_r;
reg wb_req_addr_hit;
reg cached_addr_valid;
reg [31:6] cached_addr;
wire cache_hit;
reg cache_dirty;
reg [2:0] wb_req_cache_word_addr;
wire wb_cache_en;
reg do_writeback, do_writeback_r;
wire do_writeback_start, do_writeback_finished;
wire doing_writeback;
reg do_readfrom, do_readfrom_r;
wire do_readfrom_start, do_readfrom_finished;
wire doing_readfrom;
// Domain crossing logic
reg wb_clk_r;
reg wb_clk_in_ddr2_clk;
reg wb_clk_in_ddr2_clk_r;
wire wb_clk_edge;
reg [2:0] ddr2_clk_phase;
// Sample when clk phase is 0
reg [7:0] do_writeback_ddr2_shifter;
reg [7:0] do_writeback_ddr2_shifter_r;
reg do_writeback_ddr2_fifo_we;
reg ddr2_write_done;
// Currently, ddr2-side of cache is address is a single bit
reg [1:0] ddr2_cache_addr;
wire [127:0] ddr2_cache_data_o;
reg rd_data_valid_r;
reg ddr2_read_done;
// DDR2 MIG interface wires
wire app_af_afull;
wire app_wdf_afull;
wire app_wdf_wren;
wire app_af_wren;
wire [30:0] app_af_addr;
wire [2:0] app_af_cmd;
wire [(APPDATA_WIDTH)-1:0] app_wdf_data;
wire [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data;
wire rd_data_valid;
wire [(APPDATA_WIDTH)-1:0] rd_data_fifo_out;
wire phy_init_done;
assign cache_hit = (cached_addr == wb_adr_i[31:6]) & cached_addr_valid;
// Wishbone request detection
assign wb_req = wb_stb_i & wb_cyc_i & phy_init_done;
always @(posedge wb_clk)
wb_req_r <= wb_req;
assign wb_req_new = wb_req & !wb_req_r;
always @(posedge wb_clk)
wb_req_new_r <= wb_req_new;
// Register whether it's a hit or not
// As more lines are added, add them to this check.
always @(posedge wb_clk)
if (wb_rst)
wb_req_addr_hit <= 0;
else
wb_req_addr_hit <= wb_req & cache_hit & cached_addr_valid;
always @(posedge wb_clk)
if (wb_rst)
wb_ack_o <= 0;
else
wb_ack_o <= wb_req_addr_hit & !wb_ack_o & !wb_ack_o_r;
always @(posedge wb_clk)
wb_ack_o_r <= wb_ack_o;
// Address valid logic
always @(posedge wb_clk)
if (wb_rst)
cached_addr_valid <= 0;
else if (do_readfrom_finished)
cached_addr_valid <= 1;
else if ( do_writeback_finished ) // Data written back, cache not valid
cached_addr_valid <= 0;
else if (wb_req & !cache_hit & cached_addr_valid & !cache_dirty)
// Invalidate cache so a readfrom begins
cached_addr_valid <= 0;
// Address cacheing
always @(posedge wb_clk)
if (wb_rst)
cached_addr <= 0;
else if (do_readfrom_start)
cached_addr <= wb_adr_i[31:6];
// Cache dirty signal
always @(posedge wb_clk)
if (wb_rst)
cache_dirty <= 0;
else if (wb_req & wb_we_i & wb_req_addr_hit & wb_ack_o)
cache_dirty <= 1;
else if (!cached_addr_valid & cache_dirty)
cache_dirty <= 0;
 
// Wishbone side of cache enable. Important!
// 1. Enable on first access, if it's not a write
// 2. Enable if we've just refreshed the cache
// 3. Enable on ACK'ing for a write
assign wb_cache_en = (wb_req_new & !wb_we_i) | do_readfrom_finished |
(wb_req_addr_hit & wb_stb_i & !wb_we_i & !wb_ack_o) |
(wb_ack_o & wb_we_i);
// Writeback detect logic
always @(posedge wb_clk)
if (wb_rst)
do_writeback <= 0;
else if (ddr2_write_done) // DDR2 domain signal
do_writeback <= 0;
else if (wb_req & !cache_hit & cached_addr_valid & !doing_writeback & cache_dirty)
do_writeback <= 1;
always @(posedge wb_clk)
do_writeback_r <= do_writeback;
assign do_writeback_start = do_writeback & !do_writeback_r;
assign do_writeback_finished = !do_writeback & do_writeback_r;
assign doing_writeback = do_writeback | do_writeback_r;
// DDR2 Read detect logic
always @(posedge wb_clk)
if (wb_rst)
do_readfrom <= 0;
else if (ddr2_read_done) // DDR2 domain signal
do_readfrom <= 0;
else if (wb_req & !cache_hit & !cached_addr_valid & !doing_readfrom & !cache_dirty)
do_readfrom <= 1;
 
always @(posedge wb_clk)
do_readfrom_r <= do_readfrom;
 
assign do_readfrom_start = do_readfrom & !do_readfrom_r;
assign do_readfrom_finished = !do_readfrom & do_readfrom_r;
assign doing_readfrom = do_readfrom | do_readfrom_r;
 
// Address fifo signals
assign app_af_wren = (do_writeback_finished | do_readfrom_start);
assign app_af_cmd[0] = do_readfrom_start; // 1 - read, 0 - write
assign app_af_cmd[2:1] = 0;
assign app_af_addr = do_readfrom_start ? {2'd0, wb_adr_i[31:6],3'd0} :
{2'd0,cached_addr,3'd0};
assign app_wdf_wren = do_writeback_ddr2_fifo_we;
assign app_wdf_data = ddr2_cache_data_o;
assign app_wdf_mask_data = 0;
always @(posedge wb_clk) if (wb_rst) wb_clk_r <= 0; else wb_clk_r <= ~wb_clk_r;
always @(posedge ddr2_clk) wb_clk_in_ddr2_clk <= wb_clk_r;
always @(posedge ddr2_clk) wb_clk_in_ddr2_clk_r <= wb_clk_in_ddr2_clk;
assign wb_clk_edge = wb_clk_in_ddr2_clk & !wb_clk_in_ddr2_clk_r;
always @(posedge ddr2_clk)
if (ddr2_rst)
ddr2_clk_phase <= 0;
else if (wb_clk_edge)
ddr2_clk_phase <= 0;
else
ddr2_clk_phase <= ddr2_clk_phase + 1;
always @(posedge ddr2_clk)
do_writeback_ddr2_fifo_we <= (do_writeback_ddr2_shifter_r[0]) |
(do_writeback_ddr2_shifter_r[2]) |
(do_writeback_ddr2_shifter_r[4]) |
(do_writeback_ddr2_shifter_r[6]);
 
// Kick off counting when we see that the wb_clk domain is
// doing a writeback.
always @(posedge ddr2_clk)
if (ddr2_rst)
do_writeback_ddr2_shifter <= 4'h0;
else if (|do_writeback_ddr2_shifter)
do_writeback_ddr2_shifter <= {do_writeback_ddr2_shifter[6:0], 1'b0};
else if (!(|ddr2_clk_phase) & do_writeback & !ddr2_write_done) // sample WB domain
do_writeback_ddr2_shifter <= 1;
 
 
always @(posedge ddr2_clk)
do_writeback_ddr2_shifter_r <= do_writeback_ddr2_shifter;
always @(posedge ddr2_clk)
if (ddr2_rst)
ddr2_write_done <= 0;
else if (do_writeback_ddr2_shifter[7])
ddr2_write_done <= 1;
else if ((!(|ddr2_clk_phase)) & !do_writeback) // sample WB domain
ddr2_write_done <= 0;
always @(posedge ddr2_clk)
if (ddr2_rst)
ddr2_cache_addr <= 0;
else if (rd_data_valid | do_writeback_ddr2_fifo_we)
ddr2_cache_addr <= ddr2_cache_addr + 1;
always @(posedge ddr2_clk)
rd_data_valid_r <= rd_data_valid;
// Read done signaling to WB domain
always @(posedge ddr2_clk)
if (ddr2_rst)
ddr2_read_done <= 0;
else if (!rd_data_valid & rd_data_valid_r) // Detect read data valid falling edge
ddr2_read_done <= 1;
else if (!(|ddr2_clk_phase) & !do_readfrom) // Read WB domain
ddr2_read_done <= 0;
 
wire [3:0] wb_cache_adr;
assign wb_cache_adr = wb_adr_i[5:2];
wire [3:0] wb_cache_sel_we;
assign wb_cache_sel_we = {4{wb_we_i}} & wb_sel_i;
wire ddr2_cache_en;
wire [15:0] ddr2_cache_we;
assign ddr2_cache_en = rd_data_valid | (|do_writeback_ddr2_shifter);
assign ddr2_cache_we = {16{rd_data_valid}};
// Xilinx Coregen true dual-port RAMB array.
// Wishbone side : 32-bit
// DDR2 side : 128-bit
xilinx_ddr2_if_cache cache_mem0
(
// Wishbone side
.clka(wb_clk),
.ena(wb_cache_en),
.wea(wb_cache_sel_we),
.addra({8'd0,wb_cache_adr}),
.dina(wb_dat_i),
.douta(wb_dat_o),
 
// DDR2 controller side
.clkb(ddr2_clk),
.enb(ddr2_cache_en),
.web(ddr2_cache_we),
.addrb({8'd0,ddr2_cache_addr}),
.dinb(rd_data_fifo_out),
.doutb(ddr2_cache_data_o));
ddr2_mig #
(
.BANK_WIDTH (BANK_WIDTH),
.CKE_WIDTH (CKE_WIDTH),
.CLK_WIDTH (CLK_WIDTH),
.COL_WIDTH (COL_WIDTH),
.CS_NUM (CS_NUM),
.CS_WIDTH (CS_WIDTH),
.CS_BITS (CS_BITS),
.DM_WIDTH (DM_WIDTH),
.DQ_WIDTH (DQ_WIDTH),
.DQ_PER_DQS (DQ_PER_DQS),
.DQ_BITS (DQ_BITS),
.DQS_WIDTH (DQS_WIDTH),
.DQS_BITS (DQS_BITS),
.HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
.ODT_WIDTH (ODT_WIDTH),
.ROW_WIDTH (ROW_WIDTH),
.APPDATA_WIDTH (APPDATA_WIDTH),
.ADDITIVE_LAT (ADDITIVE_LAT),
.BURST_LEN (BURST_LEN),
.BURST_TYPE (BURST_TYPE),
.CAS_LAT (CAS_LAT),
.ECC_ENABLE (ECC_ENABLE),
.MULTI_BANK_EN (MULTI_BANK_EN),
.ODT_TYPE (ODT_TYPE),
.REDUCE_DRV (REDUCE_DRV),
.REG_ENABLE (REG_ENABLE),
.TREFI_NS (TREFI_NS),
.TRAS (TRAS),
.TRCD (TRCD),
.TRFC (TRFC),
.TRP (TRP),
.TRTP (TRTP),
.TWR (TWR),
.TWTR (TWTR),
.SIM_ONLY (SIM_ONLY),
.RST_ACT_LOW (RST_ACT_LOW),
.CLK_TYPE (CLK_TYPE),
.DLL_FREQ_MODE (DLL_FREQ_MODE),
.CLK_PERIOD (CLK_PERIOD)
)
ddr2_mig0
(
.sys_clk (ddr2_if_clk),
.idly_clk_200 (idly_clk_200),
.sys_rst_n (ddr2_if_rst), // Act. high, sync. to ddr2_if_clk
.ddr2_ras_n (ddr2_ras_n),
.ddr2_cas_n (ddr2_cas_n),
.ddr2_we_n (ddr2_we_n),
.ddr2_cs_n (ddr2_cs_n),
.ddr2_cke (ddr2_cke),
.ddr2_odt (ddr2_odt),
.ddr2_dm (ddr2_dm),
.ddr2_dq (ddr2_dq),
.ddr2_dqs (ddr2_dqs),
.ddr2_dqs_n (ddr2_dqs_n),
.ddr2_ck (ddr2_ck),
.ddr2_ck_n (ddr2_ck_n),
.ddr2_ba (ddr2_ba),
.ddr2_a (ddr2_a),
.clk0_tb (ddr2_clk),
.rst0_tb (ddr2_rst),
.usr_clk (wb_clk),
.app_af_afull (app_af_afull),
.app_wdf_afull (app_wdf_afull),
.rd_data_valid (rd_data_valid),
.rd_data_fifo_out (rd_data_fifo_out),
.app_af_wren (app_af_wren),
.app_af_cmd (app_af_cmd),
.app_af_addr (app_af_addr),
.app_wdf_wren (app_wdf_wren),
.app_wdf_data (app_wdf_data),
.app_wdf_mask_data (app_wdf_mask_data),
.phy_init_done (phy_init_done)
);
 
endmodule // ml501_ddr2_if
// Local Variables:
// verilog-library-directories:("." "ddr2_mig")
// verilog-library-extensions:(".v" ".h")
// End:
/boards/xilinx/ml501/rtl/verilog/xilinx_ddr2/ddr2_phy_calib.v
0,0 → 1,2349
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007, 2008 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_phy_calib.v
// /___/ /\ Date Last Modified: $Date: 2008/12/23 14:26:00 $
// \ \ / \ Date Created: Thu Aug 10 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR2
//Purpose:
// This module handles calibration after memory initialization.
//Reference:
//Revision History:
//*****************************************************************************
 
`timescale 1ns/1ps
 
module ddr2_phy_calib #
(
// Following parameters are for 72-bit RDIMM design (for ML561 Reference
// board design). Actual values may be different. Actual parameters values
// are passed from design top module ddr2_mig module. Please refer to
// the ddr2_mig module for actual values.
parameter DQ_WIDTH = 72,
parameter DQ_BITS = 7,
parameter DQ_PER_DQS = 8,
parameter DQS_BITS = 4,
parameter DQS_WIDTH = 9,
parameter ADDITIVE_LAT = 0,
parameter CAS_LAT = 5,
parameter REG_ENABLE = 1,
parameter CLK_PERIOD = 3000,
parameter SIM_ONLY = 0,
parameter DEBUG_EN = 0
)
(
input clk,
input clkdiv,
input rstdiv,
input [3:0] calib_start,
input ctrl_rden,
input phy_init_rden,
input [DQ_WIDTH-1:0] rd_data_rise,
input [DQ_WIDTH-1:0] rd_data_fall,
input calib_ref_done,
output reg [3:0] calib_done,
output reg calib_ref_req,
output [DQS_WIDTH-1:0] calib_rden,
output reg [DQS_WIDTH-1:0] calib_rden_sel,
output reg dlyrst_dq,
output reg [DQ_WIDTH-1:0] dlyce_dq,
output reg [DQ_WIDTH-1:0] dlyinc_dq,
output reg dlyrst_dqs,
output reg [DQS_WIDTH-1:0] dlyce_dqs,
output reg [DQS_WIDTH-1:0] dlyinc_dqs,
output reg [DQS_WIDTH-1:0] dlyrst_gate,
output reg [DQS_WIDTH-1:0] dlyce_gate,
output reg [DQS_WIDTH-1:0] dlyinc_gate,
output [DQS_WIDTH-1:0] en_dqs,
output [DQS_WIDTH-1:0] rd_data_sel,
// Debug signals (optional use)
input dbg_idel_up_all,
input dbg_idel_down_all,
input dbg_idel_up_dq,
input dbg_idel_down_dq,
input dbg_idel_up_dqs,
input dbg_idel_down_dqs,
input dbg_idel_up_gate,
input dbg_idel_down_gate,
input [DQ_BITS-1:0] dbg_sel_idel_dq,
input dbg_sel_all_idel_dq,
input [DQS_BITS:0] dbg_sel_idel_dqs,
input dbg_sel_all_idel_dqs,
input [DQS_BITS:0] dbg_sel_idel_gate,
input dbg_sel_all_idel_gate,
output [3:0] dbg_calib_done,
output [3:0] dbg_calib_err,
output [(6*DQ_WIDTH)-1:0] dbg_calib_dq_tap_cnt,
output [(6*DQS_WIDTH)-1:0] dbg_calib_dqs_tap_cnt,
output [(6*DQS_WIDTH)-1:0] dbg_calib_gate_tap_cnt,
output [DQS_WIDTH-1:0] dbg_calib_rd_data_sel,
output [(5*DQS_WIDTH)-1:0] dbg_calib_rden_dly,
output [(5*DQS_WIDTH)-1:0] dbg_calib_gate_dly
);
 
// minimum time (in IDELAY taps) for which capture data must be stable for
// algorithm to consider
localparam MIN_WIN_SIZE = 5;
// IDEL_SET_VAL = (# of cycles - 1) to wait after changing IDELAY value
// we only have to wait enough for input with new IDELAY value to
// propagate through pipeline stages.
localparam IDEL_SET_VAL = 3'b111;
// # of clock cycles to delay read enable to determine if read data pattern
// is correct for stage 3/4 (RDEN, DQS gate) calibration
localparam CALIB_RDEN_PIPE_LEN = 31;
// translate CAS latency into number of clock cycles for read valid delay
// determination. Really only needed for CL = 2.5 (set to 2)
localparam CAS_LAT_RDEN = (CAS_LAT == 25) ? 2 : CAS_LAT;
// an SRL32 is used to delay CTRL_RDEN to generate read valid signal. This
// is min possible value delay through SRL32 can be
localparam RDEN_BASE_DELAY = CAS_LAT_RDEN + ADDITIVE_LAT + REG_ENABLE;
// an SRL32 is used to delay the CTRL_RDEN from the read postamble DQS
// gate. This is min possible value the SRL32 delay can be:
// - Delay from end of deassertion of CTRL_RDEN to last falling edge of
// read burst = 3.5 (CTRL_RDEN -> CAS delay) + 3 (min CAS latency) = 6.5
// - Minimum time for DQS gate circuit to be generated:
// * 1 cyc to register CTRL_RDEN from controller
// * 1 cyc after RDEN_CTRL falling edge
// * 1 cyc min through SRL32
// * 1 cyc through SRL32 output flop
// * 0 (<1) cyc of synchronization to DQS domain via IDELAY
// * 1 cyc of delay through IDDR to generate CE to DQ IDDR's
// Total = 5 cyc < 6.5 cycles
// The total should be less than 5.5 cycles to account prop delays
// adding one cycle to the synchronization time via the IDELAY.
// NOTE: Value differs because of optional pipeline register added
// for case of RDEN_BASE_DELAY > 3 to improve timing
localparam GATE_BASE_DELAY = RDEN_BASE_DELAY - 3;
localparam GATE_BASE_INIT = (GATE_BASE_DELAY <= 1) ? 0 : GATE_BASE_DELAY;
// used for RDEN calibration: difference between shift value used during
// calibration, and shift value for actual RDEN SRL. Only applies when
// RDEN edge is immediately captured by CLKDIV0. If not (depends on phase
// of CLK0 and CLKDIV0 when RDEN is asserted), then add 1 to this value.
localparam CAL3_RDEN_SRL_DLY_DELTA = 6;
// fix minimum value of DQS to be 1 to handle the case where's there's only
// one DQS group. We could also enforce that user always inputs minimum
// value of 1 for DQS_BITS (even when DQS_WIDTH=1). Leave this as safeguard
// Assume we don't have to do this for DQ, DQ_WIDTH always > 1
localparam DQS_BITS_FIX = (DQS_BITS == 0) ? 1 : DQS_BITS;
// how many taps to "pre-delay" DQ before stg 1 calibration - not needed for
// current calibration, but leave for debug
localparam DQ_IDEL_INIT = 6'b000000;
// # IDELAY taps per bit time (i.e. half cycle). Limit to 63.
localparam integer BIT_TIME_TAPS = (CLK_PERIOD/150 < 64) ?
CLK_PERIOD/150 : 63;
 
// used in various places during stage 4 cal: (1) determines maximum taps
// to increment when finding right edge, (2) amount to decrement after
// finding left edge, (3) amount to increment after finding right edge
localparam CAL4_IDEL_BIT_VAL = (BIT_TIME_TAPS >= 6'b100000) ?
6'b100000 : BIT_TIME_TAPS;
 
localparam CAL1_IDLE = 4'h0;
localparam CAL1_INIT = 4'h1;
localparam CAL1_INC_IDEL = 4'h2;
localparam CAL1_FIND_FIRST_EDGE = 4'h3;
localparam CAL1_FIRST_EDGE_IDEL_WAIT = 4'h4;
localparam CAL1_FOUND_FIRST_EDGE_WAIT = 4'h5;
localparam CAL1_FIND_SECOND_EDGE = 4'h6;
localparam CAL1_SECOND_EDGE_IDEL_WAIT = 4'h7;
localparam CAL1_CALC_IDEL = 4'h8;
localparam CAL1_DEC_IDEL = 4'h9;
localparam CAL1_DONE = 4'hA;
 
localparam CAL2_IDLE = 4'h0;
localparam CAL2_INIT = 4'h1;
localparam CAL2_INIT_IDEL_WAIT = 4'h2;
localparam CAL2_FIND_EDGE_POS = 4'h3;
localparam CAL2_FIND_EDGE_IDEL_WAIT_POS = 4'h4;
localparam CAL2_FIND_EDGE_NEG = 4'h5;
localparam CAL2_FIND_EDGE_IDEL_WAIT_NEG = 4'h6;
localparam CAL2_DEC_IDEL = 4'h7;
localparam CAL2_DONE = 4'h8;
 
localparam CAL3_IDLE = 3'h0;
localparam CAL3_INIT = 3'h1;
localparam CAL3_DETECT = 3'h2;
localparam CAL3_RDEN_PIPE_CLR_WAIT = 3'h3;
localparam CAL3_DONE = 3'h4;
 
localparam CAL4_IDLE = 3'h0;
localparam CAL4_INIT = 3'h1;
localparam CAL4_FIND_WINDOW = 3'h2;
localparam CAL4_FIND_EDGE = 3'h3;
localparam CAL4_IDEL_WAIT = 3'h4;
localparam CAL4_RDEN_PIPE_CLR_WAIT = 3'h5;
localparam CAL4_ADJ_IDEL = 3'h6;
localparam CAL4_DONE = 3'h7;
 
integer i, j;
 
reg [5:0] cal1_bit_time_tap_cnt;
reg [1:0] cal1_data_chk_last;
reg cal1_data_chk_last_valid;
reg [1:0] cal1_data_chk_r;
reg cal1_dlyce_dq;
reg cal1_dlyinc_dq;
reg cal1_dqs_dq_init_phase;
reg cal1_detect_edge;
reg cal1_detect_stable;
reg cal1_found_second_edge;
reg cal1_found_rising;
reg cal1_found_window;
reg cal1_first_edge_done;
reg [5:0] cal1_first_edge_tap_cnt;
reg [6:0] cal1_idel_dec_cnt;
reg [5:0] cal1_idel_inc_cnt;
reg [5:0] cal1_idel_max_tap;
reg cal1_idel_max_tap_we;
reg [5:0] cal1_idel_tap_cnt;
reg cal1_idel_tap_limit_hit;
reg [6:0] cal1_low_freq_idel_dec;
reg cal1_ref_req;
wire cal1_refresh;
reg [3:0] cal1_state;
reg [3:0] cal1_window_cnt;
reg cal2_curr_sel;
wire cal2_detect_edge;
reg cal2_dlyce_dqs;
reg cal2_dlyinc_dqs;
reg [5:0] cal2_idel_dec_cnt;
reg [5:0] cal2_idel_tap_cnt;
reg [5:0] cal2_idel_tap_limit;
reg cal2_idel_tap_limit_hit;
reg cal2_rd_data_fall_last_neg;
reg cal2_rd_data_fall_last_pos;
reg cal2_rd_data_last_valid_neg;
reg cal2_rd_data_last_valid_pos;
reg cal2_rd_data_rise_last_neg;
reg cal2_rd_data_rise_last_pos;
reg [DQS_WIDTH-1:0] cal2_rd_data_sel;
wire cal2_rd_data_sel_edge;
reg [DQS_WIDTH-1:0] cal2_rd_data_sel_r;
reg cal2_ref_req;
reg [3:0] cal2_state;
reg cal3_data_match;
reg cal3_data_match_stgd;
wire cal3_data_valid;
wire cal3_match_found;
wire [4:0] cal3_rden_dly;
reg [4:0] cal3_rden_srl_a;
reg [2:0] cal3_state;
wire cal4_data_good;
reg cal4_data_match;
reg cal4_data_match_stgd;
wire cal4_data_valid;
reg cal4_dlyce_gate;
reg cal4_dlyinc_gate;
reg cal4_dlyrst_gate;
reg [4:0] cal4_gate_srl_a;
reg [5:0] cal4_idel_adj_cnt;
reg cal4_idel_adj_inc;
reg cal4_idel_bit_tap;
reg [5:0] cal4_idel_tap_cnt;
reg cal4_idel_max_tap;
reg [4:0] cal4_rden_srl_a;
reg cal4_ref_req;
reg cal4_seek_left;
reg cal4_stable_window;
reg [2:0] cal4_state;
reg [3:0] cal4_window_cnt;
reg [3:0] calib_done_tmp; // only for stg1/2/4
reg calib_ctrl_gate_pulse_r;
reg calib_ctrl_rden;
reg calib_ctrl_rden_r;
wire calib_ctrl_rden_negedge;
reg calib_ctrl_rden_negedge_r;
reg [3:0] calib_done_r;
reg [3:0] calib_err;
reg [1:0] calib_err_2;
wire calib_init_gate_pulse;
reg calib_init_gate_pulse_r;
reg calib_init_gate_pulse_r1;
reg calib_init_rden;
reg calib_init_rden_r;
reg [4:0] calib_rden_srl_a;
wire [4:0] calib_rden_srl_a_r;
reg [(5*DQS_WIDTH)-1:0] calib_rden_dly;
reg calib_rden_edge_r;
reg [4:0] calib_rden_pipe_cnt;
wire calib_rden_srl_out;
wire calib_rden_srl_out_r;
reg calib_rden_srl_out_r1;
reg calib_rden_valid;
reg calib_rden_valid_stgd;
reg [DQ_BITS-1:0] count_dq;
reg [DQS_BITS_FIX-1:0] count_dqs;
reg [DQS_BITS_FIX-1:0] count_gate;
reg [DQS_BITS_FIX-1:0] count_rden;
reg ctrl_rden_r;
wire dlyce_or;
reg [(5*DQS_WIDTH)-1:0] gate_dly;
wire [(5*DQS_WIDTH)-1:0] gate_dly_r;
wire gate_srl_in;
wire [DQS_WIDTH-1:0] gate_srl_out;
wire [DQS_WIDTH-1:0] gate_srl_out_r;
reg [2:0] idel_set_cnt;
wire idel_set_wait;
reg [DQ_BITS-1:0] next_count_dq;
reg [DQS_BITS_FIX-1:0] next_count_dqs;
reg [DQS_BITS_FIX-1:0] next_count_gate;
reg phy_init_rden_r;
reg phy_init_rden_r1;
reg [DQ_WIDTH-1:0] rd_data_fall_1x_r;
reg [DQS_WIDTH-1:0] rd_data_fall_1x_r1;
reg [DQS_WIDTH-1:0] rd_data_fall_2x_r;
wire [DQS_WIDTH-1:0] rd_data_fall_chk_q1;
wire [DQS_WIDTH-1:0] rd_data_fall_chk_q2;
reg [DQ_WIDTH-1:0] rd_data_rise_1x_r;
reg [DQS_WIDTH-1:0] rd_data_rise_1x_r1;
reg [DQS_WIDTH-1:0] rd_data_rise_2x_r;
wire [DQS_WIDTH-1:0] rd_data_rise_chk_q1;
wire [DQS_WIDTH-1:0] rd_data_rise_chk_q2;
reg rdd_fall_q1;
reg rdd_fall_q1_r;
reg rdd_fall_q1_r1;
reg rdd_fall_q2;
reg rdd_fall_q2_r;
reg rdd_rise_q1;
reg rdd_rise_q1_r;
reg rdd_rise_q1_r1;
reg rdd_rise_q2;
reg rdd_rise_q2_r;
reg [DQS_BITS_FIX-1:0] rdd_mux_sel;
reg rden_dec;
reg [(5*DQS_WIDTH)-1:0] rden_dly;
wire [(5*DQS_WIDTH)-1:0] rden_dly_r;
reg [4:0] rden_dly_0;
reg rden_inc;
reg [DQS_WIDTH-1:0] rden_mux;
wire [DQS_WIDTH-1:0] rden_srl_out;
 
// Debug
integer x;
reg [5:0] dbg_dq_tap_cnt [DQ_WIDTH-1:0];
reg [5:0] dbg_dqs_tap_cnt [DQS_WIDTH-1:0];
reg [5:0] dbg_gate_tap_cnt [DQS_WIDTH-1:0];
 
//***************************************************************************
// Debug output ("dbg_phy_calib_*")
// NOTES:
// 1. All debug outputs coming out of PHY_CALIB are clocked off CLKDIV0,
// although they are also static after calibration is complete. This
// means the user can either connect them to a Chipscope ILA, or to
// either a sync/async VIO input block. Using an async VIO has the
// advantage of not requiring these paths to meet cycle-to-cycle timing.
// 2. The widths of most of these debug buses are dependent on the # of
// DQS/DQ bits (e.g. dq_tap_cnt width = 6 * (# of DQ bits)
// SIGNAL DESCRIPTION:
// 1. calib_done: 4 bits - each one asserted as each phase of calibration
// is completed.
// 2. calib_err: 4 bits - each one asserted when a calibration error
// encountered for that stage. Some of these bits may not
// be used (not all cal stages report an error).
// 3. dq_tap_cnt: final IDELAY tap counts for all DQ IDELAYs
// 4. dqs_tap_cnt: final IDELAY tap counts for all DQS IDELAYs
// 5. gate_tap_cnt: final IDELAY tap counts for all DQS gate
// synchronization IDELAYs
// 6. rd_data_sel: final read capture MUX (either "positive" or "negative"
// edge capture) settings for all DQS groups
// 7. rden_dly: related to # of cycles after issuing a read until when
// read data is valid - for all DQS groups
// 8. gate_dly: related to # of cycles after issuing a read until when
// clock enable for all DQ's is deasserted to prevent
// effect of DQS postamble glitch - for all DQS groups
//***************************************************************************
 
//*****************************************************************
// Record IDELAY tap values by "snooping" IDELAY control signals
//*****************************************************************
 
// record DQ IDELAY tap values
genvar dbg_dq_tc_i;
generate
for (dbg_dq_tc_i = 0; dbg_dq_tc_i < DQ_WIDTH;
dbg_dq_tc_i = dbg_dq_tc_i + 1) begin: gen_dbg_dq_tap_cnt
assign dbg_calib_dq_tap_cnt[(6*dbg_dq_tc_i)+5:(6*dbg_dq_tc_i)]
= dbg_dq_tap_cnt[dbg_dq_tc_i];
always @(posedge clkdiv)
if (rstdiv | dlyrst_dq)
dbg_dq_tap_cnt[dbg_dq_tc_i] <= 6'b000000;
else
if (dlyce_dq[dbg_dq_tc_i])
if (dlyinc_dq[dbg_dq_tc_i])
dbg_dq_tap_cnt[dbg_dq_tc_i]
<= dbg_dq_tap_cnt[dbg_dq_tc_i] + 1;
else
dbg_dq_tap_cnt[dbg_dq_tc_i]
<= dbg_dq_tap_cnt[dbg_dq_tc_i] - 1;
end
endgenerate
 
// record DQS IDELAY tap values
genvar dbg_dqs_tc_i;
generate
for (dbg_dqs_tc_i = 0; dbg_dqs_tc_i < DQS_WIDTH;
dbg_dqs_tc_i = dbg_dqs_tc_i + 1) begin: gen_dbg_dqs_tap_cnt
assign dbg_calib_dqs_tap_cnt[(6*dbg_dqs_tc_i)+5:(6*dbg_dqs_tc_i)]
= dbg_dqs_tap_cnt[dbg_dqs_tc_i];
always @(posedge clkdiv)
if (rstdiv | dlyrst_dqs)
dbg_dqs_tap_cnt[dbg_dqs_tc_i] <= 6'b000000;
else
if (dlyce_dqs[dbg_dqs_tc_i])
if (dlyinc_dqs[dbg_dqs_tc_i])
dbg_dqs_tap_cnt[dbg_dqs_tc_i]
<= dbg_dqs_tap_cnt[dbg_dqs_tc_i] + 1;
else
dbg_dqs_tap_cnt[dbg_dqs_tc_i]
<= dbg_dqs_tap_cnt[dbg_dqs_tc_i] - 1;
end
endgenerate
 
// record DQS gate IDELAY tap values
genvar dbg_gate_tc_i;
generate
for (dbg_gate_tc_i = 0; dbg_gate_tc_i < DQS_WIDTH;
dbg_gate_tc_i = dbg_gate_tc_i + 1) begin: gen_dbg_gate_tap_cnt
assign dbg_calib_gate_tap_cnt[(6*dbg_gate_tc_i)+5:(6*dbg_gate_tc_i)]
= dbg_gate_tap_cnt[dbg_gate_tc_i];
always @(posedge clkdiv)
if (rstdiv | dlyrst_gate[dbg_gate_tc_i])
dbg_gate_tap_cnt[dbg_gate_tc_i] <= 6'b000000;
else
if (dlyce_gate[dbg_gate_tc_i])
if (dlyinc_gate[dbg_gate_tc_i])
dbg_gate_tap_cnt[dbg_gate_tc_i]
<= dbg_gate_tap_cnt[dbg_gate_tc_i] + 1;
else
dbg_gate_tap_cnt[dbg_gate_tc_i]
<= dbg_gate_tap_cnt[dbg_gate_tc_i] - 1;
end
endgenerate
 
assign dbg_calib_done = calib_done;
assign dbg_calib_err = calib_err;
assign dbg_calib_rd_data_sel = cal2_rd_data_sel;
assign dbg_calib_rden_dly = rden_dly;
assign dbg_calib_gate_dly = gate_dly;
 
//***************************************************************************
// Read data pipelining, and read data "ISERDES" data width expansion
//***************************************************************************
 
// For all data bits, register incoming capture data to slow clock to improve
// timing. Adding single pipeline stage does not affect functionality (as
// long as we make sure to wait extra clock cycle after changing DQ IDELAY)
// Also note in this case that we're "missing" every other clock cycle's
// worth of data capture since we're sync'ing to the slow clock. This is
// fine for stage 1 and stage 2 cal, but not for stage 3 and 4 (see below
// for different circuit to handle those stages)
always @(posedge clkdiv) begin
rd_data_rise_1x_r <= rd_data_rise;
rd_data_fall_1x_r <= rd_data_fall;
end
 
// For every DQ_PER_DQS bit, generate what is essentially a ISERDES-type
// data width expander. Will need this for stage 3 and 4 cal, where we need
// to compare data over consecutive clock cycles. We can also use this for
// stage 2 as well (stage 2 doesn't require every bit to be looked at, only
// one bit per DQS group)
genvar rdd_i;
generate
for (rdd_i = 0; rdd_i < DQS_WIDTH; rdd_i = rdd_i + 1) begin: gen_rdd
// first stage: keep data in fast clk domain. Store data over two
// consecutive clock cycles for rise/fall data for proper transfer
// to slow clock domain
always @(posedge clk) begin
rd_data_rise_2x_r[rdd_i] <= rd_data_rise[(rdd_i*DQ_PER_DQS)];
rd_data_fall_2x_r[rdd_i] <= rd_data_fall[(rdd_i*DQ_PER_DQS)];
end
// second stage, register first stage to slow clock domain, 2nd stage
// consists of both these flops, and the rd_data_rise_1x_r flops
always @(posedge clkdiv) begin
rd_data_rise_1x_r1[rdd_i] <= rd_data_rise_2x_r[rdd_i];
rd_data_fall_1x_r1[rdd_i] <= rd_data_fall_2x_r[rdd_i];
end
// now we have four outputs - representing rise/fall outputs over last
// 2 fast clock cycles. However, the ordering these represent can either
// be: (1) Q2 = data @ time = n, Q1 = data @ time = n+1, or (2)
// Q2 = data @ time = n - 1, Q1 = data @ time = n (and data at [Q1,Q2]
// is "staggered") - leave it up to the stage of calibration using this
// to figure out which is which, if they care at all (e.g. stage 2 cal
// doesn't care about the ordering)
assign rd_data_rise_chk_q1[rdd_i]
= rd_data_rise_1x_r[(rdd_i*DQ_PER_DQS)];
assign rd_data_rise_chk_q2[rdd_i]
= rd_data_rise_1x_r1[rdd_i];
assign rd_data_fall_chk_q1[rdd_i]
= rd_data_fall_1x_r[(rdd_i*DQ_PER_DQS)];
assign rd_data_fall_chk_q2[rdd_i]
= rd_data_fall_1x_r1[rdd_i];
end
endgenerate
 
//*****************************************************************
// Outputs of these simplified ISERDES circuits then feed MUXes based on
// which DQ the current calibration algorithm needs to look at
//*****************************************************************
 
// generate MUX control; assume that adding an extra pipeline stage isn't
// an issue - whatever stage cal logic is using output of MUX will wait
// enough time after changing it
always @(posedge clkdiv) begin
(* full_case, parallel_case *) case (calib_done[2:0])
3'b001: rdd_mux_sel <= next_count_dqs;
3'b011: rdd_mux_sel <= count_rden;
3'b111: rdd_mux_sel <= next_count_gate;
endcase
end
 
always @(posedge clkdiv) begin
rdd_rise_q1 <= rd_data_rise_chk_q1[rdd_mux_sel];
rdd_rise_q2 <= rd_data_rise_chk_q2[rdd_mux_sel];
rdd_fall_q1 <= rd_data_fall_chk_q1[rdd_mux_sel];
rdd_fall_q2 <= rd_data_fall_chk_q2[rdd_mux_sel];
end
 
//***************************************************************************
// Demultiplexor to control (reset, increment, decrement) IDELAY tap values
// For DQ:
// STG1: for per-bit-deskew, only inc/dec the current DQ. For non-per
// deskew, increment all bits in the current DQS set
// STG2: inc/dec all DQ's in the current DQS set.
// NOTE: Nice to add some error checking logic here (or elsewhere in the
// code) to check if logic attempts to overflow tap value
//***************************************************************************
 
// don't use DLYRST to reset value of IDELAY after reset. Need to change this
// if we want to allow user to recalibrate after initial reset
always @(posedge clkdiv)
if (rstdiv) begin
dlyrst_dq <= 1'b1;
dlyrst_dqs <= 1'b1;
end else begin
dlyrst_dq <= 1'b0;
dlyrst_dqs <= 1'b0;
end
 
always @(posedge clkdiv) begin
if (rstdiv) begin
dlyce_dq <= 'b0;
dlyinc_dq <= 'b0;
dlyce_dqs <= 'b0;
dlyinc_dqs <= 'b0;
end else begin
dlyce_dq <= 'b0;
dlyinc_dq <= 'b0;
dlyce_dqs <= 'b0;
dlyinc_dqs <= 'b0;
 
// stage 1 cal: change only specified DQ
if (cal1_dlyce_dq) begin
if (SIM_ONLY == 0) begin
dlyce_dq[count_dq] <= 1'b1;
dlyinc_dq[count_dq] <= cal1_dlyinc_dq;
end else begin
// if simulation, then calibrate only first DQ, apply results
// to all DQs (i.e. assume delay on all DQs is the same)
for (i = 0; i < DQ_WIDTH; i = i + 1) begin: loop_sim_dq_dly
dlyce_dq[i] <= 1'b1;
dlyinc_dq[i] <= cal1_dlyinc_dq;
end
end
end else if (cal2_dlyce_dqs) begin
// stage 2 cal: change DQS and all corresponding DQ's
if (SIM_ONLY == 0) begin
dlyce_dqs[count_dqs] <= 1'b1;
dlyinc_dqs[count_dqs] <= cal2_dlyinc_dqs;
for (i = 0; i < DQ_PER_DQS; i = i + 1) begin: loop_dqs_dly
dlyce_dq[(DQ_PER_DQS*count_dqs)+i] <= 1'b1;
dlyinc_dq[(DQ_PER_DQS*count_dqs)+i] <= cal2_dlyinc_dqs;
end
end else begin
for (i = 0; i < DQS_WIDTH; i = i + 1) begin: loop_sim_dqs_dly
// if simulation, then calibrate only first DQS
dlyce_dqs[i] <= 1'b1;
dlyinc_dqs[i] <= cal2_dlyinc_dqs;
for (j = 0; j < DQ_PER_DQS; j = j + 1) begin: loop_sim_dq_dqs_dly
dlyce_dq[(DQ_PER_DQS*i)+j] <= 1'b1;
dlyinc_dq[(DQ_PER_DQS*i)+j] <= cal2_dlyinc_dqs;
end
end
end
end else if (DEBUG_EN != 0) begin
// DEBUG: allow user to vary IDELAY tap settings
// For DQ IDELAY taps
if (dbg_idel_up_all || dbg_idel_down_all ||
dbg_sel_all_idel_dq) begin
for (x = 0; x < DQ_WIDTH; x = x + 1) begin: loop_dly_inc_dq
dlyce_dq[x] <= dbg_idel_up_all | dbg_idel_down_all |
dbg_idel_up_dq | dbg_idel_down_dq;
dlyinc_dq[x] <= dbg_idel_up_all | dbg_idel_up_dq;
end
end else begin
dlyce_dq <= 'b0;
dlyce_dq[dbg_sel_idel_dq] <= dbg_idel_up_dq |
dbg_idel_down_dq;
dlyinc_dq[dbg_sel_idel_dq] <= dbg_idel_up_dq;
end
// For DQS IDELAY taps
if (dbg_idel_up_all || dbg_idel_down_all ||
dbg_sel_all_idel_dqs) begin
for (x = 0; x < DQS_WIDTH; x = x + 1) begin: loop_dly_inc_dqs
dlyce_dqs[x] <= dbg_idel_up_all | dbg_idel_down_all |
dbg_idel_up_dqs | dbg_idel_down_dqs;
dlyinc_dqs[x] <= dbg_idel_up_all | dbg_idel_up_dqs;
end
end else begin
dlyce_dqs <= 'b0;
dlyce_dqs[dbg_sel_idel_dqs] <= dbg_idel_up_dqs |
dbg_idel_down_dqs;
dlyinc_dqs[dbg_sel_idel_dqs] <= dbg_idel_up_dqs;
end
end
end
end
 
// GATE synchronization is handled directly by Stage 4 calibration FSM
always @(posedge clkdiv)
if (rstdiv) begin
dlyrst_gate <= {DQS_WIDTH{1'b1}};
dlyce_gate <= {DQS_WIDTH{1'b0}};
dlyinc_gate <= {DQS_WIDTH{1'b0}};
end else begin
dlyrst_gate <= {DQS_WIDTH{1'b0}};
dlyce_gate <= {DQS_WIDTH{1'b0}};
dlyinc_gate <= {DQS_WIDTH{1'b0}};
 
if (cal4_dlyrst_gate) begin
if (SIM_ONLY == 0)
dlyrst_gate[count_gate] <= 1'b1;
else
for (i = 0; i < DQS_WIDTH; i = i + 1) begin: loop_gate_sim_dly_rst
dlyrst_gate[i] <= 1'b1;
end
end
 
if (cal4_dlyce_gate) begin
if (SIM_ONLY == 0) begin
dlyce_gate[count_gate] <= 1'b1;
dlyinc_gate[count_gate] <= cal4_dlyinc_gate;
end else begin
// if simulation, then calibrate only first gate
for (i = 0; i < DQS_WIDTH; i = i + 1) begin: loop_gate_sim_dly
dlyce_gate[i] <= 1'b1;
dlyinc_gate[i] <= cal4_dlyinc_gate;
end
end
end else if (DEBUG_EN != 0) begin
// DEBUG: allow user to vary IDELAY tap settings
if (dbg_idel_up_all || dbg_idel_down_all ||
dbg_sel_all_idel_gate) begin
for (x = 0; x < DQS_WIDTH; x = x + 1) begin: loop_dly_inc_gate
dlyce_gate[x] <= dbg_idel_up_all | dbg_idel_down_all |
dbg_idel_up_gate | dbg_idel_down_gate;
dlyinc_gate[x] <= dbg_idel_up_all | dbg_idel_up_gate;
end
end else begin
dlyce_gate <= {DQS_WIDTH{1'b0}};
dlyce_gate[dbg_sel_idel_gate] <= dbg_idel_up_gate |
dbg_idel_down_gate;
dlyinc_gate[dbg_sel_idel_gate] <= dbg_idel_up_gate;
end
end
end
 
//***************************************************************************
// signal to tell calibration state machines to wait and give IDELAY time to
// settle after it's value is changed (both time for IDELAY chain to settle,
// and for settled output to propagate through ISERDES). For general use: use
// for any calibration state machines that modify any IDELAY.
// Should give at least enough time for IDELAY output to settle (technically
// for V5, this should be "glitchless" when IDELAY taps are changed, so don't
// need any time here), and also time for new data to propagate through both
// ISERDES and the "RDD" MUX + associated pipelining
// For now, give very "generous" delay - doesn't really matter since only
// needed during calibration
//***************************************************************************
 
// determine if calibration polarity has changed
always @(posedge clkdiv)
cal2_rd_data_sel_r <= cal2_rd_data_sel;
 
assign cal2_rd_data_sel_edge = |(cal2_rd_data_sel ^ cal2_rd_data_sel_r);
 
// combine requests to modify any of the IDELAYs into one. Also when second
// stage capture "edge" polarity is changed (IDELAY isn't changed in this
// case, but use the same counter to stall cal logic)
assign dlyce_or = cal1_dlyce_dq |
cal2_dlyce_dqs |
cal2_rd_data_sel_edge |
cal4_dlyce_gate |
cal4_dlyrst_gate;
 
// SYN_NOTE: Can later recode to avoid combinational path
assign idel_set_wait = dlyce_or || (idel_set_cnt != IDEL_SET_VAL);
 
always @(posedge clkdiv)
if (rstdiv)
idel_set_cnt <= 4'b0000;
else if (dlyce_or)
idel_set_cnt <= 4'b0000;
else if (idel_set_cnt != IDEL_SET_VAL)
idel_set_cnt <= idel_set_cnt + 1;
 
// generate request to PHY_INIT logic to issue auto-refresh
// used by certain states to force prech/auto-refresh part way through
// calibration to avoid a tRAS violation (which will happen if that
// stage of calibration lasts long enough). This signal must meet the
// following requirements: (1) only transition from 0->1 when the refresh
// request is needed, (2) stay at 1 and only transition 1->0 when
// CALIB_REF_DONE is asserted
always @(posedge clkdiv)
if (rstdiv)
calib_ref_req <= 1'b0;
else
calib_ref_req <= cal1_ref_req | cal2_ref_req | cal4_ref_req;
 
// stage 1 calibration requests auto-refresh every 4 bits
generate
if (DQ_BITS < 2) begin: gen_cal1_refresh_dq_lte4
assign cal1_refresh = 1'b0;
end else begin: gen_cal1_refresh_dq_gt4
assign cal1_refresh = (next_count_dq[1:0] == 2'b00);
end
endgenerate
 
//***************************************************************************
// First stage calibration: DQ-DQS
// Definitions:
// edge: detected when varying IDELAY, and current capture data != prev
// capture data
// valid bit window: detected when current capture data == prev capture
// data for more than half the bit time
// starting conditions for DQS-DQ phase:
// case 1: when DQS starts somewhere in rising edge bit window, or
// on the right edge of the rising bit window.
// case 2: when DQS starts somewhere in falling edge bit window, or
// on the right edge of the falling bit window.
// Algorithm Description:
// 1. Increment DQ IDELAY until we find an edge.
// 2. While we're finding the first edge, note whether a valid bit window
// has been detected before we found an edge. If so, then figure out if
// this is the rising or falling bit window. If rising, then our starting
// DQS-DQ phase is case 1. If falling, then it's case 2. If don't detect
// a valid bit window, then we must have started on the edge of a window.
// Need to wait until later on to decide which case we are.
// - Store FIRST_EDGE IDELAY value
// 3. Now look for second edge.
// 4. While we're finding the second edge, note whether valid bit window
// is detected. If so, then use to, along with results from (2) to figure
// out what the starting case is. If in rising bit window, then we're in
// case 2. If falling, then case 1.
// - Store SECOND_EDGE IDELAY value
// NOTES:
// a. Finding two edges allows us to calculate the bit time (although
// not the "same" bit time polarity - need to investigate this
// more).
// b. If we run out of taps looking for the second edge, then the bit
// time must be too long (>= 2.5ns, and DQS-DQ starting phase must be
// case 1).
// 5. Calculate absolute amount to delay DQ as:
// If second edge found, and case 1:
// - DQ_IDELAY = FIRST_EDGE - 0.5*(SECOND_EDGE - FIRST_EDGE)
// If second edge found, and case 2:
// - DQ_IDELAY = SECOND_EDGE - 0.5*(SECOND_EDGE - FIRST_EDGE)
// If second edge not found, then need to make an approximation on
// how much to shift by (should be okay, because we have more timing
// margin):
// - DQ_IDELAY = FIRST_EDGE - 0.5 * (bit_time)
// NOTE: Does this account for either case 1 or case 2?????
// NOTE: It's also possible even when we find the second edge, that
// to instead just use half the bit time to subtract from either
// FIRST or SECOND_EDGE. Finding the actual bit time (which is
// what (SECOND_EDGE - FIRST_EDGE) is, is slightly more accurate,
// since it takes into account duty cycle distortion.
// 6. Repeat for each DQ in current DQS set.
//***************************************************************************
 
//*****************************************************************
// for first stage calibration - used for checking if DQS is aligned to the
// particular DQ, such that we're in the data valid window. Basically, this
// is one giant MUX.
// = [falling data, rising data]
// = [0, 1] = rising DQS aligned in proper (rising edge) bit window
// = [1, 0] = rising DQS aligned in wrong (falling edge) bit window
// = [0, 0], or [1,1] = in uncertain region between windows
//*****************************************************************
 
// SYN_NOTE: May have to split this up into multiple levels - MUX can get
// very wide - as wide as the data bus width
always @(posedge clkdiv)
cal1_data_chk_r <= {rd_data_fall_1x_r[next_count_dq],
rd_data_rise_1x_r[next_count_dq]};
 
//*****************************************************************
// determine when an edge has occurred - when either the current value
// is different from the previous latched value or when the DATA_CHK
// outputs are the same (rare, but indicates that we're at an edge)
// This is only valid when the IDELAY output and propagation of the
// data through the capture flops has had a chance to settle out.
//*****************************************************************
 
// write CAL1_DETECT_EDGE and CAL1_DETECT_STABLE in such a way that
// if X's are captured on the bus during functional simulation, that
// the logic will register this as an edge detected. Do this to allow
// use of this HDL with Denali memory models (Denali models drive DQ
// to X's on both edges of the data valid window to simulate jitter)
// This is only done for functional simulation purposes. **Should not**
// make the final synthesized logic more complicated, but it does make
// the HDL harder to understand b/c we have to "phrase" the logic
// slightly differently than when not worrying about X's
always @(*) begin
// no edge found if: (1) we have recorded prev edge, and rise
// data == fall data, (2) we haven't yet recorded prev edge, but
// rise/fall data is equal to either [0,1] or [1,0] (i.e. rise/fall
// data isn't either X's, or [0,0] or [1,1], which indicates we're
// in the middle of an edge, since normally rise != fall data for stg1)
if ((cal1_data_chk_last_valid &&
(cal1_data_chk_r == cal1_data_chk_last)) ||
(!cal1_data_chk_last_valid &&
((cal1_data_chk_r == 2'b01) || (cal1_data_chk_r == 2'b10))))
cal1_detect_edge = 1'b0;
else
cal1_detect_edge = 1'b1;
end
 
always @(*) begin
// assert if we've found a region where data valid window is stable
// over consecutive IDELAY taps, and either rise/fall = [1,0], or [0,1]
if ((cal1_data_chk_last_valid &&
(cal1_data_chk_r == cal1_data_chk_last)) &&
((cal1_data_chk_r == 2'b01) || (cal1_data_chk_r == 2'b10)))
cal1_detect_stable <= 1'b1;
else
cal1_detect_stable <= 1'b0;
end
 
//*****************************************************************
// Find valid window: keep track of how long we've been in the same data
// window. If it's been long enough, then declare that we've found a valid
// window. Also returns whether we found a rising or falling window (only
// valid when found_window is asserted)
//*****************************************************************
 
always @(posedge clkdiv) begin
if (cal1_state == CAL1_INIT) begin
cal1_window_cnt <= 4'b0000;
cal1_found_window <= 1'b0;
cal1_found_rising <= 1'bx;
end else if (!cal1_data_chk_last_valid) begin
// if we haven't stored a previous value of CAL1_DATA_CHK (or it got
// invalidated because we detected an edge, and are now looking for the
// second edge), then make sure FOUND_WINDOW deasserted on following
// clock edge (to avoid finding a false window immediately after finding
// an edge). Note that because of jitter, it's possible to not find an
// edge at the end of the IDELAY increment settling time, but to find an
// edge on the next clock cycle (e.g. during CAL1_FIND_FIRST_EDGE)
cal1_window_cnt <= 4'b0000;
cal1_found_window <= 1'b0;
cal1_found_rising <= 1'bx;
end else if (((cal1_state == CAL1_FIRST_EDGE_IDEL_WAIT) ||
(cal1_state == CAL1_SECOND_EDGE_IDEL_WAIT)) &&
!idel_set_wait) begin
// while finding the first and second edges, see if we can detect a
// stable bit window (occurs over MIN_WIN_SIZE number of taps). If
// so, then we're away from an edge, and can conclusively determine the
// starting DQS-DQ phase.
if (cal1_detect_stable) begin
cal1_window_cnt <= cal1_window_cnt + 1;
if (cal1_window_cnt == MIN_WIN_SIZE-1) begin
cal1_found_window <= 1'b1;
if (cal1_data_chk_r == 2'b01)
cal1_found_rising <= 1'b1;
else
cal1_found_rising <= 1'b0;
end
end else begin
// otherwise, we're not in a data valid window, reset the window
// counter, and indicate we're not currently in window. This should
// happen by design at least once after finding the first edge.
cal1_window_cnt <= 4'b0000;
cal1_found_window <= 1'b0;
cal1_found_rising <= 1'bx;
end
end
end
 
//*****************************************************************
// keep track of edge tap counts found, and whether we've
// incremented to the maximum number of taps allowed
//*****************************************************************
 
always @(posedge clkdiv)
if (cal1_state == CAL1_INIT) begin
cal1_idel_tap_limit_hit <= 1'b0;
cal1_idel_tap_cnt <= 6'b000000;
end else if (cal1_dlyce_dq) begin
if (cal1_dlyinc_dq) begin
cal1_idel_tap_cnt <= cal1_idel_tap_cnt + 1;
cal1_idel_tap_limit_hit <= (cal1_idel_tap_cnt == 6'b111110);
end else begin
cal1_idel_tap_cnt <= cal1_idel_tap_cnt - 1;
cal1_idel_tap_limit_hit <= 1'b0;
end
end
 
//*****************************************************************
// Pipeline for better timing - amount to decrement by if second
// edge not found
//*****************************************************************
// if only one edge found (possible for low frequencies), then:
// 1. Assume starting DQS-DQ phase has DQS in DQ window (aka "case 1")
// 2. We have to decrement by (63 - first_edge_tap_cnt) + (BIT_TIME_TAPS/2)
// (i.e. decrement by 63-first_edge_tap_cnt to get to right edge of
// DQ window. Then decrement again by (BIT_TIME_TAPS/2) to get to center
// of DQ window.
// 3. Clamp the above value at 63 to ensure we don't underflow IDELAY
// (note: clamping happens in the CAL1 state machine)
always @(posedge clkdiv)
cal1_low_freq_idel_dec
<= (7'b0111111 - {1'b0, cal1_first_edge_tap_cnt}) +
(BIT_TIME_TAPS/2);
 
//*****************************************************************
// Keep track of max taps used during stage 1, use this to limit
// the number of taps that can be used in stage 2
//*****************************************************************
 
always @(posedge clkdiv)
if (rstdiv) begin
cal1_idel_max_tap <= 6'b000000;
cal1_idel_max_tap_we <= 1'b0;
end else begin
// pipeline latch enable for CAL1_IDEL_MAX_TAP - we have plenty
// of time, tap count gets updated, then dead cycles waiting for
// IDELAY output to settle
cal1_idel_max_tap_we <= (cal1_idel_max_tap < cal1_idel_tap_cnt);
// record maximum # of taps used for stg 1 cal
if ((cal1_state == CAL1_DONE) && cal1_idel_max_tap_we)
cal1_idel_max_tap <= cal1_idel_tap_cnt;
end
 
//*****************************************************************
 
always @(posedge clkdiv)
if (rstdiv) begin
calib_done[0] <= 1'b0;
calib_done_tmp[0] <= 1'bx;
calib_err[0] <= 1'b0;
count_dq <= {DQ_BITS{1'b0}};
next_count_dq <= {DQ_BITS{1'b0}};
cal1_bit_time_tap_cnt <= 6'bxxxxxx;
cal1_data_chk_last <= 2'bxx;
cal1_data_chk_last_valid <= 1'bx;
cal1_dlyce_dq <= 1'b0;
cal1_dlyinc_dq <= 1'b0;
cal1_dqs_dq_init_phase <= 1'bx;
cal1_first_edge_done <= 1'bx;
cal1_found_second_edge <= 1'bx;
cal1_first_edge_tap_cnt <= 6'bxxxxxx;
cal1_idel_dec_cnt <= 7'bxxxxxxx;
cal1_idel_inc_cnt <= 6'bxxxxxx;
cal1_ref_req <= 1'b0;
cal1_state <= CAL1_IDLE;
end else begin
// default values for all "pulse" outputs
cal1_ref_req <= 1'b0;
cal1_dlyce_dq <= 1'b0;
cal1_dlyinc_dq <= 1'b0;
 
case (cal1_state)
CAL1_IDLE: begin
count_dq <= {DQ_BITS{1'b0}};
next_count_dq <= {DQ_BITS{1'b0}};
if (calib_start[0]) begin
calib_done[0] <= 1'b0;
calib_done_tmp[0] <= 1'b0;
cal1_state <= CAL1_INIT;
end
end
 
CAL1_INIT: begin
cal1_data_chk_last_valid <= 1'b0;
cal1_found_second_edge <= 1'b0;
cal1_dqs_dq_init_phase <= 1'b0;
cal1_idel_inc_cnt <= 6'b000000;
cal1_state <= CAL1_INC_IDEL;
end
 
// increment DQ IDELAY so that either: (1) DQS starts somewhere in
// first rising DQ window, or (2) DQS starts in first falling DQ
// window. The amount to shift is frequency dependent (and is either
// precalculated by MIG or possibly adjusted by the user)
CAL1_INC_IDEL:
if ((cal1_idel_inc_cnt == DQ_IDEL_INIT) && !idel_set_wait) begin
cal1_state <= CAL1_FIND_FIRST_EDGE;
end else if (cal1_idel_inc_cnt != DQ_IDEL_INIT) begin
cal1_idel_inc_cnt <= cal1_idel_inc_cnt + 1;
cal1_dlyce_dq <= 1'b1;
cal1_dlyinc_dq <= 1'b1;
end
 
// look for first edge
CAL1_FIND_FIRST_EDGE: begin
// Determine DQS-DQ phase if we can detect enough of a valid window
if (cal1_found_window)
cal1_dqs_dq_init_phase <= ~cal1_found_rising;
// find first edge - if found then record position
if (cal1_detect_edge) begin
cal1_state <= CAL1_FOUND_FIRST_EDGE_WAIT;
cal1_first_edge_done <= 1'b0;
cal1_first_edge_tap_cnt <= cal1_idel_tap_cnt;
cal1_data_chk_last_valid <= 1'b0;
end else begin
// otherwise, store the current value of DATA_CHK, increment
// DQ IDELAY, and compare again
cal1_state <= CAL1_FIRST_EDGE_IDEL_WAIT;
cal1_data_chk_last <= cal1_data_chk_r;
// avoid comparing against DATA_CHK_LAST for previous iteration
cal1_data_chk_last_valid <= 1'b1;
cal1_dlyce_dq <= 1'b1;
cal1_dlyinc_dq <= 1'b1;
end
end
 
// wait for DQ IDELAY to settle
CAL1_FIRST_EDGE_IDEL_WAIT:
if (!idel_set_wait)
cal1_state <= CAL1_FIND_FIRST_EDGE;
 
// delay state between finding first edge and looking for second
// edge. Necessary in order to invalidate CAL1_FOUND_WINDOW before
// starting to look for second edge
CAL1_FOUND_FIRST_EDGE_WAIT:
cal1_state <= CAL1_FIND_SECOND_EDGE;
 
// Try and find second edge
CAL1_FIND_SECOND_EDGE: begin
// When looking for 2nd edge, first make sure data stabilized (by
// detecting valid data window) - needed to avoid false edges
if (cal1_found_window) begin
cal1_first_edge_done <= 1'b1;
cal1_dqs_dq_init_phase <= cal1_found_rising;
end
// exit if run out of taps to increment
if (cal1_idel_tap_limit_hit)
cal1_state <= CAL1_CALC_IDEL;
else begin
// found second edge, record the current edge count
if (cal1_first_edge_done && cal1_detect_edge) begin
cal1_state <= CAL1_CALC_IDEL;
cal1_found_second_edge <= 1'b1;
cal1_bit_time_tap_cnt <= cal1_idel_tap_cnt -
cal1_first_edge_tap_cnt + 1;
end else begin
cal1_state <= CAL1_SECOND_EDGE_IDEL_WAIT;
cal1_data_chk_last <= cal1_data_chk_r;
cal1_data_chk_last_valid <= 1'b1;
cal1_dlyce_dq <= 1'b1;
cal1_dlyinc_dq <= 1'b1;
end
end
end
 
// wait for DQ IDELAY to settle, then store ISERDES output
CAL1_SECOND_EDGE_IDEL_WAIT:
if (!idel_set_wait)
cal1_state <= CAL1_FIND_SECOND_EDGE;
 
// pipeline delay state to calculate amount to decrement DQ IDELAY
// NOTE: We're calculating the amount to decrement by, not the
// absolute setting for DQ IDELAY
CAL1_CALC_IDEL: begin
// if two edges found
if (cal1_found_second_edge)
// case 1: DQS was in DQ window to start with. First edge found
// corresponds to left edge of DQ rising window. Backup by 1.5*BT
// NOTE: In this particular case, it is possible to decrement
// "below 0" in the case where DQS delay is less than 0.5*BT,
// need to limit decrement to prevent IDELAY tap underflow
if (!cal1_dqs_dq_init_phase)
cal1_idel_dec_cnt <= {1'b0, cal1_bit_time_tap_cnt} +
{1'b0, (cal1_bit_time_tap_cnt >> 1)};
// case 2: DQS was in wrong DQ window (in DQ falling window).
// First edge found is right edge of DQ rising window. Second
// edge is left edge of DQ rising window. Backup by 0.5*BT
else
cal1_idel_dec_cnt <= {1'b0, (cal1_bit_time_tap_cnt >> 1)};
// if only one edge found - assume will always be case 1 - DQS in
// DQS window. Case 2 only possible if path delay on DQS > 5ns
else
cal1_idel_dec_cnt <= cal1_low_freq_idel_dec;
cal1_state <= CAL1_DEC_IDEL;
end
 
// decrement DQ IDELAY for final adjustment
CAL1_DEC_IDEL:
// once adjustment is complete, we're done with calibration for
// this DQ, now return to IDLE state and repeat for next DQ
// Add underflow protection for case of 2 edges found and DQS
// starting in DQ window (see comments for above state) - note we
// have to take into account delayed value of CAL1_IDEL_TAP_CNT -
// gets updated one clock cycle after CAL1_DLYCE/INC_DQ
if ((cal1_idel_dec_cnt == 7'b0000000) ||
(cal1_dlyce_dq && (cal1_idel_tap_cnt == 6'b000001))) begin
cal1_state <= CAL1_DONE;
// stop when all DQ's calibrated, or DQ[0] cal'ed (for sim)
if ((count_dq == DQ_WIDTH-1) || (SIM_ONLY != 0))
calib_done_tmp[0] <= 1'b1;
else
// need for VHDL simulation to prevent out-of-index error
next_count_dq <= count_dq + 1;
end else begin
// keep decrementing until final tap count reached
cal1_idel_dec_cnt <= cal1_idel_dec_cnt - 1;
cal1_dlyce_dq <= 1'b1;
cal1_dlyinc_dq <= 1'b0;
end
 
// delay state to allow count_dq and DATA_CHK to point to the next
// DQ bit (allows us to potentially begin checking for an edge on
// next DQ right away).
CAL1_DONE:
if (!idel_set_wait) begin
count_dq <= next_count_dq;
if (calib_done_tmp[0]) begin
calib_done[0] <= 1'b1;
cal1_state <= CAL1_IDLE;
end else begin
// request auto-refresh after every 8-bits calibrated to
// avoid tRAS violation
if (cal1_refresh) begin
cal1_ref_req <= 1'b1;
if (calib_ref_done)
cal1_state <= CAL1_INIT;
end else
// if no need this time for refresh, proceed to next bit
cal1_state <= CAL1_INIT;
end
end
endcase
end
 
//***************************************************************************
// Second stage calibration: DQS-FPGA Clock
// Algorithm Description:
// 1. Assumes a training pattern that will produce a pattern oscillating at
// half the core clock frequency each on rise and fall outputs, and such
// that rise and fall outputs are 180 degrees out of phase from each
// other. Note that since the calibration logic runs at half the speed
// of the interface, expect that data sampled with the slow clock always
// to be constant (either always = 1, or = 0, and rise data != fall data)
// unless we cross the edge of the data valid window
// 2. Start by setting RD_DATA_SEL = 0. This selects the rising capture data
// sync'ed to rising edge of core clock, and falling edge data sync'ed
// to falling edge of core clock
// 3. Start looking for an edge. An edge is defined as either: (1) a
// change in capture value or (2) an invalid capture value (e.g. rising
// data != falling data for that same clock cycle).
// 4. If an edge is found, go to step (6). If edge hasn't been found, then
// set RD_DATA_SEL = 1, and try again.
// 5. If no edge is found, then increment IDELAY and return to step (3)
// 6. If an edge if found, then invert RD_DATA_SEL - this shifts the
// capture point 180 degrees from the edge of the window (minus duty
// cycle distortion, delay skew between rising/falling edge capture
// paths, etc.)
// 7. If no edge is found by CAL2_IDEL_TAP_LIMIT (= 63 - # taps used for
// stage 1 calibration), then decrement IDELAY (without reinverting
// RD_DATA_SEL) by CAL2_IDEL_TAP_LIMIT/2. This guarantees we at least
// have CAL2_IDEL_TAP_LIMIT/2 of slack both before and after the
// capture point (not optimal, but best we can do not having found an
// of the window). This happens only for very low frequencies.
// 8. Repeat for each DQS group.
// NOTE: Step 6 is not optimal. A better (and perhaps more complicated)
// algorithm might be to find both edges of the data valid window (using
// the same polarity of RD_DATA_SEL), and then decrement to the midpoint.
//***************************************************************************
 
// RD_DATA_SEL should be tagged with FROM-TO (multi-cycle) constraint in
// UCF file to relax timing. This net is "pseudo-static" (after value is
// changed, FSM waits number of cycles before using the output).
// Note that we are adding one clock cycle of delay (to isolate it from
// the other logic CAL2_RD_DATA_SEL feeds), make sure FSM waits long
// enough to compensate (by default it does, it waits a few cycles more
// than minimum # of clock cycles)
genvar rd_i;
generate
for (rd_i = 0; rd_i < DQS_WIDTH; rd_i = rd_i+1) begin: gen_rd_data_sel
FDRSE u_ff_rd_data_sel
(
.Q (rd_data_sel[rd_i]),
.C (clkdiv),
.CE (1'b1),
.D (cal2_rd_data_sel[rd_i]),
.R (1'b0),
.S (1'b0)
) /* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
end
endgenerate
 
//*****************************************************************
// Max number of taps used for stg2 cal dependent on number of taps
// used for stg1 (give priority to stg1 cal - let it use as many
// taps as it needs - the remainder of the IDELAY taps can be used
// by stg2)
//*****************************************************************
 
always @(posedge clkdiv)
cal2_idel_tap_limit <= 6'b111111 - cal1_idel_max_tap;
 
//*****************************************************************
// second stage calibration uses readback pattern of "1100" (i.e.
// 1st rising = 1, 1st falling = 1, 2nd rising = 0, 2nd falling = 0)
// only look at the first bit of each DQS group
//*****************************************************************
 
// deasserted when captured data has changed since IDELAY was
// incremented, or when we're right on the edge (i.e. rise data =
// fall data).
assign cal2_detect_edge =
((((rdd_rise_q1 != cal2_rd_data_rise_last_pos) ||
(rdd_fall_q1 != cal2_rd_data_fall_last_pos)) &&
cal2_rd_data_last_valid_pos && (!cal2_curr_sel)) ||
(((rdd_rise_q1 != cal2_rd_data_rise_last_neg) ||
(rdd_fall_q1 != cal2_rd_data_fall_last_neg)) &&
cal2_rd_data_last_valid_neg && (cal2_curr_sel)) ||
(rdd_rise_q1 != rdd_fall_q1));
 
//*****************************************************************
// keep track of edge tap counts found, and whether we've
// incremented to the maximum number of taps allowed
// NOTE: Assume stage 2 cal always increments the tap count (never
// decrements) when searching for edge of the data valid window
//*****************************************************************
 
always @(posedge clkdiv)
if (cal2_state == CAL2_INIT) begin
cal2_idel_tap_limit_hit <= 1'b0;
cal2_idel_tap_cnt <= 6'b000000;
end else if (cal2_dlyce_dqs) begin
cal2_idel_tap_cnt <= cal2_idel_tap_cnt + 1;
cal2_idel_tap_limit_hit <= (cal2_idel_tap_cnt ==
cal2_idel_tap_limit - 1);
end
 
//*****************************************************************
 
always @(posedge clkdiv)
if (rstdiv) begin
calib_done[1] <= 1'b0;
calib_done_tmp[1] <= 1'bx;
calib_err[1] <= 1'b0;
count_dqs <= 'b0;
next_count_dqs <= 'b0;
cal2_dlyce_dqs <= 1'b0;
cal2_dlyinc_dqs <= 1'b0;
cal2_idel_dec_cnt <= 6'bxxxxxx;
cal2_rd_data_last_valid_neg <= 1'bx;
cal2_rd_data_last_valid_pos <= 1'bx;
cal2_rd_data_sel <= 'b0;
cal2_ref_req <= 1'b0;
cal2_state <= CAL2_IDLE;
end else begin
cal2_ref_req <= 1'b0;
cal2_dlyce_dqs <= 1'b0;
cal2_dlyinc_dqs <= 1'b0;
 
case (cal2_state)
CAL2_IDLE: begin
count_dqs <= 'b0;
next_count_dqs <= 'b0;
if (calib_start[1]) begin
cal2_rd_data_sel <= {DQS_WIDTH{1'b0}};
calib_done[1] <= 1'b0;
calib_done_tmp[1] <= 1'b0;
cal2_state <= CAL2_INIT;
end
end
 
// Pass through this state every time we calibrate a new DQS group
CAL2_INIT: begin
cal2_curr_sel <= 1'b0;
cal2_rd_data_last_valid_neg <= 1'b0;
cal2_rd_data_last_valid_pos <= 1'b0;
cal2_state <= CAL2_INIT_IDEL_WAIT;
end
 
// Stall state only used if calibration run more than once. Can take
// this state out if design never runs calibration more than once.
// We need this state to give time for MUX'ed data to settle after
// resetting RD_DATA_SEL
CAL2_INIT_IDEL_WAIT:
if (!idel_set_wait)
cal2_state <= CAL2_FIND_EDGE_POS;
 
// Look for an edge - first check "positive-edge" stage 2 capture
CAL2_FIND_EDGE_POS: begin
// if found an edge, then switch to the opposite edge stage 2
// capture and we're done - no need to decrement the tap count,
// since switching to the opposite edge will shift the capture
// point by 180 degrees
if (cal2_detect_edge) begin
cal2_curr_sel <= 1'b1;
cal2_state <= CAL2_DONE;
// set all DQS groups to be the same for simulation
if (SIM_ONLY != 0)
cal2_rd_data_sel <= {DQS_WIDTH{1'b1}};
else
cal2_rd_data_sel[count_dqs] <= 1'b1;
if ((count_dqs == DQS_WIDTH-1) || (SIM_ONLY != 0))
calib_done_tmp[1] <= 1'b1;
else
// MIG 2.1: Fix for simulation out-of-bounds error when
// SIM_ONLY=0, and DQS_WIDTH=(power of 2) (needed for VHDL)
next_count_dqs <= count_dqs + 1;
end else begin
// otherwise, invert polarity of stage 2 capture and look for
// an edge with opposite capture clock polarity
cal2_curr_sel <= 1'b1;
cal2_rd_data_sel[count_dqs] <= 1'b1;
cal2_state <= CAL2_FIND_EDGE_IDEL_WAIT_POS;
cal2_rd_data_rise_last_pos <= rdd_rise_q1;
cal2_rd_data_fall_last_pos <= rdd_fall_q1;
cal2_rd_data_last_valid_pos <= 1'b1;
end
end
 
// Give time to switch from positive-edge to negative-edge second
// stage capture (need time for data to filter though pipe stages)
CAL2_FIND_EDGE_IDEL_WAIT_POS:
if (!idel_set_wait)
cal2_state <= CAL2_FIND_EDGE_NEG;
 
// Look for an edge - check "negative-edge" stage 2 capture
CAL2_FIND_EDGE_NEG:
if (cal2_detect_edge) begin
cal2_curr_sel <= 1'b0;
cal2_state <= CAL2_DONE;
// set all DQS groups to be the same for simulation
if (SIM_ONLY != 0)
cal2_rd_data_sel <= {DQS_WIDTH{1'b0}};
else
cal2_rd_data_sel[count_dqs] <= 1'b0;
if ((count_dqs == DQS_WIDTH-1) || (SIM_ONLY != 0))
calib_done_tmp[1] <= 1'b1;
else
// MIG 2.1: Fix for simulation out-of-bounds error when
// SIM_ONLY=0, and DQS_WIDTH=(power of 2) (needed for VHDL)
next_count_dqs <= count_dqs + 1;
end else if (cal2_idel_tap_limit_hit) begin
// otherwise, if we've run out of taps, then immediately
// backoff by half # of taps used - that's our best estimate
// for optimal calibration point. Doesn't matter whether which
// polarity we're using for capture (we don't know which one is
// best to use)
cal2_idel_dec_cnt <= {1'b0, cal2_idel_tap_limit[5:1]};
cal2_state <= CAL2_DEC_IDEL;
if ((count_dqs == DQS_WIDTH-1) || (SIM_ONLY != 0))
calib_done_tmp[1] <= 1'b1;
else
// MIG 2.1: Fix for simulation out-of-bounds error when
// SIM_ONLY=0, and DQS_WIDTH=(power of 2) (needed for VHDL)
next_count_dqs <= count_dqs + 1;
end else begin
// otherwise, increment IDELAY, and start looking for edge again
cal2_curr_sel <= 1'b0;
cal2_rd_data_sel[count_dqs] <= 1'b0;
cal2_state <= CAL2_FIND_EDGE_IDEL_WAIT_NEG;
cal2_rd_data_rise_last_neg <= rdd_rise_q1;
cal2_rd_data_fall_last_neg <= rdd_fall_q1;
cal2_rd_data_last_valid_neg <= 1'b1;
cal2_dlyce_dqs <= 1'b1;
cal2_dlyinc_dqs <= 1'b1;
end
 
CAL2_FIND_EDGE_IDEL_WAIT_NEG:
if (!idel_set_wait)
cal2_state <= CAL2_FIND_EDGE_POS;
 
// if no edge found, then decrement by half # of taps used
CAL2_DEC_IDEL: begin
if (cal2_idel_dec_cnt == 6'b000000)
cal2_state <= CAL2_DONE;
else begin
cal2_idel_dec_cnt <= cal2_idel_dec_cnt - 1;
cal2_dlyce_dqs <= 1'b1;
cal2_dlyinc_dqs <= 1'b0;
end
end
 
// delay state to allow count_dqs and ISERDES data to point to next
// DQ bit (DQS group) before going to INIT
CAL2_DONE:
if (!idel_set_wait) begin
count_dqs <= next_count_dqs;
if (calib_done_tmp[1]) begin
calib_done[1] <= 1'b1;
cal2_state <= CAL2_IDLE;
end else begin
// request auto-refresh after every DQS group calibrated to
// avoid tRAS violation
cal2_ref_req <= 1'b1;
if (calib_ref_done)
cal2_state <= CAL2_INIT;
end
end
endcase
end
 
//***************************************************************************
// Stage 3 calibration: Read Enable
// Description:
// read enable calibration determines the "round-trip" time (in # of CLK0
// cycles) between when a read command is issued by the controller, and
// when the corresponding read data is synchronized by into the CLK0 domain
// this is a long delay chain to delay read enable signal from controller/
// initialization logic (i.e. this is used for both initialization and
// during normal controller operation). Stage 3 calibration logic decides
// which delayed version is appropriate to use (which is affected by the
// round trip delay of DQ/DQS) as a "valid" signal to tell rest of logic
// when the captured data output from ISERDES is valid.
//***************************************************************************
 
//*****************************************************************
// Delay chains: Use shift registers
// Two sets of delay chains are used:
// 1. One to delay RDEN from PHY_INIT module for calibration
// purposes (delay required for RDEN for calibration is different
// than during normal operation)
// 2. One per DQS group to delay RDEN from controller for normal
// operation - the value to delay for each DQS group can be different
// as is determined during calibration
//*****************************************************************
 
//*****************************************************************
// First delay chain, use only for calibration
// input = asserted on rising edge of RDEN from PHY_INIT module
//*****************************************************************
 
always @(posedge clk) begin
ctrl_rden_r <= ctrl_rden;
phy_init_rden_r <= phy_init_rden;
phy_init_rden_r1 <= phy_init_rden_r;
calib_rden_edge_r <= phy_init_rden_r & ~phy_init_rden_r1;
end
 
// Calibration shift register used for both Stage 3 and Stage 4 cal
// (not strictly necessary for stage 4, but use as an additional check
// to make sure we're checking for correct data on the right clock cycle)
always @(posedge clkdiv)
if (!calib_done[2])
calib_rden_srl_a <= cal3_rden_srl_a;
else
calib_rden_srl_a <= cal4_rden_srl_a;
 
// Flops for targetting of multi-cycle path in UCF
genvar cal_rden_ff_i;
generate
for (cal_rden_ff_i = 0; cal_rden_ff_i < 5;
cal_rden_ff_i = cal_rden_ff_i+1) begin: gen_cal_rden_dly
FDRSE u_ff_cal_rden_dly
(
.Q (calib_rden_srl_a_r[cal_rden_ff_i]),
.C (clkdiv),
.CE (1'b1),
.D (calib_rden_srl_a[cal_rden_ff_i]),
.R (1'b0),
.S (1'b0)
) /* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
end
endgenerate
 
SRLC32E u_calib_rden_srl
(
.Q (calib_rden_srl_out),
.Q31 (),
.A (calib_rden_srl_a_r),
.CE (1'b1),
.CLK (clk),
.D (calib_rden_edge_r)
);
 
FDRSE u_calib_rden_srl_out_r
(
.Q (calib_rden_srl_out_r),
.C (clk),
.CE (1'b1),
.D (calib_rden_srl_out),
.R (1'b0),
.S (1'b0)
) /* synthesis syn_preserve = 1 */;
 
// convert to CLKDIV domain. Two version are generated because we need
// to be able to tell exactly which fast (clk) clock cycle the read
// enable was asserted in. Only one of CALIB_DATA_VALID or
// CALIB_DATA_VALID_STGD will be asserted for any given shift value
always @(posedge clk)
calib_rden_srl_out_r1 <= calib_rden_srl_out_r;
 
always @(posedge clkdiv) begin
calib_rden_valid <= calib_rden_srl_out_r;
calib_rden_valid_stgd <= calib_rden_srl_out_r1;
end
 
//*****************************************************************
// Second set of delays chain, use for normal reads
// input = RDEN from controller
//*****************************************************************
 
// Flops for targetting of multi-cycle path in UCF
genvar rden_ff_i;
generate
for (rden_ff_i = 0; rden_ff_i < 5*DQS_WIDTH;
rden_ff_i = rden_ff_i+1) begin: gen_rden_dly
FDRSE u_ff_rden_dly
(
.Q (rden_dly_r[rden_ff_i]),
.C (clkdiv),
.CE (1'b1),
.D (rden_dly[rden_ff_i]),
.R (1'b0),
.S (1'b0)
) /* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
end
endgenerate
 
// NOTE: Comment this section explaining purpose of SRL's
genvar rden_i;
generate
for (rden_i = 0; rden_i < DQS_WIDTH; rden_i = rden_i + 1) begin: gen_rden
SRLC32E u_rden_srl
(
.Q (rden_srl_out[rden_i]),
.Q31 (),
.A ({rden_dly_r[(rden_i*5)+4],
rden_dly_r[(rden_i*5)+3],
rden_dly_r[(rden_i*5)+2],
rden_dly_r[(rden_i*5)+1],
rden_dly_r[(rden_i*5)]}),
.CE (1'b1),
.CLK (clk),
.D (ctrl_rden_r)
);
FDRSE u_calib_rden_r
(
.Q (calib_rden[rden_i]),
.C (clk),
.CE (1'b1),
.D (rden_srl_out[rden_i]),
.R (1'b0),
.S (1'b0)
) /* synthesis syn_preserve = 1 */;
end
endgenerate
 
//*****************************************************************
// indicates that current received data is the correct pattern. Check both
// rising and falling data for first DQ in each DQS group. Note that
// we're checking using a pipelined version of read data, so need to take
// this inherent delay into account in determining final read valid delay
// Data is written to the memory in the following order (first -> last):
// 0x1, 0xE, 0xE, 0x1, 0x1, 0xE, 0xE, 0x1
// Looking just at LSb, expect data in sequence (in binary):
// 1, 0, 0, 1, 1, 0, 0, 1
// Check for the presence of the first 7 words, and compensate read valid
// delay accordingly. Don't check last falling edge data, it may be
// corrupted by the DQS tri-state glitch at end of read postamble
// (glitch protection not yet active until stage 4 cal)
//*****************************************************************
 
always @(posedge clkdiv) begin
rdd_rise_q1_r <= rdd_rise_q1;
rdd_fall_q1_r <= rdd_fall_q1;
rdd_rise_q2_r <= rdd_rise_q2;
rdd_fall_q2_r <= rdd_fall_q2;
rdd_rise_q1_r1 <= rdd_rise_q1_r;
rdd_fall_q1_r1 <= rdd_fall_q1_r;
end
 
always @(posedge clkdiv) begin
// For the following sequence from memory:
// rise[0], fall[0], rise[1], fall[1]
// if data is aligned out of fabric ISERDES:
// RDD_RISE_Q2 = rise[0]
// RDD_FALL_Q2 = fall[0]
// RDD_RISE_Q1 = rise[1]
// RDD_FALL_Q1 = fall[1]
cal3_data_match <= ((rdd_rise_q2_r == 1) &&
(rdd_fall_q2_r == 0) &&
(rdd_rise_q1_r == 0) &&
(rdd_fall_q1_r == 1) &&
(rdd_rise_q2 == 1) &&
(rdd_fall_q2 == 0) &&
(rdd_rise_q1 == 0));
 
// if data is staggered out of fabric ISERDES:
// RDD_RISE_Q1_R = rise[0]
// RDD_FALL_Q1_R = fall[0]
// RDD_RISE_Q2 = rise[1]
// RDD_FALL_Q2 = fall[1]
cal3_data_match_stgd <= ((rdd_rise_q1_r1 == 1) &&
(rdd_fall_q1_r1 == 0) &&
(rdd_rise_q2_r == 0) &&
(rdd_fall_q2_r == 1) &&
(rdd_rise_q1_r == 1) &&
(rdd_fall_q1_r == 0) &&
(rdd_rise_q2 == 0));
end
 
assign cal3_rden_dly = cal3_rden_srl_a - CAL3_RDEN_SRL_DLY_DELTA;
assign cal3_data_valid = (calib_rden_valid | calib_rden_valid_stgd);
assign cal3_match_found
= ((calib_rden_valid && cal3_data_match) ||
(calib_rden_valid_stgd && cal3_data_match_stgd));
 
// when calibrating, check to see which clock cycle (after the read is
// issued) does the expected data pattern arrive. Record this result
// NOTE: Can add error checking here in case valid data not found on any
// of the available pipeline stages
always @(posedge clkdiv) begin
if (rstdiv) begin
cal3_rden_srl_a <= 5'bxxxxx;
cal3_state <= CAL3_IDLE;
calib_done[2] <= 1'b0;
calib_err_2[0] <= 1'b0;
count_rden <= {DQS_WIDTH{1'b0}};
rden_dly <= {5*DQS_WIDTH{1'b0}};
end else begin
 
case (cal3_state)
CAL3_IDLE: begin
count_rden <= {DQS_WIDTH{1'b0}};
if (calib_start[2]) begin
calib_done[2] <= 1'b0;
cal3_state <= CAL3_INIT;
end
end
 
CAL3_INIT: begin
cal3_rden_srl_a <= RDEN_BASE_DELAY;
// let SRL pipe clear after loading initial shift value
cal3_state <= CAL3_RDEN_PIPE_CLR_WAIT;
end
 
CAL3_DETECT:
if (cal3_data_valid)
// if match found at the correct clock cycle
if (cal3_match_found) begin
 
// For simulation, load SRL addresses for all DQS with same value
if (SIM_ONLY != 0) begin
for (i = 0; i < DQS_WIDTH; i = i + 1) begin: loop_sim_rden_dly
rden_dly[(i*5)] <= cal3_rden_dly[0];
rden_dly[(i*5)+1] <= cal3_rden_dly[1];
rden_dly[(i*5)+2] <= cal3_rden_dly[2];
rden_dly[(i*5)+3] <= cal3_rden_dly[3];
rden_dly[(i*5)+4] <= cal3_rden_dly[4];
end
end else begin
rden_dly[(count_rden*5)] <= cal3_rden_dly[0];
rden_dly[(count_rden*5)+1] <= cal3_rden_dly[1];
rden_dly[(count_rden*5)+2] <= cal3_rden_dly[2];
rden_dly[(count_rden*5)+3] <= cal3_rden_dly[3];
rden_dly[(count_rden*5)+4] <= cal3_rden_dly[4];
end
 
// Use for stage 4 calibration
calib_rden_dly[(count_rden*5)] <= cal3_rden_srl_a[0];
calib_rden_dly[(count_rden*5)+1] <= cal3_rden_srl_a[1];
calib_rden_dly[(count_rden*5)+2] <= cal3_rden_srl_a[2];
calib_rden_dly[(count_rden*5)+3] <= cal3_rden_srl_a[3];
calib_rden_dly[(count_rden*5)+4] <= cal3_rden_srl_a[4];
cal3_state <= CAL3_DONE;
end else begin
// If we run out of stages to shift, without finding correct
// result, the stop and assert error
if (cal3_rden_srl_a == 5'b11111) begin
calib_err_2[0] <= 1'b1;
cal3_state <= CAL3_IDLE;
end else begin
// otherwise, increase the shift value and try again
cal3_rden_srl_a <= cal3_rden_srl_a + 1;
cal3_state <= CAL3_RDEN_PIPE_CLR_WAIT;
end
end
 
// give additional time for RDEN_R pipe to clear from effects of
// previous pipeline or IDELAY tap change
CAL3_RDEN_PIPE_CLR_WAIT:
if (calib_rden_pipe_cnt == 5'b00000)
cal3_state <= CAL3_DETECT;
 
CAL3_DONE: begin
if ((count_rden == DQS_WIDTH-1) || (SIM_ONLY != 0)) begin
calib_done[2] <= 1'b1;
cal3_state <= CAL3_IDLE;
end else begin
count_rden <= count_rden + 1;
cal3_state <= CAL3_INIT;
end
end
endcase
end
end
 
//*****************************************************************
// Last part of stage 3 calibration - compensate for differences
// in delay between different DQS groups. Assume that in the worst
// case, DQS groups can only differ by one clock cycle. Data for
// certain DQS groups must be delayed by one clock cycle.
// NOTE: May need to increase allowable variation to greater than
// one clock cycle in certain customer designs.
// Algorithm is:
// 1. Record shift delay value for DQS[0]
// 2. Compare each DQS[x] delay value to that of DQS[0]:
// - If different, than record this fact (RDEN_MUX)
// - If greater than DQS[0], set RDEN_INC. Assume greater by
// one clock cycle only - this is a key assumption, assume no
// more than a one clock cycle variation.
// - If less than DQS[0], set RDEN_DEC
// 3. After calibration is complete, set control for DQS group
// delay (CALIB_RDEN_SEL):
// - If RDEN_DEC = 1, then assume that DQS[0] is the lowest
// delay (and at least one other DQS group has a higher
// delay).
// - If RDEN_INC = 1, then assume that DQS[0] is the highest
// delay (and that all other DQS groups have the same or
// lower delay).
// - If both RDEN_INC and RDEN_DEC = 1, then flag error
// (variation is too high for this algorithm to handle)
//*****************************************************************
 
always @(posedge clkdiv) begin
if (rstdiv) begin
calib_err_2[1] <= 1'b0;
calib_rden_sel <= {DQS_WIDTH{1'bx}};
rden_dec <= 1'b0;
rden_dly_0 <= 5'bxxxxx;
rden_inc <= 1'b0;
rden_mux <= {DQS_WIDTH{1'b0}};
end else begin
// if a match if found, then store the value of rden_dly
if (!calib_done[2]) begin
if ((cal3_state == CAL3_DETECT) && cal3_match_found) begin
// store the value for DQS[0] as a reference
if (count_rden == 0) begin
// for simulation, RDEN calibration only happens for DQS[0]
// set RDEN_MUX for all DQS groups to be the same as DQS[0]
if (SIM_ONLY != 0)
rden_mux <= {DQS_WIDTH{1'b0}};
else begin
// otherwise, load values for DQS[0]
rden_dly_0 <= cal3_rden_srl_a;
rden_mux[0] <= 1'b0;
end
end else if (SIM_ONLY == 0) begin
// for all other DQS groups, compare RDEN_DLY delay value with
// that of DQS[0]
if (rden_dly_0 != cal3_rden_srl_a) begin
// record that current DQS group has a different delay
// than DQS[0] (the "reference" DQS group)
rden_mux[count_rden] <= 1'b1;
if (rden_dly_0 > cal3_rden_srl_a)
rden_inc <= 1'b1;
else if (rden_dly_0 < cal3_rden_srl_a)
rden_dec <= 1'b1;
// otherwise, if current DQS group has same delay as DQS[0],
// then rden_mux[count_rden] remains at 0 (since rden_mux
// array contents initialized to 0)
end
end
end
end else begin
// Otherwise - if we're done w/ stage 2 calibration:
// set final value for RDEN data delay
// flag error if there's more than one cycle variation from DQS[0]
calib_err_2[1] <= (rden_inc && rden_dec);
if (rden_inc)
// if DQS[0] delay represents max delay
calib_rden_sel <= ~rden_mux;
else
// if DQS[0] delay represents min delay (or all the delays are
// the same between DQS groups)
calib_rden_sel <= rden_mux;
end
end
end
 
// flag error for stage 3 if appropriate
always @(posedge clkdiv)
calib_err[2] <= calib_err_2[0] | calib_err_2[1];
 
//***************************************************************************
// Stage 4 calibration: DQS gate
//***************************************************************************
 
//*****************************************************************
// indicates that current received data is the correct pattern. Same as
// for READ VALID calibration, except that the expected data sequence is
// different since DQS gate is asserted after the 6th word.
// Data sequence:
// Arrives from memory (at FPGA input) (R, F): 1 0 0 1 1 0 0 1
// After gating the sequence looks like: 1 0 0 1 1 0 1 0 (7th word =
// 5th word, 8th word = 6th word)
// What is the gate timing is off? Need to make sure we can distinquish
// between the results of correct vs. incorrect gate timing. We also use
// the "read_valid" signal from stage 3 calibration to help us determine
// when to check for a valid sequence for stage 4 calibration (i.e. use
// CAL4_DATA_VALID in addition to CAL4_DATA_MATCH/CAL4_DATA_MATCH_STGD)
// Note that since the gate signal from the CLK0 domain is synchronized
// to the falling edge of DQS, that the effect of the gate will only be
// seen starting with a rising edge data (although it is possible
// the GATE IDDR output could go metastable and cause a unexpected result
// on the first rising and falling edges after the gate is enabled).
// Also note that the actual DQS glitch can come more than 0.5*tCK after
// the last falling edge of DQS and the constraint for this path is can
// be > 0.5*tCK; however, this means when calibrating, the output of the
// GATE IDDR may miss the setup time requirement of the rising edge flop
// and only meet it for the falling edge flop. Therefore the rising
// edge data immediately following the assertion of the gate can either
// be a 1 or 0 (can rely on either)
// As the timing on the gate is varied, we expect to see (sequence of
// captured read data shown below):
// - 1 0 0 1 1 0 0 1 (gate is really early, starts and ends before
// read burst even starts)
// - x 0 0 1 1 0 0 1 (gate pulse starts before the burst, and ends
// - x y 0 1 1 0 0 1 sometime during the burst; x,y = 0, or 1, but
// - x y x 1 1 0 0 1 all bits that show an x are the same value,
// - x y x y 1 0 0 1 and y are the same value)
// - x y x y x 0 0 1
// - x y x y x y 0 1 (gate starts just before start of burst)
// - 1 0 x 0 x 0 x 0 (gate starts after 1st falling word. The "x"
// represents possiblity that gate may not disable
// clock for 2nd rising word in time)
// - 1 0 0 1 x 1 x 1 (gate starts after 2nd falling word)
// - 1 0 0 1 1 0 x 0 (gate starts after 3rd falling word - GOOD!!)
// - 1 0 0 1 1 0 0 1 (gate starts after burst is already done)
//*****************************************************************
 
assign cal4_data_valid = calib_rden_valid | calib_rden_valid_stgd;
assign cal4_data_good = (calib_rden_valid &
cal4_data_match) |
(calib_rden_valid_stgd &
cal4_data_match_stgd);
 
always @(posedge clkdiv) begin
// if data is aligned out of fabric ISERDES:
cal4_data_match <= ((rdd_rise_q2_r == 1) &&
(rdd_fall_q2_r == 0) &&
(rdd_rise_q1_r == 0) &&
(rdd_fall_q1_r == 1) &&
(rdd_rise_q2 == 1) &&
(rdd_fall_q2 == 0) &&
// MIG 2.1: Last rising edge data value not
// guaranteed to be certain value at higher
// frequencies
// (rdd_rise_q1 == 0) &&
(rdd_fall_q1 == 0));
// if data is staggered out of fabric ISERDES:
cal4_data_match_stgd <= ((rdd_rise_q1_r1 == 1) &&
(rdd_fall_q1_r1 == 0) &&
(rdd_rise_q2_r == 0) &&
(rdd_fall_q2_r == 1) &&
(rdd_rise_q1_r == 1) &&
(rdd_fall_q1_r == 0) &&
// MIG 2.1: Last rising edge data value not
// guaranteed to be certain value at higher
// frequencies
// (rdd_rise_q2 == 0) &&
(rdd_fall_q2 == 0));
end
 
//*****************************************************************
// DQS gate enable generation:
// This signal gets synchronized to DQS domain, and drives IDDR
// register that in turn asserts/deasserts CE to all 4 or 8 DQ
// IDDR's in that DQS group.
// 1. During normal (post-cal) operation, this is only for 2 clock
// cycles following the end of a burst. Check for falling edge
// of RDEN. But must also make sure NOT assert for a read-idle-
// read (two non-consecutive reads, separated by exactly one
// idle cycle) - in this case, don't assert the gate because:
// (1) we don't have enough time to deassert the gate before the
// first rising edge of DQS for second burst (b/c of fact
// that DQS gate is generated in the fabric only off rising
// edge of CLK0 - if we somehow had an ODDR in fabric, we
// could pull this off, (2) assumption is that the DQS glitch
// will not rise enough to cause a glitch because the
// post-amble of the first burst is followed immediately by
// the pre-amble of the next burst
// 2. During stage 4 calibration, assert for 3 clock cycles
// (assert gate enable one clock cycle early), since we gate out
// the last two words (in addition to the crap on the DQ bus after
// the DQS read postamble).
// NOTE: PHY_INIT_RDEN and CTRL_RDEN have slightly different timing w/r
// to when they are asserted w/r to the start of the read burst
// (PHY_INIT_RDEN is one cycle earlier than CTRL_RDEN).
//*****************************************************************
 
// register for timing purposes for fast clock path - currently only
// calib_done_r[2] used
always @(posedge clk)
calib_done_r <= calib_done;
 
always @(*) begin
calib_ctrl_rden = ctrl_rden;
calib_init_rden = calib_done_r[2] & phy_init_rden;
end
 
assign calib_ctrl_rden_negedge = ~calib_ctrl_rden & calib_ctrl_rden_r;
// check for read-idle-read before asserting DQS pulse at end of read
assign calib_ctrl_gate_pulse = calib_ctrl_rden_negedge_r &
~calib_ctrl_rden;
always @(posedge clk) begin
calib_ctrl_rden_r <= calib_ctrl_rden;
calib_ctrl_rden_negedge_r <= calib_ctrl_rden_negedge;
calib_ctrl_gate_pulse_r <= calib_ctrl_gate_pulse;
end
 
assign calib_init_gate_pulse = ~calib_init_rden & calib_init_rden_r;
always @(posedge clk) begin
calib_init_rden_r <= calib_init_rden;
calib_init_gate_pulse_r <= calib_init_gate_pulse;
calib_init_gate_pulse_r1 <= calib_init_gate_pulse_r;
end
 
// Gate is asserted: (1) during cal, for 3 cycles, starting 1 cycle
// after falling edge of CTRL_RDEN, (2) during normal ops, for 2
// cycles, starting 2 cycles after falling edge of CTRL_RDEN
assign gate_srl_in = ~((calib_ctrl_gate_pulse |
calib_ctrl_gate_pulse_r) |
(calib_init_gate_pulse |
calib_init_gate_pulse_r |
calib_init_gate_pulse_r1));
 
//*****************************************************************
// generate DQS enable signal for each DQS group
// There are differences between DQS gate signal for calibration vs. during
// normal operation:
// * calibration gates the second to last clock cycle of the burst,
// rather than after the last word (e.g. for a 8-word, 4-cycle burst,
// cycle 4 is gated for calibration; during normal operation, cycle
// 5 (i.e. cycle after the last word) is gated)
// enable for DQS is deasserted for two clock cycles, except when
// we have the preamble for the next read immediately following
// the postamble of the current read - assume DQS does not glitch
// during this time, that it stays low. Also if we did have to gate
// the DQS for this case, then we don't have enough time to deassert
// the gate in time for the first rising edge of DQS for the second
// read
//*****************************************************************
 
// Flops for targetting of multi-cycle path in UCF
genvar gate_ff_i;
generate
for (gate_ff_i = 0; gate_ff_i < 5*DQS_WIDTH;
gate_ff_i = gate_ff_i+1) begin: gen_gate_dly
FDRSE u_ff_gate_dly
(
.Q (gate_dly_r[gate_ff_i]),
.C (clkdiv),
.CE (1'b1),
.D (gate_dly[gate_ff_i]),
.R (1'b0),
.S (1'b0)
) /* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
end
endgenerate
 
genvar gate_i;
generate
for (gate_i = 0; gate_i < DQS_WIDTH; gate_i = gate_i + 1) begin: gen_gate
SRLC32E u_gate_srl
(
.Q (gate_srl_out[gate_i]),
.Q31 (),
.A ({gate_dly_r[(gate_i*5)+4],
gate_dly_r[(gate_i*5)+3],
gate_dly_r[(gate_i*5)+2],
gate_dly_r[(gate_i*5)+1],
gate_dly_r[(gate_i*5)]}),
.CE (1'b1),
.CLK (clk),
.D (gate_srl_in)
);
 
// For GATE_BASE_DELAY > 0, have one extra cycle to register outputs
// from controller before generating DQS gate pulse. In PAR, the
// location of the controller logic can be far from the DQS gate
// logic (DQS gate logic located near the DQS I/O's), contributing
// to large net delays. Registering the controller outputs for
// CL >= 4 (above 200MHz) adds a stage of pipelining to reduce net
// delays
if (GATE_BASE_DELAY > 0) begin: gen_gate_base_dly_gt3
// add flop between SRL32 and EN_DQS flop (which is located near the
// DDR2 IOB's)
FDRSE u_gate_srl_ff
(
.Q (gate_srl_out_r[gate_i]),
.C (clk),
.CE (1'b1),
.D (gate_srl_out[gate_i]),
.R (1'b0),
.S (1'b0)
) /* synthesis syn_preserve = 1 */;
end else begin: gen_gate_base_dly_le3
assign gate_srl_out_r[gate_i] = gate_srl_out[gate_i];
end
 
FDRSE u_en_dqs_ff
(
.Q (en_dqs[gate_i]),
.C (clk),
.CE (1'b1),
.D (gate_srl_out_r[gate_i]),
.R (1'b0),
.S (1'b0)
) /* synthesis syn_preserve = 1 */
/* synthesis syn_replicate = 0 */;
end
endgenerate
 
//*****************************************************************
// Find valid window: keep track of how long we've been in the same data
// window. If it's been long enough, then declare that we've found a stable
// valid window - in particular, that we're past any region of instability
// associated with the edge of the window. Use only when finding left edge
//*****************************************************************
 
always @(posedge clkdiv)
// reset before we start to look for window
if (cal4_state == CAL4_INIT) begin
cal4_window_cnt <= 4'b0000;
cal4_stable_window <= 1'b0;
end else if ((cal4_state == CAL4_FIND_EDGE) && cal4_seek_left) begin
// if we're looking for left edge, and incrementing IDELAY, count
// consecutive taps over which we're in the window
if (cal4_data_valid) begin
if (cal4_data_good)
cal4_window_cnt <= cal4_window_cnt + 1;
else
cal4_window_cnt <= 4'b0000;
end
 
if (cal4_window_cnt == MIN_WIN_SIZE-1)
cal4_stable_window <= 1'b1;
end
 
//*****************************************************************
// keep track of edge tap counts found, and whether we've
// incremented to the maximum number of taps allowed
//*****************************************************************
 
always @(posedge clkdiv)
if ((cal4_state == CAL4_INIT) || cal4_dlyrst_gate) begin
cal4_idel_max_tap <= 1'b0;
cal4_idel_bit_tap <= 1'b0;
cal4_idel_tap_cnt <= 6'b000000;
end else if (cal4_dlyce_gate) begin
if (cal4_dlyinc_gate) begin
cal4_idel_tap_cnt <= cal4_idel_tap_cnt + 1;
cal4_idel_bit_tap <= (cal4_idel_tap_cnt == CAL4_IDEL_BIT_VAL-2);
cal4_idel_max_tap <= (cal4_idel_tap_cnt == 6'b111110);
end else begin
cal4_idel_tap_cnt <= cal4_idel_tap_cnt - 1;
cal4_idel_bit_tap <= 1'b0;
cal4_idel_max_tap <= 1'b0;
end
end
 
always @(posedge clkdiv)
if ((cal4_state != CAL4_RDEN_PIPE_CLR_WAIT) &&
(cal3_state != CAL3_RDEN_PIPE_CLR_WAIT))
calib_rden_pipe_cnt <= CALIB_RDEN_PIPE_LEN-1;
else
calib_rden_pipe_cnt <= calib_rden_pipe_cnt - 1;
 
//*****************************************************************
// Stage 4 cal state machine
//*****************************************************************
 
always @(posedge clkdiv)
if (rstdiv) begin
calib_done[3] <= 1'b0;
calib_done_tmp[3] <= 1'b0;
calib_err[3] <= 1'b0;
count_gate <= 'b0;
gate_dly <= 'b0;
next_count_gate <= 'b0;
cal4_idel_adj_cnt <= 6'bxxxxxx;
cal4_dlyce_gate <= 1'b0;
cal4_dlyinc_gate <= 1'b0;
cal4_dlyrst_gate <= 1'b0; // reset handled elsewhere in code
cal4_gate_srl_a <= 5'bxxxxx;
cal4_rden_srl_a <= 5'bxxxxx;
cal4_ref_req <= 1'b0;
cal4_seek_left <= 1'bx;
cal4_state <= CAL4_IDLE;
end else begin
cal4_ref_req <= 1'b0;
cal4_dlyce_gate <= 1'b0;
cal4_dlyinc_gate <= 1'b0;
cal4_dlyrst_gate <= 1'b0;
 
case (cal4_state)
CAL4_IDLE: begin
count_gate <= 'b0;
next_count_gate <= 'b0;
if (calib_start[3]) begin
gate_dly <= 'b0;
calib_done[3] <= 1'b0;
cal4_state <= CAL4_INIT;
end
end
 
CAL4_INIT: begin
// load: (1) initial value of gate delay SRL, (2) appropriate
// value of RDEN SRL (so that we get correct "data valid" timing)
cal4_gate_srl_a <= GATE_BASE_INIT;
cal4_rden_srl_a <= {calib_rden_dly[(count_gate*5)+4],
calib_rden_dly[(count_gate*5)+3],
calib_rden_dly[(count_gate*5)+2],
calib_rden_dly[(count_gate*5)+1],
calib_rden_dly[(count_gate*5)]};
// let SRL pipe clear after loading initial shift value
cal4_state <= CAL4_RDEN_PIPE_CLR_WAIT;
end
 
// sort of an initial state - start checking to see whether we're
// already in the window or not
CAL4_FIND_WINDOW:
// decide right away if we start in the proper window - this
// determines if we are then looking for the left (trailing) or
// right (leading) edge of the data valid window
if (cal4_data_valid) begin
// if we find a match - then we're already in window, now look
// for left edge. Otherwise, look for right edge of window
cal4_seek_left <= cal4_data_good;
cal4_state <= CAL4_FIND_EDGE;
end
 
CAL4_FIND_EDGE:
// don't do anything until the exact clock cycle when to check that
// readback data is valid or not
if (cal4_data_valid) begin
// we're currently in the window, look for left edge of window
if (cal4_seek_left) begin
// make sure we've passed the right edge before trying to detect
// the left edge (i.e. avoid any edge "instability") - else, we
// may detect an "false" edge too soon. By design, if we start in
// the data valid window, always expect at least
// MIN(BIT_TIME_TAPS,32) (-/+ jitter, see below) taps of valid
// window before we hit the left edge (this is because when stage
// 4 calibration first begins (i.e., gate_dly = 00, and IDELAY =
// 00), we're guaranteed to NOT be in the window, and we always
// start searching for MIN(BIT_TIME_TAPS,32) for the right edge
// of window. If we don't find it, increment gate_dly, and if we
// now start in the window, we have at least approximately
// CLK_PERIOD-MIN(BIT_TIME_TAPS,32) = MIN(BIT_TIME_TAPS,32) taps.
// It's approximately because jitter, noise, etc. can bring this
// value down slightly. Because of this (although VERY UNLIKELY),
// we have to protect against not decrementing IDELAY below 0
// during adjustment phase).
if (cal4_stable_window && !cal4_data_good) begin
// found left edge of window, dec by MIN(BIT_TIME_TAPS,32)
cal4_idel_adj_cnt <= CAL4_IDEL_BIT_VAL;
cal4_idel_adj_inc <= 1'b0;
cal4_state <= CAL4_ADJ_IDEL;
end else begin
// Otherwise, keep looking for left edge:
if (cal4_idel_max_tap) begin
// ran out of taps looking for left edge (max=63) - happens
// for low frequency case, decrement by 32
cal4_idel_adj_cnt <= 6'b100000;
cal4_idel_adj_inc <= 1'b0;
cal4_state <= CAL4_ADJ_IDEL;
end else begin
cal4_dlyce_gate <= 1'b1;
cal4_dlyinc_gate <= 1'b1;
cal4_state <= CAL4_IDEL_WAIT;
end
end
end else begin
// looking for right edge of window:
// look for the first match - this means we've found the right
// (leading) edge of the data valid window, increment by
// MIN(BIT_TIME_TAPS,32)
if (cal4_data_good) begin
cal4_idel_adj_cnt <= CAL4_IDEL_BIT_VAL;
cal4_idel_adj_inc <= 1'b1;
cal4_state <= CAL4_ADJ_IDEL;
end else begin
// Otherwise, keep looking:
// only look for MIN(BIT_TIME_TAPS,32) taps for right edge,
// if we haven't found it, then inc gate delay, try again
if (cal4_idel_bit_tap) begin
// if we're already maxed out on gate delay, then error out
// (simulation only - calib_err isn't currently connected)
if (cal4_gate_srl_a == 5'b11111) begin
calib_err[3] <= 1'b1;
cal4_state <= CAL4_IDLE;
end else begin
// otherwise, increment gate delay count, and start
// over again
cal4_gate_srl_a <= cal4_gate_srl_a + 1;
cal4_dlyrst_gate <= 1'b1;
cal4_state <= CAL4_RDEN_PIPE_CLR_WAIT;
end
end else begin
// keep looking for right edge
cal4_dlyce_gate <= 1'b1;
cal4_dlyinc_gate <= 1'b1;
cal4_state <= CAL4_IDEL_WAIT;
end
end
end
end
 
// wait for GATE IDELAY to settle, after reset or increment
CAL4_IDEL_WAIT: begin
// For simulation, load SRL addresses for all DQS with same value
if (SIM_ONLY != 0) begin
for (i = 0; i < DQS_WIDTH; i = i + 1) begin: loop_sim_gate_dly
gate_dly[(i*5)+4] <= cal4_gate_srl_a[4];
gate_dly[(i*5)+3] <= cal4_gate_srl_a[3];
gate_dly[(i*5)+2] <= cal4_gate_srl_a[2];
gate_dly[(i*5)+1] <= cal4_gate_srl_a[1];
gate_dly[(i*5)] <= cal4_gate_srl_a[0];
end
end else begin
gate_dly[(count_gate*5)+4] <= cal4_gate_srl_a[4];
gate_dly[(count_gate*5)+3] <= cal4_gate_srl_a[3];
gate_dly[(count_gate*5)+2] <= cal4_gate_srl_a[2];
gate_dly[(count_gate*5)+1] <= cal4_gate_srl_a[1];
gate_dly[(count_gate*5)] <= cal4_gate_srl_a[0];
end
// check to see if we've found edge of window
if (!idel_set_wait)
cal4_state <= CAL4_FIND_EDGE;
end
 
// give additional time for RDEN_R pipe to clear from effects of
// previous pipeline (and IDELAY reset)
CAL4_RDEN_PIPE_CLR_WAIT: begin
// MIG 2.2: Bug fix - make sure to update GATE_DLY count, since
// possible for FIND_EDGE->RDEN_PIPE_CLR_WAIT->FIND_WINDOW
// transition (i.e. need to make sure the gate count updated in
// FIND_EDGE gets reflected in GATE_DLY by the time we reach
// state FIND_WINDOW) - previously GATE_DLY only being updated
// during state CAL4_IDEL_WAIT
if (SIM_ONLY != 0) begin
for (i = 0; i < DQS_WIDTH; i = i + 1) begin: loop_sim_gate_dly_pipe
gate_dly[(i*5)+4] <= cal4_gate_srl_a[4];
gate_dly[(i*5)+3] <= cal4_gate_srl_a[3];
gate_dly[(i*5)+2] <= cal4_gate_srl_a[2];
gate_dly[(i*5)+1] <= cal4_gate_srl_a[1];
gate_dly[(i*5)] <= cal4_gate_srl_a[0];
end
end else begin
gate_dly[(count_gate*5)+4] <= cal4_gate_srl_a[4];
gate_dly[(count_gate*5)+3] <= cal4_gate_srl_a[3];
gate_dly[(count_gate*5)+2] <= cal4_gate_srl_a[2];
gate_dly[(count_gate*5)+1] <= cal4_gate_srl_a[1];
gate_dly[(count_gate*5)] <= cal4_gate_srl_a[0];
end
// look for new window
if (calib_rden_pipe_cnt == 5'b00000)
cal4_state <= CAL4_FIND_WINDOW;
end
 
// increment/decrement DQS/DQ IDELAY for final adjustment
CAL4_ADJ_IDEL:
// add underflow protection for corner case when left edge found
// using fewer than MIN(BIT_TIME_TAPS,32) taps
if ((cal4_idel_adj_cnt == 6'b000000) ||
(cal4_dlyce_gate && !cal4_dlyinc_gate &&
(cal4_idel_tap_cnt == 6'b000001))) begin
cal4_state <= CAL4_DONE;
// stop when all gates calibrated, or gate[0] cal'ed (for sim)
if ((count_gate == DQS_WIDTH-1) || (SIM_ONLY != 0))
calib_done_tmp[3] <= 1'b1;
else
// need for VHDL simulation to prevent out-of-index error
next_count_gate <= count_gate + 1;
end else begin
cal4_idel_adj_cnt <= cal4_idel_adj_cnt - 1;
cal4_dlyce_gate <= 1'b1;
// whether inc or dec depends on whether left or right edge found
cal4_dlyinc_gate <= cal4_idel_adj_inc;
end
 
// wait for IDELAY output to settle after decrement. Check current
// COUNT_GATE value and decide if we're done
CAL4_DONE:
if (!idel_set_wait) begin
count_gate <= next_count_gate;
if (calib_done_tmp[3]) begin
calib_done[3] <= 1'b1;
cal4_state <= CAL4_IDLE;
end else begin
// request auto-refresh after every DQS group calibrated to
// avoid tRAS violation
cal4_ref_req <= 1'b1;
if (calib_ref_done)
cal4_state <= CAL4_INIT;
end
end
endcase
end
 
endmodule
/boards/xilinx/ml501/rtl/verilog/xilinx_ddr2/ddr2_idelay_ctrl.v
0,0 → 1,87
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007, 2008 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_idelay_ctrl.v
// /___/ /\ Date Last Modified: $Date: 2008/12/23 14:26:00 $
// \ \ / \ Date Created: Wed Aug 16 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR2
//Purpose:
// This module instantiates the IDELAYCTRL primitive of the Virtex-5 device
// which continuously calibrates the IDELAY elements in the region in case of
// varying operating conditions. It takes a 200MHz clock as an input
//Reference:
//Revision History:
// Rev 1.1 - Parameter IODELAY_GRP added and constraint IODELAY_GROUP added
// on IOELAYCTRL primitive. Generate logic on IDELAYCTRL removed
// since tools will replicate idelactrl primitives.PK. 11/27/08
//*****************************************************************************
 
`timescale 1ns/1ps
 
module ddr2_idelay_ctrl #
(
// Following parameters are for 72-bit RDIMM design (for ML561 Reference
// board design). Actual values may be different. Actual parameters values
// are passed from design top module ddr2_mig module. Please refer to
// the ddr2_mig module for actual values.
parameter IODELAY_GRP = "IODELAY_MIG"
)
 
(
input clk200,
input rst200,
output idelay_ctrl_rdy
);
 
(* IODELAY_GROUP = IODELAY_GRP *) IDELAYCTRL u_idelayctrl
(
.RDY(idelay_ctrl_rdy),
.REFCLK(clk200),
.RST(rst200)
);
 
endmodule
/boards/xilinx/ml501/rtl/verilog/xilinx_ddr2/ddr2_usr_top.v
0,0 → 1,184
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_usr_top.v
// /___/ /\ Date Last Modified: $Date: 2008/12/23 14:26:01 $
// \ \ / \ Date Created: Mon Aug 28 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR2
//Purpose:
// This module interfaces with the user. The user should provide the data
// and various commands.
//Reference:
//Revision History:
//*****************************************************************************
 
`timescale 1ns/1ps
 
module ddr2_usr_top #
(
// Following parameters are for 72-bit RDIMM design (for ML561 Reference
// board design). Actual values may be different. Actual parameters values
// are passed from design top module ddr2_mig module. Please refer to
// the ddr2_mig module for actual values.
parameter BANK_WIDTH = 2,
parameter CS_BITS = 0,
parameter COL_WIDTH = 10,
parameter DQ_WIDTH = 72,
parameter DQ_PER_DQS = 8,
parameter APPDATA_WIDTH = 144,
parameter ECC_ENABLE = 0,
parameter DQS_WIDTH = 9,
parameter ROW_WIDTH = 14
)
(
input clk0,
input usr_clk, //jb
input clk90,
input rst0,
input [DQ_WIDTH-1:0] rd_data_in_rise,
input [DQ_WIDTH-1:0] rd_data_in_fall,
input [DQS_WIDTH-1:0] phy_calib_rden,
input [DQS_WIDTH-1:0] phy_calib_rden_sel,
output rd_data_valid,
output [APPDATA_WIDTH-1:0] rd_data_fifo_out,
input [2:0] app_af_cmd,
input [30:0] app_af_addr,
input app_af_wren,
input ctrl_af_rden,
output [2:0] af_cmd,
output [30:0] af_addr,
output af_empty,
output app_af_afull,
output [1:0] rd_ecc_error,
input app_wdf_wren,
input [APPDATA_WIDTH-1:0] app_wdf_data,
input [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data,
input wdf_rden,
output app_wdf_afull,
output [(2*DQ_WIDTH)-1:0] wdf_data,
output [((2*DQ_WIDTH)/8)-1:0] wdf_mask_data
);
 
wire [(APPDATA_WIDTH/2)-1:0] i_rd_data_fifo_out_fall;
wire [(APPDATA_WIDTH/2)-1:0] i_rd_data_fifo_out_rise;
 
//***************************************************************************
 
assign rd_data_fifo_out = {i_rd_data_fifo_out_fall,
i_rd_data_fifo_out_rise};
 
// read data de-skew and ECC calculation
ddr2_usr_rd #
(
.DQ_PER_DQS (DQ_PER_DQS),
.ECC_ENABLE (ECC_ENABLE),
.APPDATA_WIDTH (APPDATA_WIDTH),
.DQS_WIDTH (DQS_WIDTH)
)
u_usr_rd
(
.clk0 (clk0),
.rst0 (rst0),
.rd_data_in_rise (rd_data_in_rise),
.rd_data_in_fall (rd_data_in_fall),
.rd_ecc_error (rd_ecc_error),
.ctrl_rden (phy_calib_rden),
.ctrl_rden_sel (phy_calib_rden_sel),
.rd_data_valid (rd_data_valid),
.rd_data_out_rise (i_rd_data_fifo_out_rise),
.rd_data_out_fall (i_rd_data_fifo_out_fall)
);
 
// Command/Addres FIFO
ddr2_usr_addr_fifo #
(
.BANK_WIDTH (BANK_WIDTH),
.COL_WIDTH (COL_WIDTH),
.CS_BITS (CS_BITS),
.ROW_WIDTH (ROW_WIDTH)
)
u_usr_addr_fifo
(
.clk0 (clk0),
.usr_clk (usr_clk), //jb
.rst0 (rst0),
.app_af_cmd (app_af_cmd),
.app_af_addr (app_af_addr),
.app_af_wren (app_af_wren),
.ctrl_af_rden (ctrl_af_rden),
.af_cmd (af_cmd),
.af_addr (af_addr),
.af_empty (af_empty),
.app_af_afull (app_af_afull)
);
 
ddr2_usr_wr #
(
.BANK_WIDTH (BANK_WIDTH),
.COL_WIDTH (COL_WIDTH),
.CS_BITS (CS_BITS),
.DQ_WIDTH (DQ_WIDTH),
.APPDATA_WIDTH (APPDATA_WIDTH),
.ECC_ENABLE (ECC_ENABLE),
.ROW_WIDTH (ROW_WIDTH)
)
u_usr_wr
(
.clk0 (clk0),
.usr_clk (usr_clk), // jb
.clk90 (clk90),
.rst0 (rst0),
.app_wdf_wren (app_wdf_wren),
.app_wdf_data (app_wdf_data),
.app_wdf_mask_data (app_wdf_mask_data),
.wdf_rden (wdf_rden),
.app_wdf_afull (app_wdf_afull),
.wdf_data (wdf_data),
.wdf_mask_data (wdf_mask_data)
);
 
endmodule
/boards/xilinx/ml501/rtl/verilog/xilinx_ddr2/ddr2_usr_rd.v
0,0 → 1,299
//*****************************************************************************
// DISCLAIMER OF LIABILITY
//
// This file contains proprietary and confidential information of
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
// from Xilinx, and may be used, copied and/or disclosed only
// pursuant to the terms of a valid license agreement with Xilinx.
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
// does not warrant that functions included in the Materials will
// meet the requirements of Licensee, or that the operation of the
// Materials will be uninterrupted or error-free, or that defects
// in the Materials will be corrected. Furthermore, Xilinx does
// not warrant or make any representations regarding use, or the
// results of the use, of the Materials in terms of correctness,
// accuracy, reliability or otherwise.
//
// Xilinx products are not designed or intended to be fail-safe,
// or for use in any application requiring fail-safe performance,
// such as life-support or safety devices or systems, Class III
// medical devices, nuclear facilities, applications related to
// the deployment of airbags, or any other applications that could
// lead to death, personal injury or severe property or
// environmental damage (individually and collectively, "critical
// applications"). Customer assumes the sole risk and liability
// of any use of Xilinx products in critical applications,
// subject only to applicable laws and regulations governing
// limitations on product liability.
//
// Copyright 2006, 2007, 2008 Xilinx, Inc.
// All rights reserved.
//
// This disclaimer and copyright notice must be retained as part
// of this file at all times.
//*****************************************************************************
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 3.0
// \ \ Application: MIG
// / / Filename: ddr2_usr_rd.v
// /___/ /\ Date Last Modified: $Date: 2008/12/23 14:26:01 $
// \ \ / \ Date Created: Tue Aug 29 2006
// \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR2
//Purpose:
// The delay between the read data with respect to the command issued is
// calculted in terms of no. of clocks. This data is then stored into the
// FIFOs and then read back and given as the ouput for comparison.
//Reference:
//Revision History:
//*****************************************************************************
 
`timescale 1ns/1ps
 
module ddr2_usr_rd #
(
// Following parameters are for 72-bit RDIMM design (for ML561 Reference
// board design). Actual values may be different. Actual parameters values
// are passed from design top module ddr2_mig module. Please refer to
// the ddr2_mig module for actual values.
parameter DQ_PER_DQS = 8,
parameter DQS_WIDTH = 9,
parameter APPDATA_WIDTH = 144,
parameter ECC_WIDTH = 72,
parameter ECC_ENABLE = 0
)
(
input clk0,
input rst0,
input [(DQS_WIDTH*DQ_PER_DQS)-1:0] rd_data_in_rise,
input [(DQS_WIDTH*DQ_PER_DQS)-1:0] rd_data_in_fall,
input [DQS_WIDTH-1:0] ctrl_rden,
input [DQS_WIDTH-1:0] ctrl_rden_sel,
output reg [1:0] rd_ecc_error,
output rd_data_valid,
output reg [(APPDATA_WIDTH/2)-1:0] rd_data_out_rise,
output reg [(APPDATA_WIDTH/2)-1:0] rd_data_out_fall
);
 
// determine number of FIFO72's to use based on data width
localparam RDF_FIFO_NUM = ((APPDATA_WIDTH/2)+63)/64;
 
reg [DQS_WIDTH-1:0] ctrl_rden_r;
wire [(DQS_WIDTH*DQ_PER_DQS)-1:0] fall_data;
reg [(DQS_WIDTH*DQ_PER_DQS)-1:0] rd_data_in_fall_r;
reg [(DQS_WIDTH*DQ_PER_DQS)-1:0] rd_data_in_rise_r;
wire rden;
reg [DQS_WIDTH-1:0] rden_sel_r
/* synthesis syn_preserve=1 */;
wire [DQS_WIDTH-1:0] rden_sel_mux;
wire [(DQS_WIDTH*DQ_PER_DQS)-1:0] rise_data;
 
// ECC specific signals
wire [((RDF_FIFO_NUM -1) *2)+1:0] db_ecc_error;
reg [(DQS_WIDTH*DQ_PER_DQS)-1:0] fall_data_r;
reg fifo_rden_r0;
reg fifo_rden_r1;
reg fifo_rden_r2;
reg fifo_rden_r3;
reg fifo_rden_r4;
reg fifo_rden_r5;
reg fifo_rden_r6;
wire [(APPDATA_WIDTH/2)-1:0] rd_data_out_fall_temp;
wire [(APPDATA_WIDTH/2)-1:0] rd_data_out_rise_temp;
reg rst_r;
reg [(DQS_WIDTH*DQ_PER_DQS)-1:0] rise_data_r;
wire [((RDF_FIFO_NUM -1) *2)+1:0] sb_ecc_error;
 
 
//***************************************************************************
 
always @(posedge clk0) begin
rden_sel_r <= ctrl_rden_sel;
ctrl_rden_r <= ctrl_rden;
rd_data_in_rise_r <= rd_data_in_rise;
rd_data_in_fall_r <= rd_data_in_fall;
end
 
// Instantiate primitive to allow this flop to be attached to multicycle
// path constraint in UCF. Multicycle path allowed for data from read FIFO.
// This is the same signal as RDEN_SEL_R, but is only used to select data
// (does not affect control signals)
genvar rd_i;
generate
for (rd_i = 0; rd_i < DQS_WIDTH; rd_i = rd_i+1) begin: gen_rden_sel_mux
FDRSE u_ff_rden_sel_mux
(
.Q (rden_sel_mux[rd_i]),
.C (clk0),
.CE (1'b1),
.D (ctrl_rden_sel[rd_i]),
.R (1'b0),
.S (1'b0)
) /* synthesis syn_preserve=1 */;
end
endgenerate
 
// determine correct read data valid signal timing
assign rden = (rden_sel_r[0]) ? ctrl_rden[0] : ctrl_rden_r[0];
 
// assign data based on the skew
genvar data_i;
generate
for(data_i = 0; data_i < DQS_WIDTH; data_i = data_i+1) begin: gen_data
assign rise_data[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1):
(data_i*DQ_PER_DQS)]
= (rden_sel_mux[data_i]) ?
rd_data_in_rise[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1) :
(data_i*DQ_PER_DQS)] :
rd_data_in_rise_r[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1):
(data_i*DQ_PER_DQS)];
assign fall_data[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1):
(data_i*DQ_PER_DQS)]
= (rden_sel_mux[data_i]) ?
rd_data_in_fall[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1):
(data_i*DQ_PER_DQS)] :
rd_data_in_fall_r[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1):
(data_i*DQ_PER_DQS)];
end
endgenerate
 
// Generate RST for FIFO reset AND for read/write enable:
// ECC FIFO always being read from and written to
always @(posedge clk0)
rst_r <= rst0;
 
genvar rdf_i;
generate
if (ECC_ENABLE) begin
always @(posedge clk0) begin
rd_ecc_error[0] <= (|sb_ecc_error) & fifo_rden_r5;
rd_ecc_error[1] <= (|db_ecc_error) & fifo_rden_r5;
rd_data_out_rise <= rd_data_out_rise_temp;
rd_data_out_fall <= rd_data_out_fall_temp;
rise_data_r <= rise_data;
fall_data_r <= fall_data;
end
 
// can use any of the read valids, they're all delayed by same amount
assign rd_data_valid = fifo_rden_r6;
 
// delay read valid to take into account max delay difference btw
// the read enable coming from the different DQS groups
always @(posedge clk0) begin
if (rst0) begin
fifo_rden_r0 <= 1'b0;
fifo_rden_r1 <= 1'b0;
fifo_rden_r2 <= 1'b0;
fifo_rden_r3 <= 1'b0;
fifo_rden_r4 <= 1'b0;
fifo_rden_r5 <= 1'b0;
fifo_rden_r6 <= 1'b0;
end else begin
fifo_rden_r0 <= rden;
fifo_rden_r1 <= fifo_rden_r0;
fifo_rden_r2 <= fifo_rden_r1;
fifo_rden_r3 <= fifo_rden_r2;
fifo_rden_r4 <= fifo_rden_r3;
fifo_rden_r5 <= fifo_rden_r4;
fifo_rden_r6 <= fifo_rden_r5;
end
end
 
for (rdf_i = 0; rdf_i < RDF_FIFO_NUM; rdf_i = rdf_i + 1) begin: gen_rdf
 
FIFO36_72 # // rise fifo
(
.ALMOST_EMPTY_OFFSET (9'h007),
.ALMOST_FULL_OFFSET (9'h00F),
.DO_REG (1), // extra CC output delay
.EN_ECC_WRITE ("FALSE"),
.EN_ECC_READ ("TRUE"),
.EN_SYN ("FALSE"),
.FIRST_WORD_FALL_THROUGH ("FALSE")
)
u_rdf
(
.ALMOSTEMPTY (),
.ALMOSTFULL (),
.DBITERR (db_ecc_error[rdf_i + rdf_i]),
.DO (rd_data_out_rise_temp[(64*(rdf_i+1))-1:
(64 *rdf_i)]),
.DOP (),
.ECCPARITY (),
.EMPTY (),
.FULL (),
.RDCOUNT (),
.RDERR (),
.SBITERR (sb_ecc_error[rdf_i + rdf_i]),
.WRCOUNT (),
.WRERR (),
.DI (rise_data_r[((64*(rdf_i+1)) + (rdf_i*8))-1:
(64 *rdf_i)+(rdf_i*8)]),
.DIP (rise_data_r[(72*(rdf_i+1))-1:
(64*(rdf_i+1))+ (8*rdf_i)]),
.RDCLK (clk0),
.RDEN (~rst_r),
.RST (rst_r),
.WRCLK (clk0),
.WREN (~rst_r)
);
 
FIFO36_72 # // fall_fifo
(
.ALMOST_EMPTY_OFFSET (9'h007),
.ALMOST_FULL_OFFSET (9'h00F),
.DO_REG (1), // extra CC output delay
.EN_ECC_WRITE ("FALSE"),
.EN_ECC_READ ("TRUE"),
.EN_SYN ("FALSE"),
.FIRST_WORD_FALL_THROUGH ("FALSE")
)
u_rdf1
(
.ALMOSTEMPTY (),
.ALMOSTFULL (),
.DBITERR (db_ecc_error[(rdf_i+1) + rdf_i]),
.DO (rd_data_out_fall_temp[(64*(rdf_i+1))-1:
(64 *rdf_i)]),
.DOP (),
.ECCPARITY (),
.EMPTY (),
.FULL (),
.RDCOUNT (),
.RDERR (),
.SBITERR (sb_ecc_error[(rdf_i+1) + rdf_i]),
.WRCOUNT (),
.WRERR (),
.DI (fall_data_r[((64*(rdf_i+1)) + (rdf_i*8))-1:
(64*rdf_i)+(rdf_i*8)]),
.DIP (fall_data_r[(72*(rdf_i+1))-1:
(64*(rdf_i+1))+ (8*rdf_i)]),
.RDCLK (clk0),
.RDEN (~rst_r),
.RST (rst_r), // or can use rst0
.WRCLK (clk0),
.WREN (~rst_r)
);
end
end // if (ECC_ENABLE)
else begin
assign rd_data_valid = fifo_rden_r0;
always @(posedge clk0) begin
rd_data_out_rise <= rise_data;
rd_data_out_fall <= fall_data;
fifo_rden_r0 <= rden;
end
end
endgenerate
 
endmodule
/boards/xilinx/ml501/rtl/verilog/orpsoc_top/orpsoc_top.v
0,0 → 1,1562
//////////////////////////////////////////////////////////////////////
/// ////
/// ORPSoC top for ML501 board ////
/// ////
/// Instantiates modules, depending on ORPSoC defines file ////
/// ////
/// Julius Baxter, julius@opencores.org ////
/// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2009, 2010 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
 
`include "orpsoc-defines.v"
`include "synthesis-defines.v"
module orpsoc_top
(
`ifdef JTAG_DEBUG
tdo_pad_o, tms_pad_i, tck_pad_i, tdi_pad_i,
`endif
`ifdef XILINX_DDR2
ddr2_a, ddr2_ba, ddr2_ras_n, ddr2_cas_n, ddr2_we_n,
ddr2_cs_n, ddr2_odt, ddr2_cke, ddr2_dm,
ddr2_dq, ddr2_dqs, ddr2_dqs_n, ddr2_ck, ddr2_ck_n,
`endif
`ifdef XILINX_SSRAM
sram_clk, sram_clk_fb, sram_flash_addr, sram_flash_data,
sram_cen, sram_flash_oe_n, sram_flash_we_n, sram_bw,
sram_adv_ld_n, sram_mode,
`endif
`ifdef UART0
uart0_srx_pad_i, uart0_stx_pad_o,
uart0_srx_expheader_pad_i, uart0_stx_expheader_pad_o,
`endif
`ifdef SPI0
spi0_sck_o, spi0_mosi_o, spi0_miso_i, spi0_ss_o,
`endif
`ifdef I2C0
i2c0_sda_io, i2c0_scl_io,
`endif
`ifdef I2C1
i2c1_sda_io, i2c1_scl_io,
`endif
`ifdef GPIO0
gpio0_io,
`endif
`ifdef ETH0
eth0_tx_clk, eth0_tx_data, eth0_tx_en, eth0_tx_er,
eth0_rx_clk, eth0_rx_data, eth0_dv, eth0_rx_er,
eth0_col, eth0_crs,
eth0_mdc_pad_o, eth0_md_pad_io,
`ifdef ETH0_PHY_RST
eth0_rst_n_o,
`endif
`endif
sys_clk_in_p,sys_clk_in_n,
 
rst_n_pad_i
 
);
 
`include "orpsoc-params.v"
 
input sys_clk_in_p,sys_clk_in_n;
input rst_n_pad_i;
`ifdef JTAG_DEBUG
output tdo_pad_o;
input tms_pad_i;
input tck_pad_i;
input tdi_pad_i;
`endif
`ifdef XILINX_DDR2
output [12:0] ddr2_a;
output [1:0] ddr2_ba;
output ddr2_ras_n;
output ddr2_cas_n;
output ddr2_we_n;
output [1:0] ddr2_cs_n;
output [1:0] ddr2_odt;
output [1:0] ddr2_cke;
output [7:0] ddr2_dm;
inout [63:0] ddr2_dq;
inout [7:0] ddr2_dqs;
inout [7:0] ddr2_dqs_n;
output [1:0] ddr2_ck;
output [1:0] ddr2_ck_n;
`endif
`ifdef XILINX_SSRAM
// ZBT SSRAM
output sram_clk,
input sram_clk_fb,
output [21:1] sram_flash_addr,
inout [31:0] sram_flash_data,
output sram_cen,
output sram_flash_oe_n,
output sram_flash_we_n,
output [3:0] sram_bw,
output sram_adv_ld_n,
output sram_mode,
`endif
`ifdef UART0
input uart0_srx_pad_i;
output uart0_stx_pad_o;
// Duplicates of the UART signals, this time to the USB debug cable
input uart0_srx_expheader_pad_i;
output uart0_stx_expheader_pad_o;
`endif
`ifdef SPI0
output spi0_sck_o;
output spi0_mosi_o;
output [spi0_ss_width-1:0] spi0_ss_o;
input spi0_miso_i;
`endif
`ifdef I2C0
inout i2c0_sda_io, i2c0_scl_io;
`endif
`ifdef I2C1
inout i2c1_sda_io, i2c1_scl_io;
`endif
`ifdef GPIO0
inout [gpio0_io_width-1:0] gpio0_io;
`endif
`ifdef ETH0
input eth0_tx_clk;
output [3:0] eth0_tx_data;
output eth0_tx_en;
output eth0_tx_er;
input eth0_rx_clk;
input [3:0] eth0_rx_data;
input eth0_dv;
input eth0_rx_er;
input eth0_col;
input eth0_crs;
output eth0_mdc_pad_o;
inout eth0_md_pad_io;
`ifdef ETH0_PHY_RST
output eth0_rst_n_o;
`endif
`endif // `ifdef ETH0
////////////////////////////////////////////////////////////////////////
//
// Clock and reset generation module
//
////////////////////////////////////////////////////////////////////////
 
//
// Wires
//
wire wb_clk, wb_rst;
wire ddr2_if_clk, ddr2_if_rst;
wire clk200;
wire dbg_tck;
 
clkgen clkgen0
(
.sys_clk_in_p (sys_clk_in_p),
.sys_clk_in_n (sys_clk_in_n),
 
.wb_clk_o (wb_clk),
.wb_rst_o (wb_rst),
 
`ifdef JTAG_DEBUG
.tck_pad_i (tck_pad_i),
.dbg_tck_o (dbg_tck),
`endif
`ifdef XILINX_DDR2
.ddr2_if_clk_o (ddr2_if_clk),
.ddr2_if_rst_o (ddr2_if_rst),
.clk200_o (clk200),
`endif
 
// Asynchronous active low reset
.rst_n_pad_i (rst_n_pad_i)
);
 
////////////////////////////////////////////////////////////////////////
//
// Arbiter
//
////////////////////////////////////////////////////////////////////////
// Wire naming convention:
// First: wishbone master or slave (wbm/wbs)
// Second: Which bus it's on instruction or data (i/d)
// Third: Between which module and the arbiter the wires are
// Fourth: Signal name
// Fifth: Direction relative to module (not bus/arbiter!)
// ie. wbm_d_or12_adr_o is address OUT from the or1200
 
// OR1200 instruction bus wires
wire [wb_aw-1:0] wbm_i_or12_adr_o;
wire [wb_dw-1:0] wbm_i_or12_dat_o;
wire [3:0] wbm_i_or12_sel_o;
wire wbm_i_or12_we_o;
wire wbm_i_or12_cyc_o;
wire wbm_i_or12_stb_o;
wire [2:0] wbm_i_or12_cti_o;
wire [1:0] wbm_i_or12_bte_o;
wire [wb_dw-1:0] wbm_i_or12_dat_i;
wire wbm_i_or12_ack_i;
wire wbm_i_or12_err_i;
wire wbm_i_or12_rty_i;
 
// OR1200 data bus wires
wire [wb_aw-1:0] wbm_d_or12_adr_o;
wire [wb_dw-1:0] wbm_d_or12_dat_o;
wire [3:0] wbm_d_or12_sel_o;
wire wbm_d_or12_we_o;
wire wbm_d_or12_cyc_o;
wire wbm_d_or12_stb_o;
wire [2:0] wbm_d_or12_cti_o;
wire [1:0] wbm_d_or12_bte_o;
wire [wb_dw-1:0] wbm_d_or12_dat_i;
wire wbm_d_or12_ack_i;
wire wbm_d_or12_err_i;
wire wbm_d_or12_rty_i;
 
// Debug interface bus wires
wire [wb_aw-1:0] wbm_d_dbg_adr_o;
wire [wb_dw-1:0] wbm_d_dbg_dat_o;
wire [3:0] wbm_d_dbg_sel_o;
wire wbm_d_dbg_we_o;
wire wbm_d_dbg_cyc_o;
wire wbm_d_dbg_stb_o;
wire [2:0] wbm_d_dbg_cti_o;
wire [1:0] wbm_d_dbg_bte_o;
wire [wb_dw-1:0] wbm_d_dbg_dat_i;
wire wbm_d_dbg_ack_i;
wire wbm_d_dbg_err_i;
wire wbm_d_dbg_rty_i;
 
// Byte bus bridge master signals
wire [wb_aw-1:0] wbm_b_d_adr_o;
wire [wb_dw-1:0] wbm_b_d_dat_o;
wire [3:0] wbm_b_d_sel_o;
wire wbm_b_d_we_o;
wire wbm_b_d_cyc_o;
wire wbm_b_d_stb_o;
wire [2:0] wbm_b_d_cti_o;
wire [1:0] wbm_b_d_bte_o;
wire [wb_dw-1:0] wbm_b_d_dat_i;
wire wbm_b_d_ack_i;
wire wbm_b_d_err_i;
wire wbm_b_d_rty_i;
 
// Instruction bus slave wires //
// rom0 instruction bus wires
wire [31:0] wbs_i_rom0_adr_i;
wire [wbs_i_rom0_data_width-1:0] wbs_i_rom0_dat_i;
wire [3:0] wbs_i_rom0_sel_i;
wire wbs_i_rom0_we_i;
wire wbs_i_rom0_cyc_i;
wire wbs_i_rom0_stb_i;
wire [2:0] wbs_i_rom0_cti_i;
wire [1:0] wbs_i_rom0_bte_i;
wire [wbs_i_rom0_data_width-1:0] wbs_i_rom0_dat_o;
wire wbs_i_rom0_ack_o;
wire wbs_i_rom0_err_o;
wire wbs_i_rom0_rty_o;
 
// mc0 instruction bus wires
wire [31:0] wbs_i_mc0_adr_i;
wire [wbs_i_mc0_data_width-1:0] wbs_i_mc0_dat_i;
wire [3:0] wbs_i_mc0_sel_i;
wire wbs_i_mc0_we_i;
wire wbs_i_mc0_cyc_i;
wire wbs_i_mc0_stb_i;
wire [2:0] wbs_i_mc0_cti_i;
wire [1:0] wbs_i_mc0_bte_i;
wire [wbs_i_mc0_data_width-1:0] wbs_i_mc0_dat_o;
wire wbs_i_mc0_ack_o;
wire wbs_i_mc0_err_o;
wire wbs_i_mc0_rty_o;
// Data bus slave wires //
// mc0 data bus wires
wire [31:0] wbs_d_mc0_adr_i;
wire [wbs_d_mc0_data_width-1:0] wbs_d_mc0_dat_i;
wire [3:0] wbs_d_mc0_sel_i;
wire wbs_d_mc0_we_i;
wire wbs_d_mc0_cyc_i;
wire wbs_d_mc0_stb_i;
wire [2:0] wbs_d_mc0_cti_i;
wire [1:0] wbs_d_mc0_bte_i;
wire [wbs_d_mc0_data_width-1:0] wbs_d_mc0_dat_o;
wire wbs_d_mc0_ack_o;
wire wbs_d_mc0_err_o;
wire wbs_d_mc0_rty_o;
// i2c0 wires
wire [31:0] wbs_d_i2c0_adr_i;
wire [wbs_d_i2c0_data_width-1:0] wbs_d_i2c0_dat_i;
wire [3:0] wbs_d_i2c0_sel_i;
wire wbs_d_i2c0_we_i;
wire wbs_d_i2c0_cyc_i;
wire wbs_d_i2c0_stb_i;
wire [2:0] wbs_d_i2c0_cti_i;
wire [1:0] wbs_d_i2c0_bte_i;
wire [wbs_d_i2c0_data_width-1:0] wbs_d_i2c0_dat_o;
wire wbs_d_i2c0_ack_o;
wire wbs_d_i2c0_err_o;
wire wbs_d_i2c0_rty_o;
 
// i2c1 wires
wire [31:0] wbs_d_i2c1_adr_i;
wire [wbs_d_i2c1_data_width-1:0] wbs_d_i2c1_dat_i;
wire [3:0] wbs_d_i2c1_sel_i;
wire wbs_d_i2c1_we_i;
wire wbs_d_i2c1_cyc_i;
wire wbs_d_i2c1_stb_i;
wire [2:0] wbs_d_i2c1_cti_i;
wire [1:0] wbs_d_i2c1_bte_i;
wire [wbs_d_i2c1_data_width-1:0] wbs_d_i2c1_dat_o;
wire wbs_d_i2c1_ack_o;
wire wbs_d_i2c1_err_o;
wire wbs_d_i2c1_rty_o;
// spi0 wires
wire [31:0] wbs_d_spi0_adr_i;
wire [wbs_d_spi0_data_width-1:0] wbs_d_spi0_dat_i;
wire [3:0] wbs_d_spi0_sel_i;
wire wbs_d_spi0_we_i;
wire wbs_d_spi0_cyc_i;
wire wbs_d_spi0_stb_i;
wire [2:0] wbs_d_spi0_cti_i;
wire [1:0] wbs_d_spi0_bte_i;
wire [wbs_d_spi0_data_width-1:0] wbs_d_spi0_dat_o;
wire wbs_d_spi0_ack_o;
wire wbs_d_spi0_err_o;
wire wbs_d_spi0_rty_o;
 
// uart0 wires
wire [31:0] wbs_d_uart0_adr_i;
wire [wbs_d_uart0_data_width-1:0] wbs_d_uart0_dat_i;
wire [3:0] wbs_d_uart0_sel_i;
wire wbs_d_uart0_we_i;
wire wbs_d_uart0_cyc_i;
wire wbs_d_uart0_stb_i;
wire [2:0] wbs_d_uart0_cti_i;
wire [1:0] wbs_d_uart0_bte_i;
wire [wbs_d_uart0_data_width-1:0] wbs_d_uart0_dat_o;
wire wbs_d_uart0_ack_o;
wire wbs_d_uart0_err_o;
wire wbs_d_uart0_rty_o;
// gpio0 wires
wire [31:0] wbs_d_gpio0_adr_i;
wire [wbs_d_gpio0_data_width-1:0] wbs_d_gpio0_dat_i;
wire [3:0] wbs_d_gpio0_sel_i;
wire wbs_d_gpio0_we_i;
wire wbs_d_gpio0_cyc_i;
wire wbs_d_gpio0_stb_i;
wire [2:0] wbs_d_gpio0_cti_i;
wire [1:0] wbs_d_gpio0_bte_i;
wire [wbs_d_gpio0_data_width-1:0] wbs_d_gpio0_dat_o;
wire wbs_d_gpio0_ack_o;
wire wbs_d_gpio0_err_o;
wire wbs_d_gpio0_rty_o;
 
// eth0 slave wires
wire [31:0] wbs_d_eth0_adr_i;
wire [wbs_d_eth0_data_width-1:0] wbs_d_eth0_dat_i;
wire [3:0] wbs_d_eth0_sel_i;
wire wbs_d_eth0_we_i;
wire wbs_d_eth0_cyc_i;
wire wbs_d_eth0_stb_i;
wire [2:0] wbs_d_eth0_cti_i;
wire [1:0] wbs_d_eth0_bte_i;
wire [wbs_d_eth0_data_width-1:0] wbs_d_eth0_dat_o;
wire wbs_d_eth0_ack_o;
wire wbs_d_eth0_err_o;
wire wbs_d_eth0_rty_o;
 
// eth0 master wires
wire [wbm_eth0_addr_width-1:0] wbm_eth0_adr_o;
wire [wbm_eth0_data_width-1:0] wbm_eth0_dat_o;
wire [3:0] wbm_eth0_sel_o;
wire wbm_eth0_we_o;
wire wbm_eth0_cyc_o;
wire wbm_eth0_stb_o;
wire [2:0] wbm_eth0_cti_o;
wire [1:0] wbm_eth0_bte_o;
wire [wbm_eth0_data_width-1:0] wbm_eth0_dat_i;
wire wbm_eth0_ack_i;
wire wbm_eth0_err_i;
wire wbm_eth0_rty_i;
 
 
 
//
// Wishbone instruction bus arbiter
//
arbiter_ibus arbiter_ibus0
(
// Instruction Bus Master
// Inputs to arbiter from master
.wbm_adr_o (wbm_i_or12_adr_o),
.wbm_dat_o (wbm_i_or12_dat_o),
.wbm_sel_o (wbm_i_or12_sel_o),
.wbm_we_o (wbm_i_or12_we_o),
.wbm_cyc_o (wbm_i_or12_cyc_o),
.wbm_stb_o (wbm_i_or12_stb_o),
.wbm_cti_o (wbm_i_or12_cti_o),
.wbm_bte_o (wbm_i_or12_bte_o),
// Outputs to master from arbiter
.wbm_dat_i (wbm_i_or12_dat_i),
.wbm_ack_i (wbm_i_or12_ack_i),
.wbm_err_i (wbm_i_or12_err_i),
.wbm_rty_i (wbm_i_or12_rty_i),
// Slave 0
// Inputs to slave from arbiter
.wbs0_adr_i (wbs_i_rom0_adr_i),
.wbs0_dat_i (wbs_i_rom0_dat_i),
.wbs0_sel_i (wbs_i_rom0_sel_i),
.wbs0_we_i (wbs_i_rom0_we_i),
.wbs0_cyc_i (wbs_i_rom0_cyc_i),
.wbs0_stb_i (wbs_i_rom0_stb_i),
.wbs0_cti_i (wbs_i_rom0_cti_i),
.wbs0_bte_i (wbs_i_rom0_bte_i),
// Outputs from slave to arbiter
.wbs0_dat_o (wbs_i_rom0_dat_o),
.wbs0_ack_o (wbs_i_rom0_ack_o),
.wbs0_err_o (wbs_i_rom0_err_o),
.wbs0_rty_o (wbs_i_rom0_rty_o),
 
// Slave 1
// Inputs to slave from arbiter
.wbs1_adr_i (wbs_i_mc0_adr_i),
.wbs1_dat_i (wbs_i_mc0_dat_i),
.wbs1_sel_i (wbs_i_mc0_sel_i),
.wbs1_we_i (wbs_i_mc0_we_i),
.wbs1_cyc_i (wbs_i_mc0_cyc_i),
.wbs1_stb_i (wbs_i_mc0_stb_i),
.wbs1_cti_i (wbs_i_mc0_cti_i),
.wbs1_bte_i (wbs_i_mc0_bte_i),
// Outputs from slave to arbiter
.wbs1_dat_o (wbs_i_mc0_dat_o),
.wbs1_ack_o (wbs_i_mc0_ack_o),
.wbs1_err_o (wbs_i_mc0_err_o),
.wbs1_rty_o (wbs_i_mc0_rty_o),
 
// Clock, reset inputs
.wb_clk (wb_clk),
.wb_rst (wb_rst));
 
defparam arbiter_ibus0.wb_addr_match_width = ibus_arb_addr_match_width;
 
defparam arbiter_ibus0.slave0_adr = ibus_arb_slave0_adr; // FLASH ROM
defparam arbiter_ibus0.slave1_adr = ibus_arb_slave1_adr; // Main memory
 
//
// Wishbone data bus arbiter
//
arbiter_dbus arbiter_dbus0
(
// Master 0
// Inputs to arbiter from master
.wbm0_adr_o (wbm_d_or12_adr_o),
.wbm0_dat_o (wbm_d_or12_dat_o),
.wbm0_sel_o (wbm_d_or12_sel_o),
.wbm0_we_o (wbm_d_or12_we_o),
.wbm0_cyc_o (wbm_d_or12_cyc_o),
.wbm0_stb_o (wbm_d_or12_stb_o),
.wbm0_cti_o (wbm_d_or12_cti_o),
.wbm0_bte_o (wbm_d_or12_bte_o),
// Outputs to master from arbiter
.wbm0_dat_i (wbm_d_or12_dat_i),
.wbm0_ack_i (wbm_d_or12_ack_i),
.wbm0_err_i (wbm_d_or12_err_i),
.wbm0_rty_i (wbm_d_or12_rty_i),
 
// Master 0
// Inputs to arbiter from master
.wbm1_adr_o (wbm_d_dbg_adr_o),
.wbm1_dat_o (wbm_d_dbg_dat_o),
.wbm1_we_o (wbm_d_dbg_we_o),
.wbm1_cyc_o (wbm_d_dbg_cyc_o),
.wbm1_sel_o (wbm_d_dbg_sel_o),
.wbm1_stb_o (wbm_d_dbg_stb_o),
.wbm1_cti_o (wbm_d_dbg_cti_o),
.wbm1_bte_o (wbm_d_dbg_bte_o),
// Outputs to master from arbiter
.wbm1_dat_i (wbm_d_dbg_dat_i),
.wbm1_ack_i (wbm_d_dbg_ack_i),
.wbm1_err_i (wbm_d_dbg_err_i),
.wbm1_rty_i (wbm_d_dbg_rty_i),
 
// Slaves
.wbs0_adr_i (wbs_d_mc0_adr_i),
.wbs0_dat_i (wbs_d_mc0_dat_i),
.wbs0_sel_i (wbs_d_mc0_sel_i),
.wbs0_we_i (wbs_d_mc0_we_i),
.wbs0_cyc_i (wbs_d_mc0_cyc_i),
.wbs0_stb_i (wbs_d_mc0_stb_i),
.wbs0_cti_i (wbs_d_mc0_cti_i),
.wbs0_bte_i (wbs_d_mc0_bte_i),
.wbs0_dat_o (wbs_d_mc0_dat_o),
.wbs0_ack_o (wbs_d_mc0_ack_o),
.wbs0_err_o (wbs_d_mc0_err_o),
.wbs0_rty_o (wbs_d_mc0_rty_o),
 
.wbs1_adr_i (wbs_d_eth0_adr_i),
.wbs1_dat_i (wbs_d_eth0_dat_i),
.wbs1_sel_i (wbs_d_eth0_sel_i),
.wbs1_we_i (wbs_d_eth0_we_i),
.wbs1_cyc_i (wbs_d_eth0_cyc_i),
.wbs1_stb_i (wbs_d_eth0_stb_i),
.wbs1_cti_i (wbs_d_eth0_cti_i),
.wbs1_bte_i (wbs_d_eth0_bte_i),
.wbs1_dat_o (wbs_d_eth0_dat_o),
.wbs1_ack_o (wbs_d_eth0_ack_o),
.wbs1_err_o (wbs_d_eth0_err_o),
.wbs1_rty_o (wbs_d_eth0_rty_o),
.wbs2_adr_i (wbm_b_d_adr_o),
.wbs2_dat_i (wbm_b_d_dat_o),
.wbs2_sel_i (wbm_b_d_sel_o),
.wbs2_we_i (wbm_b_d_we_o),
.wbs2_cyc_i (wbm_b_d_cyc_o),
.wbs2_stb_i (wbm_b_d_stb_o),
.wbs2_cti_i (wbm_b_d_cti_o),
.wbs2_bte_i (wbm_b_d_bte_o),
.wbs2_dat_o (wbm_b_d_dat_i),
.wbs2_ack_o (wbm_b_d_ack_i),
.wbs2_err_o (wbm_b_d_err_i),
.wbs2_rty_o (wbm_b_d_rty_i),
 
// Clock, reset inputs
.wb_clk (wb_clk),
.wb_rst (wb_rst));
 
// These settings are from top level params file
defparam arbiter_dbus0.wb_addr_match_width = dbus_arb_wb_addr_match_width;
defparam arbiter_dbus0.wb_num_slaves = dbus_arb_wb_num_slaves;
defparam arbiter_dbus0.slave0_adr = dbus_arb_slave0_adr;
defparam arbiter_dbus0.slave1_adr = dbus_arb_slave1_adr;
 
//
// Wishbone byte-wide bus arbiter
//
arbiter_bytebus arbiter_bytebus0
(
 
// Master 0
// Inputs to arbiter from master
.wbm0_adr_o (wbm_b_d_adr_o),
.wbm0_dat_o (wbm_b_d_dat_o),
.wbm0_sel_o (wbm_b_d_sel_o),
.wbm0_we_o (wbm_b_d_we_o),
.wbm0_cyc_o (wbm_b_d_cyc_o),
.wbm0_stb_o (wbm_b_d_stb_o),
.wbm0_cti_o (wbm_b_d_cti_o),
.wbm0_bte_o (wbm_b_d_bte_o),
// Outputs to master from arbiter
.wbm0_dat_i (wbm_b_d_dat_i),
.wbm0_ack_i (wbm_b_d_ack_i),
.wbm0_err_i (wbm_b_d_err_i),
.wbm0_rty_i (wbm_b_d_rty_i),
 
// Byte bus slaves
.wbs0_adr_i (wbs_d_uart0_adr_i),
.wbs0_dat_i (wbs_d_uart0_dat_i),
.wbs0_we_i (wbs_d_uart0_we_i),
.wbs0_cyc_i (wbs_d_uart0_cyc_i),
.wbs0_stb_i (wbs_d_uart0_stb_i),
.wbs0_cti_i (wbs_d_uart0_cti_i),
.wbs0_bte_i (wbs_d_uart0_bte_i),
.wbs0_dat_o (wbs_d_uart0_dat_o),
.wbs0_ack_o (wbs_d_uart0_ack_o),
.wbs0_err_o (wbs_d_uart0_err_o),
.wbs0_rty_o (wbs_d_uart0_rty_o),
 
.wbs1_adr_i (wbs_d_gpio0_adr_i),
.wbs1_dat_i (wbs_d_gpio0_dat_i),
.wbs1_we_i (wbs_d_gpio0_we_i),
.wbs1_cyc_i (wbs_d_gpio0_cyc_i),
.wbs1_stb_i (wbs_d_gpio0_stb_i),
.wbs1_cti_i (wbs_d_gpio0_cti_i),
.wbs1_bte_i (wbs_d_gpio0_bte_i),
.wbs1_dat_o (wbs_d_gpio0_dat_o),
.wbs1_ack_o (wbs_d_gpio0_ack_o),
.wbs1_err_o (wbs_d_gpio0_err_o),
.wbs1_rty_o (wbs_d_gpio0_rty_o),
 
.wbs2_adr_i (wbs_d_i2c0_adr_i),
.wbs2_dat_i (wbs_d_i2c0_dat_i),
.wbs2_we_i (wbs_d_i2c0_we_i),
.wbs2_cyc_i (wbs_d_i2c0_cyc_i),
.wbs2_stb_i (wbs_d_i2c0_stb_i),
.wbs2_cti_i (wbs_d_i2c0_cti_i),
.wbs2_bte_i (wbs_d_i2c0_bte_i),
.wbs2_dat_o (wbs_d_i2c0_dat_o),
.wbs2_ack_o (wbs_d_i2c0_ack_o),
.wbs2_err_o (wbs_d_i2c0_err_o),
.wbs2_rty_o (wbs_d_i2c0_rty_o),
 
.wbs3_adr_i (wbs_d_i2c1_adr_i),
.wbs3_dat_i (wbs_d_i2c1_dat_i),
.wbs3_we_i (wbs_d_i2c1_we_i),
.wbs3_cyc_i (wbs_d_i2c1_cyc_i),
.wbs3_stb_i (wbs_d_i2c1_stb_i),
.wbs3_cti_i (wbs_d_i2c1_cti_i),
.wbs3_bte_i (wbs_d_i2c1_bte_i),
.wbs3_dat_o (wbs_d_i2c1_dat_o),
.wbs3_ack_o (wbs_d_i2c1_ack_o),
.wbs3_err_o (wbs_d_i2c1_err_o),
.wbs3_rty_o (wbs_d_i2c1_rty_o),
 
.wbs4_adr_i (wbs_d_spi0_adr_i),
.wbs4_dat_i (wbs_d_spi0_dat_i),
.wbs4_we_i (wbs_d_spi0_we_i),
.wbs4_cyc_i (wbs_d_spi0_cyc_i),
.wbs4_stb_i (wbs_d_spi0_stb_i),
.wbs4_cti_i (wbs_d_spi0_cti_i),
.wbs4_bte_i (wbs_d_spi0_bte_i),
.wbs4_dat_o (wbs_d_spi0_dat_o),
.wbs4_ack_o (wbs_d_spi0_ack_o),
.wbs4_err_o (wbs_d_spi0_err_o),
.wbs4_rty_o (wbs_d_spi0_rty_o),
 
// Clock, reset inputs
.wb_clk (wb_clk),
.wb_rst (wb_rst));
 
defparam arbiter_bytebus0.wb_addr_match_width = bbus_arb_wb_addr_match_width;
defparam arbiter_bytebus0.wb_num_slaves = bbus_arb_wb_num_slaves;
 
defparam arbiter_bytebus0.slave0_adr = bbus_arb_slave0_adr;
defparam arbiter_bytebus0.slave1_adr = bbus_arb_slave1_adr;
defparam arbiter_bytebus0.slave2_adr = bbus_arb_slave2_adr;
defparam arbiter_bytebus0.slave3_adr = bbus_arb_slave3_adr;
defparam arbiter_bytebus0.slave4_adr = bbus_arb_slave4_adr;
 
 
`ifdef JTAG_DEBUG
////////////////////////////////////////////////////////////////////////
//
// JTAG TAP
//
////////////////////////////////////////////////////////////////////////
 
//
// Wires
//
wire dbg_if_select;
wire dbg_if_tdo;
wire jtag_tap_tdo;
wire jtag_tap_shift_dr, jtag_tap_pause_dr,
jtag_tap_upate_dr, jtag_tap_capture_dr;
//
// Instantiation
//
 
jtag_tap jtag_tap0
(
// Ports to pads
.tdo_pad_o (tdo_pad_o),
.tms_pad_i (tms_pad_i),
.tck_pad_i (dbg_tck),
.trst_pad_i (async_rst),
.tdi_pad_i (tdi_pad_i),
.tdo_padoe_o (tdo_padoe_o),
.tdo_o (jtag_tap_tdo),
 
.shift_dr_o (jtag_tap_shift_dr),
.pause_dr_o (jtag_tap_pause_dr),
.update_dr_o (jtag_tap_update_dr),
.capture_dr_o (jtag_tap_capture_dr),
.extest_select_o (),
.sample_preload_select_o (),
.mbist_select_o (),
.debug_select_o (dbg_if_select),
 
.bs_chain_tdi_i (1'b0),
.mbist_tdi_i (1'b0),
.debug_tdi_i (dbg_if_tdo)
);
////////////////////////////////////////////////////////////////////////
`endif // `ifdef JTAG_DEBUG
 
////////////////////////////////////////////////////////////////////////
//
// OpenRISC processor
//
////////////////////////////////////////////////////////////////////////
 
//
// Wires
//
wire [30:0] or1200_pic_ints;
 
wire [31:0] or1200_dbg_dat_i;
wire [31:0] or1200_dbg_adr_i;
wire or1200_dbg_we_i;
wire or1200_dbg_stb_i;
wire or1200_dbg_ack_o;
wire [31:0] or1200_dbg_dat_o;
wire or1200_dbg_stall_i;
wire or1200_dbg_ewt_i;
wire [3:0] or1200_dbg_lss_o;
wire [1:0] or1200_dbg_is_o;
wire [10:0] or1200_dbg_wp_o;
wire or1200_dbg_bp_o;
wire or1200_dbg_rst;
wire or1200_clk, or1200_rst;
wire sig_tick;
//
// Assigns
//
assign or1200_clk = wb_clk;
assign or1200_rst = wb_rst | or1200_dbg_rst;
 
//
// Instantiation
//
or1200_top or1200_top0
(
// Instruction bus, clocks, reset
.iwb_clk_i (wb_clk),
.iwb_rst_i (wb_rst),
.iwb_ack_i (wbm_i_or12_ack_i),
.iwb_err_i (wbm_i_or12_err_i),
.iwb_rty_i (wbm_i_or12_rty_i),
.iwb_dat_i (wbm_i_or12_dat_i),
.iwb_cyc_o (wbm_i_or12_cyc_o),
.iwb_adr_o (wbm_i_or12_adr_o),
.iwb_stb_o (wbm_i_or12_stb_o),
.iwb_we_o (wbm_i_or12_we_o),
.iwb_sel_o (wbm_i_or12_sel_o),
.iwb_dat_o (wbm_i_or12_dat_o),
.iwb_cti_o (wbm_i_or12_cti_o),
.iwb_bte_o (wbm_i_or12_bte_o),
// Data bus, clocks, reset
.dwb_clk_i (wb_clk),
.dwb_rst_i (wb_rst),
.dwb_ack_i (wbm_d_or12_ack_i),
.dwb_err_i (wbm_d_or12_err_i),
.dwb_rty_i (wbm_d_or12_rty_i),
.dwb_dat_i (wbm_d_or12_dat_i),
 
.dwb_cyc_o (wbm_d_or12_cyc_o),
.dwb_adr_o (wbm_d_or12_adr_o),
.dwb_stb_o (wbm_d_or12_stb_o),
.dwb_we_o (wbm_d_or12_we_o),
.dwb_sel_o (wbm_d_or12_sel_o),
.dwb_dat_o (wbm_d_or12_dat_o),
.dwb_cti_o (wbm_d_or12_cti_o),
.dwb_bte_o (wbm_d_or12_bte_o),
// Debug interface ports
.dbg_stall_i (or1200_dbg_stall_i),
//.dbg_ewt_i (or1200_dbg_ewt_i),
.dbg_ewt_i (1'b0),
.dbg_lss_o (or1200_dbg_lss_o),
.dbg_is_o (or1200_dbg_is_o),
.dbg_wp_o (or1200_dbg_wp_o),
.dbg_bp_o (or1200_dbg_bp_o),
 
.dbg_adr_i (or1200_dbg_adr_i),
.dbg_we_i (or1200_dbg_we_i ),
.dbg_stb_i (or1200_dbg_stb_i),
.dbg_dat_i (or1200_dbg_dat_i),
.dbg_dat_o (or1200_dbg_dat_o),
.dbg_ack_o (or1200_dbg_ack_o),
.pm_clksd_o (),
.pm_dc_gate_o (),
.pm_ic_gate_o (),
.pm_dmmu_gate_o (),
.pm_immu_gate_o (),
.pm_tt_gate_o (),
.pm_cpu_gate_o (),
.pm_wakeup_o (),
.pm_lvolt_o (),
 
// Core clocks, resets
.clk_i (or1200_clk),
.rst_i (or1200_rst),
.clmode_i (2'b00),
// Interrupts
.pic_ints_i (or1200_pic_ints),
.sig_tick(sig_tick),
/*
.mbist_so_o (),
.mbist_si_i (0),
.mbist_ctrl_i (0),
*/
 
.pm_cpustall_i (1'b0)
 
);
////////////////////////////////////////////////////////////////////////
 
 
`ifdef JTAG_DEBUG
////////////////////////////////////////////////////////////////////////
//
// OR1200 Debug Interface
//
////////////////////////////////////////////////////////////////////////
dbg_if dbg_if0
(
// OR1200 interface
.cpu0_clk_i (or1200_clk),
.cpu0_rst_o (or1200_dbg_rst),
.cpu0_addr_o (or1200_dbg_adr_i),
.cpu0_data_o (or1200_dbg_dat_i),
.cpu0_stb_o (or1200_dbg_stb_i),
.cpu0_we_o (or1200_dbg_we_i),
.cpu0_data_i (or1200_dbg_dat_o),
.cpu0_ack_i (or1200_dbg_ack_o),
 
 
.cpu0_stall_o (or1200_dbg_stall_i),
.cpu0_bp_i (or1200_dbg_bp_o),
// TAP interface
.tck_i (dbg_tck),
.tdi_i (jtag_tap_tdo),
.tdo_o (dbg_if_tdo),
.rst_i (wb_rst),
.shift_dr_i (jtag_tap_shift_dr),
.pause_dr_i (jtag_tap_pause_dr),
.update_dr_i (jtag_tap_update_dr),
.debug_select_i (dbg_if_select),
 
// Wishbone debug master
.wb_clk_i (wb_clk),
.wb_dat_i (wbm_d_dbg_dat_i),
.wb_ack_i (wbm_d_dbg_ack_i),
.wb_err_i (wbm_d_dbg_err_i),
.wb_adr_o (wbm_d_dbg_adr_o),
.wb_dat_o (wbm_d_dbg_dat_o),
.wb_cyc_o (wbm_d_dbg_cyc_o),
.wb_stb_o (wbm_d_dbg_stb_o),
.wb_sel_o (wbm_d_dbg_sel_o),
.wb_we_o (wbm_d_dbg_we_o ),
.wb_cti_o (wbm_d_dbg_cti_o),
.wb_cab_o (/* UNUSED */),
.wb_bte_o (wbm_d_dbg_bte_o)
);
////////////////////////////////////////////////////////////////////////
`else // !`ifdef JTAG_DEBUG
 
assign wbm_d_dbg_adr_o = 0;
assign wbm_d_dbg_dat_o = 0;
assign wbm_d_dbg_cyc_o = 0;
assign wbm_d_dbg_stb_o = 0;
assign wbm_d_dbg_sel_o = 0;
assign wbm_d_dbg_we_o = 0;
assign wbm_d_dbg_cti_o = 0;
assign wbm_d_dbg_bte_o = 0;
 
assign or1200_dbg_adr_i = 0;
assign or1200_dbg_dat_i = 0;
assign or1200_dbg_stb_i = 0;
assign or1200_dbg_we_i = 0;
assign or1200_dbg_stall_i = 0;
////////////////////////////////////////////////////////////////////////
`endif // !`ifdef JTAG_DEBUG
`ifdef XILINX_DDR2
////////////////////////////////////////////////////////////////////////
//
// Xilinx MIG DDR2 controller, Wishbone interface
//
////////////////////////////////////////////////////////////////////////
xilinx_ddr2 xilinx_ddr2_0
(
.wbm0_adr_i (wbm_eth0_adr_o),
.wbm0_bte_i (wbm_eth0_bte_o),
.wbm0_cti_i (wbm_eth0_cti_o),
.wbm0_cyc_i (wbm_eth0_cyc_o),
.wbm0_dat_i (wbm_eth0_dat_o),
.wbm0_sel_i (wbm_eth0_sel_o),
.wbm0_stb_i (wbm_eth0_stb_o),
.wbm0_we_i (wbm_eth0_we_o),
.wbm0_ack_o (wbm_eth0_ack_i),
.wbm0_err_o (wbm_eth0_err_i),
.wbm0_rty_o (wbm_eth0_rty_i),
.wbm0_dat_o (wbm_eth0_dat_i),
.wbm1_adr_i (wbs_d_mc0_adr_i),
.wbm1_bte_i (wbs_d_mc0_bte_i),
.wbm1_cti_i (wbs_d_mc0_cti_i),
.wbm1_cyc_i (wbs_d_mc0_cyc_i),
.wbm1_dat_i (wbs_d_mc0_dat_i),
.wbm1_sel_i (wbs_d_mc0_sel_i),
.wbm1_stb_i (wbs_d_mc0_stb_i),
.wbm1_we_i (wbs_d_mc0_we_i),
.wbm1_ack_o (wbs_d_mc0_ack_o),
.wbm1_err_o (wbs_d_mc0_err_o),
.wbm1_rty_o (wbs_d_mc0_rty_o),
.wbm1_dat_o (wbs_d_mc0_dat_o),
.wbm2_adr_i (wbs_i_mc0_adr_i),
.wbm2_bte_i (wbs_i_mc0_bte_i),
.wbm2_cti_i (wbs_i_mc0_cti_i),
.wbm2_cyc_i (wbs_i_mc0_cyc_i),
.wbm2_dat_i (wbs_i_mc0_dat_i),
.wbm2_sel_i (wbs_i_mc0_sel_i),
.wbm2_stb_i (wbs_i_mc0_stb_i),
.wbm2_we_i (wbs_i_mc0_we_i),
.wbm2_ack_o (wbs_i_mc0_ack_o),
.wbm2_err_o (wbs_i_mc0_err_o),
.wbm2_rty_o (wbs_i_mc0_rty_o),
.wbm2_dat_o (wbs_i_mc0_dat_o),
.wb_clk (wb_clk),
.wb_rst (wb_rst),
.ddr2_a (ddr2_a[12:0]),
.ddr2_ba (ddr2_ba[1:0]),
.ddr2_ras_n (ddr2_ras_n),
.ddr2_cas_n (ddr2_cas_n),
.ddr2_we_n (ddr2_we_n),
.ddr2_cs_n (ddr2_cs_n),
.ddr2_odt (ddr2_odt),
.ddr2_cke (ddr2_cke),
.ddr2_dm (ddr2_dm[7:0]),
.ddr2_ck (ddr2_ck[1:0]),
.ddr2_ck_n (ddr2_ck_n[1:0]),
.ddr2_dq (ddr2_dq[63:0]),
.ddr2_dqs (ddr2_dqs[7:0]),
.ddr2_dqs_n (ddr2_dqs_n[7:0]),
.ddr2_if_clk (ddr2_if_clk),
.clk200 (clk200),
.ddr2_if_rst (ddr2_if_rst)
);
`endif
 
 
////////////////////////////////////////////////////////////////////////
//
// ROM
//
////////////////////////////////////////////////////////////////////////
rom rom0
(
.wb_dat_o (wbs_i_rom0_dat_o),
.wb_ack_o (wbs_i_rom0_ack_o),
.wb_adr_i (wbs_i_rom0_adr_i[(wbs_i_rom0_addr_width+2)-1:2]),
.wb_stb_i (wbs_i_rom0_stb_i),
.wb_cyc_i (wbs_i_rom0_cyc_i),
.wb_cti_i (wbs_i_rom0_cti_i),
.wb_bte_i (wbs_i_rom0_bte_i),
.wb_clk (wb_clk),
.wb_rst (wb_rst));
 
defparam rom0.addr_width = wbs_i_rom0_addr_width;
 
assign wbs_i_rom0_err_o = 0;
assign wbs_i_rom0_rty_o = 0;
////////////////////////////////////////////////////////////////////////
 
`ifdef RAM_WB
////////////////////////////////////////////////////////////////////////
//
// Generic RAM
//
////////////////////////////////////////////////////////////////////////
 
ram_wb ram_wb0
(
// Wishbone slave interface 0
.wbm0_dat_i (wbs_i_mc0_dat_i),
.wbm0_adr_i (wbs_i_mc0_adr_i),
.wbm0_sel_i (wbs_i_mc0_sel_i),
.wbm0_cti_i (wbs_i_mc0_cti_i),
.wbm0_bte_i (wbs_i_mc0_bte_i),
.wbm0_we_i (wbs_i_mc0_we_i ),
.wbm0_cyc_i (wbs_i_mc0_cyc_i),
.wbm0_stb_i (wbs_i_mc0_stb_i),
.wbm0_dat_o (wbs_i_mc0_dat_o),
.wbm0_ack_o (wbs_i_mc0_ack_o),
.wbm0_err_o (),
.wbm0_rty_o (),
// Wishbone slave interface 1
.wbm1_dat_i (wbs_d_mc0_dat_i),
.wbm1_adr_i (wbs_d_mc0_adr_i),
.wbm1_sel_i (wbs_d_mc0_sel_i),
.wbm1_cti_i (wbs_d_mc0_cti_i),
.wbm1_bte_i (wbs_d_mc0_bte_i),
.wbm1_we_i (wbs_d_mc0_we_i ),
.wbm1_cyc_i (wbs_d_mc0_cyc_i),
.wbm1_stb_i (wbs_d_mc0_stb_i),
.wbm1_dat_o (wbs_d_mc0_dat_o),
.wbm1_ack_o (wbs_d_mc0_ack_o),
.wbm1_err_o (),
.wbm1_rty_o (),
// Clock, reset
.wb_clk_i (wb_clk),
.wb_rst_i (wb_rst));
 
assign wbs_i_mc0_err_o = 0;
assign wbs_i_mc0_rty_o = 0;
 
assign wbs_d_mc0_err_o = 0;
assign wbs_d_mc0_rty_o = 0;
defparam ram_wb0.aw = wb_aw;
defparam ram_wb0.dw = wb_dw;
defparam ram_wb0.mem_span = internal_sram_mem_span;
defparam ram_wb0.adr_width_for_span = internal_sram_adr_width_for_span;
////////////////////////////////////////////////////////////////////////
`endif // `ifdef RAM_WB
 
 
`ifdef ETH0
 
//
// Wires
//
wire eth0_irq;
wire [3:0] eth0_mtxd;
wire eth0_mtxen;
wire eth0_mtxerr;
wire eth0_mtx_clk;
wire eth0_mrx_clk;
wire [3:0] eth0_mrxd;
wire eth0_mrxdv;
wire eth0_mrxerr;
wire eth0_mcoll;
wire eth0_mcrs;
wire eth0_speed;
wire eth0_duplex;
wire eth0_link;
// Management interface wires
wire eth0_md_i;
wire eth0_md_o;
wire eth0_md_oe;
 
 
//
// assigns
 
// Hook up MII wires
assign eth0_mtx_clk = eth0_tx_clk;
assign eth0_tx_data = eth0_mtxd[3:0];
assign eth0_tx_en = eth0_mtxen;
assign eth0_tx_er = eth0_mtxerr;
assign eth0_mrxd[3:0] = eth0_rx_data;
assign eth0_mrxdv = eth0_dv;
assign eth0_mrxerr = eth0_rx_er;
assign eth0_mrx_clk = eth0_rx_clk;
assign eth0_mcoll = eth0_col;
assign eth0_mcrs = eth0_crs;
 
`ifdef XILINX
// Xilinx primitive for MDIO tristate
IOBUF iobuf_phy_smi_data
(
// Outputs
.O (eth0_md_i),
// Inouts
.IO (eth0_md_pad_io),
// Inputs
.I (eth0_md_o),
.T (!eth0_md_oe));
`else // !`ifdef XILINX
// Generic technology tristate control for management interface
assign eth0_md_pad_io = eth0_md_oe ? eth0_md_o : 1'bz;
assign eth0_md_i = eth0_md_pad_io;
`endif // !`ifdef XILINX
 
`ifdef ETH0_PHY_RST
assign eth0_rst_n_o = !wb_rst;
`endif
ethmac ethmac0
(
// Wishbone Slave interface
.wb_clk_i (wb_clk),
.wb_rst_i (wb_rst),
.wb_dat_i (wbs_d_eth0_dat_i[31:0]),
.wb_adr_i (wbs_d_eth0_adr_i[wbs_d_eth0_addr_width-1:2]),
.wb_sel_i (wbs_d_eth0_sel_i[3:0]),
.wb_we_i (wbs_d_eth0_we_i),
.wb_cyc_i (wbs_d_eth0_cyc_i),
.wb_stb_i (wbs_d_eth0_stb_i),
.wb_dat_o (wbs_d_eth0_dat_o[31:0]),
.wb_err_o (wbs_d_eth0_err_o),
.wb_ack_o (wbs_d_eth0_ack_o),
// Wishbone Master Interface
.m_wb_adr_o (wbm_eth0_adr_o[31:0]),
.m_wb_sel_o (wbm_eth0_sel_o[3:0]),
.m_wb_we_o (wbm_eth0_we_o),
.m_wb_dat_o (wbm_eth0_dat_o[31:0]),
.m_wb_cyc_o (wbm_eth0_cyc_o),
.m_wb_stb_o (wbm_eth0_stb_o),
.m_wb_cti_o (wbm_eth0_cti_o[2:0]),
.m_wb_bte_o (wbm_eth0_bte_o[1:0]),
.m_wb_dat_i (wbm_eth0_dat_i[31:0]),
.m_wb_ack_i (wbm_eth0_ack_i),
.m_wb_err_i (wbm_eth0_err_i),
 
// Ethernet MII interface
// Transmit
.mtxd_pad_o (eth0_mtxd[3:0]),
.mtxen_pad_o (eth0_mtxen),
.mtxerr_pad_o (eth0_mtxerr),
.mtx_clk_pad_i (eth0_mtx_clk),
// Receive
.mrx_clk_pad_i (eth0_mrx_clk),
.mrxd_pad_i (eth0_mrxd[3:0]),
.mrxdv_pad_i (eth0_mrxdv),
.mrxerr_pad_i (eth0_mrxerr),
.mcoll_pad_i (eth0_mcoll),
.mcrs_pad_i (eth0_mcrs),
// Management interface
.md_pad_i (eth0_md_i),
.mdc_pad_o (eth0_mdc_pad_o),
.md_pad_o (eth0_md_o),
.md_padoe_o (eth0_md_oe),
 
// Processor interrupt
.int_o (eth0_irq)
/*
.mbist_so_o (),
.mbist_si_i (),
.mbist_ctrl_i ()
*/
);
 
assign wbs_d_eth0_rty_o = 0;
 
`else
assign wbs_d_eth0_dat_o = 0;
assign wbs_d_eth0_err_o = 0;
assign wbs_d_eth0_ack_o = 0;
assign wbs_d_eth0_rty_o = 0;
assign wbm_eth0_adr_o = 0;
assign wbm_eth0_sel_o = 0;
assign wbm_eth0_we_o = 0;
assign wbm_eth0_dat_o = 0;
assign wbm_eth0_cyc_o = 0;
assign wbm_eth0_stb_o = 0;
assign wbm_eth0_cti_o = 0;
assign wbm_eth0_bte_o = 0;
`endif
`ifdef UART0
////////////////////////////////////////////////////////////////////////
//
// UART0
//
////////////////////////////////////////////////////////////////////////
 
//
// Wires
//
wire uart0_srx;
wire uart0_stx;
wire uart0_irq;
 
//
// Assigns
//
assign wbs_d_uart0_err_o = 0;
assign wbs_d_uart0_rty_o = 0;
 
// Two UART lines coming to single one (ensure they go high when unconnected)
assign uart_srx = uart0_srx_pad_i & uart0_srx_expheader_pad_i;
assign uart0_stx_pad_o = uart0_stx;
assign uart0_stx_expheader_pad_o = uart0_stx;
uart16550 uart16550_0
(
// Wishbone slave interface
.wb_clk_i (wb_clk),
.wb_rst_i (wb_rst),
.wb_adr_i (wbs_d_uart0_adr_i[uart0_addr_width-1:0]),
.wb_dat_i (wbs_d_uart0_dat_i),
.wb_we_i (wbs_d_uart0_we_i),
.wb_stb_i (wbs_d_uart0_stb_i),
.wb_cyc_i (wbs_d_uart0_cyc_i),
//.wb_sel_i (),
.wb_dat_o (wbs_d_uart0_dat_o),
.wb_ack_o (wbs_d_uart0_ack_o),
 
.int_o (uart0_irq),
.stx_pad_o (uart0_stx),
.rts_pad_o (),
.dtr_pad_o (),
// .baud_o (),
// Inputs
.srx_pad_i (uart0_srx),
.cts_pad_i (1'b0),
.dsr_pad_i (1'b0),
.ri_pad_i (1'b0),
.dcd_pad_i (1'b0));
 
////////////////////////////////////////////////////////////////////////
`else // !`ifdef UART0
//
// Assigns
//
assign wbs_d_uart0_err_o = 0;
assign wbs_d_uart0_rty_o = 0;
assign wbs_d_uart0_ack_o = 0;
assign wbs_d_uart0_dat_o = 0;
////////////////////////////////////////////////////////////////////////
`endif // !`ifdef UART0
`ifdef SPI0
////////////////////////////////////////////////////////////////////////
//
// SPI0 controller
//
////////////////////////////////////////////////////////////////////////
 
//
// Wires
//
wire spi0_irq;
 
//
// Assigns
//
assign wbs_d_spi0_err_o = 0;
assign wbs_d_spi0_rty_o = 0;
//assign spi0_hold_n_o = 1;
//assign spi0_w_n_o = 1;
simple_spi spi0
(
// Wishbone slave interface
.clk_i (wb_clk),
.rst_i (wb_rst),
.cyc_i (wbs_d_spi0_cyc_i),
.stb_i (wbs_d_spi0_stb_i),
.adr_i (wbs_d_spi0_adr_i[spi0_wb_adr_width-1:0]),
.we_i (wbs_d_spi0_we_i),
.dat_i (wbs_d_spi0_dat_i),
.dat_o (wbs_d_spi0_dat_o),
.ack_o (wbs_d_spi0_ack_o),
// SPI IRQ
.inta_o (spi0_irq),
// External SPI interface
.sck_o (spi0_sck_o),
.ss_o (spi0_ss_o),
.mosi_o (spi0_mosi_o),
.miso_i (spi0_miso_i)
);
 
defparam spi0.slave_select_width = spi0_ss_width;
////////////////////////////////////////////////////////////////////////
`else // !`ifdef SPI0
 
//
// Assigns
//
assign wbs_d_spi0_dat_o = 0;
assign wbs_d_spi0_ack_o = 0;
assign wbs_d_spi0_err_o = 0;
assign wbs_d_spi0_rty_o = 0;
////////////////////////////////////////////////////////////////////////
`endif // !`ifdef SPI0
 
 
`ifdef I2C0
////////////////////////////////////////////////////////////////////////
//
// i2c controller 0
//
////////////////////////////////////////////////////////////////////////
 
//
// Wires
//
wire i2c0_irq;
wire scl0_pad_o;
wire scl0_padoen_o;
wire sda0_pad_o;
wire sda0_padoen_o;
i2c_master_slave
#
(
.DEFAULT_SLAVE_ADDR(HV0_SADR)
)
i2c_master_slave0
(
.wb_clk_i (wb_clk),
.wb_rst_i (wb_rst),
.arst_i (wb_rst),
.wb_adr_i (wbs_d_i2c0_adr_i[i2c_0_wb_adr_width-1:0]),
.wb_dat_i (wbs_d_i2c0_dat_i),
.wb_we_i (wbs_d_i2c0_we_i ),
.wb_cyc_i (wbs_d_i2c0_cyc_i),
.wb_stb_i (wbs_d_i2c0_stb_i),
.wb_dat_o (wbs_d_i2c0_dat_o),
.wb_ack_o (wbs_d_i2c0_ack_o),
.scl_pad_i (i2c0_scl_io ),
.scl_pad_o (scl0_pad_o ),
.scl_padoen_o (scl0_padoen_o ),
.sda_pad_i (i2c0_sda_io ),
.sda_pad_o (sda0_pad_o ),
.sda_padoen_o (sda0_padoen_o ),
// Interrupt
.wb_inta_o (i2c0_irq)
);
 
assign wbs_d_i2c0_err_o = 0;
assign wbs_d_i2c0_rty_o = 0;
 
// i2c phy lines
assign i2c0_scl_io = scl0_padoen_o ? 1'bz : scl0_pad_o;
assign i2c0_sda_io = sda0_padoen_o ? 1'bz : sda0_pad_o;
 
 
////////////////////////////////////////////////////////////////////////
`else // !`ifdef I2C0
 
assign wbs_d_i2c0_dat_o = 0;
assign wbs_d_i2c0_ack_o = 0;
assign wbs_d_i2c0_err_o = 0;
assign wbs_d_i2c0_rty_o = 0;
 
////////////////////////////////////////////////////////////////////////
`endif // !`ifdef I2C0
 
`ifdef I2C1
////////////////////////////////////////////////////////////////////////
//
// i2c controller 1
//
////////////////////////////////////////////////////////////////////////
 
//
// Wires
//
wire i2c1_irq;
wire scl1_pad_o;
wire scl1_padoen_o;
wire sda1_pad_o;
wire sda1_padoen_o;
 
i2c_master_slave
#
(
.DEFAULT_SLAVE_ADDR(HV1_SADR)
)
i2c_master_slave1
(
.wb_clk_i (wb_clk),
.wb_rst_i (wb_rst),
.arst_i (wb_rst),
.wb_adr_i (wbs_d_i2c1_adr_i[i2c_1_wb_adr_width-1:0]),
.wb_dat_i (wbs_d_i2c1_dat_i),
.wb_we_i (wbs_d_i2c1_we_i ),
.wb_cyc_i (wbs_d_i2c1_cyc_i),
.wb_stb_i (wbs_d_i2c1_stb_i),
.wb_dat_o (wbs_d_i2c1_dat_o),
.wb_ack_o (wbs_d_i2c1_ack_o),
.scl_pad_i (i2c1_scl_io ),
.scl_pad_o (scl1_pad_o ),
.scl_padoen_o (scl1_padoen_o ),
.sda_pad_i (i2c1_sda_io ),
.sda_pad_o (sda1_pad_o ),
.sda_padoen_o (sda1_padoen_o ),
// Interrupt
.wb_inta_o (i2c1_irq)
);
 
assign wbs_d_i2c1_err_o = 0;
assign wbs_d_i2c1_rty_o = 0;
 
// i2c phy lines
assign i2c1_scl_io = scl1_padoen_o ? 1'bz : scl1_pad_o;
assign i2c1_sda_io = sda1_padoen_o ? 1'bz : sda1_pad_o;
 
////////////////////////////////////////////////////////////////////////
`else // !`ifdef I2C1
 
assign wbs_d_i2c1_dat_o = 0;
assign wbs_d_i2c1_ack_o = 0;
assign wbs_d_i2c1_err_o = 0;
assign wbs_d_i2c1_rty_o = 0;
 
////////////////////////////////////////////////////////////////////////
`endif // !`ifdef I2C1
 
`ifdef GPIO0
////////////////////////////////////////////////////////////////////////
//
// GPIO 0
//
////////////////////////////////////////////////////////////////////////
 
gpio gpio0
(
// GPIO bus
.gpio_io (gpio0_io[gpio0_io_width-1:0]),
// Wishbone slave interface
.wb_adr_i (wbs_d_gpio0_adr_i[gpio0_wb_adr_width-1:0]),
.wb_dat_i (wbs_d_gpio0_dat_i),
.wb_we_i (wbs_d_gpio0_we_i),
.wb_cyc_i (wbs_d_gpio0_cyc_i),
.wb_stb_i (wbs_d_gpio0_stb_i),
.wb_cti_i (wbs_d_gpio0_cti_i),
.wb_bte_i (wbs_d_gpio0_bte_i),
.wb_dat_o (wbs_d_gpio0_dat_o),
.wb_ack_o (wbs_d_gpio0_ack_o),
.wb_err_o (wbs_d_gpio0_err_o),
.wb_rty_o (wbs_d_gpio0_rty_o),
.wb_clk (wb_clk),
.wb_rst (wb_rst)
);
 
defparam gpio0.gpio_io_width = gpio0_io_width;
defparam gpio0.gpio_dir_reset_val = gpio0_dir_reset_val;
defparam gpio0.gpio_o_reset_val = gpio0_o_reset_val;
 
////////////////////////////////////////////////////////////////////////
`else // !`ifdef GPIO0
assign wbs_d_gpio0_dat_o = 0;
assign wbs_d_gpio0_ack_o = 0;
assign wbs_d_gpio0_err_o = 0;
assign wbs_d_gpio0_rty_o = 0;
////////////////////////////////////////////////////////////////////////
`endif // !`ifdef GPIO0
////////////////////////////////////////////////////////////////////////
//
// OR1200 Interrupt assignment
//
////////////////////////////////////////////////////////////////////////
assign or1200_pic_ints[0] = 0; // Non-maskable inside OR1200
assign or1200_pic_ints[1] = 0; // Non-maskable inside OR1200
`ifdef UART0
assign or1200_pic_ints[2] = uart0_irq;
`else
assign or1200_pic_ints[2] = 0;
`endif
assign or1200_pic_ints[3] = 0;
`ifdef ETH0
assign or1200_pic_ints[4] = eth0_irq;
`else
assign or1200_pic_ints[4] = 0;
`endif
assign or1200_pic_ints[5] = 0;
`ifdef SPI0
assign or1200_pic_ints[6] = spi0_irq;
`else
assign or1200_pic_ints[6] = 0;
`endif
assign or1200_pic_ints[7] = 0;
assign or1200_pic_ints[8] = 0;
assign or1200_pic_ints[9] = 0;
`ifdef I2C0
assign or1200_pic_ints[10] = i2c0_irq;
`else
assign or1200_pic_ints[10] = 0;
`endif
`ifdef I2C1
assign or1200_pic_ints[11] = i2c1_irq;
`else
assign or1200_pic_ints[11] = 0;
`endif
assign or1200_pic_ints[12] = 0;
assign or1200_pic_ints[13] = 0;
assign or1200_pic_ints[14] = 0;
assign or1200_pic_ints[15] = 0;
assign or1200_pic_ints[16] = 0;
assign or1200_pic_ints[17] = 0;
assign or1200_pic_ints[18] = 0;
assign or1200_pic_ints[19] = 0;
assign or1200_pic_ints[20] = 0;
assign or1200_pic_ints[21] = 0;
assign or1200_pic_ints[22] = 0;
assign or1200_pic_ints[23] = 0;
assign or1200_pic_ints[24] = 0;
assign or1200_pic_ints[25] = 0;
assign or1200_pic_ints[26] = 0;
assign or1200_pic_ints[27] = 0;
assign or1200_pic_ints[28] = 0;
assign or1200_pic_ints[29] = 0;
assign or1200_pic_ints[30] = 0;
endmodule // orpsoc_top
 
 
/boards/xilinx/ml501/rtl/verilog/arbiter/arbiter_bytebus.v
0,0 → 1,1192
//////////////////////////////////////////////////////////////////////
/// ////
/// Wishbone arbiter, byte-wide data path, no bursting ////
/// ////
/// Simple arbiter, single master, multiple slave, for byte-wide ////
/// peripherals ////
/// ////
/// Julius Baxter, julius@opencores.org ////
/// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2009, 2010 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
 
//
// Things to update when changing slave config:
//
// 1. Port list
// 2. Port specification
// 3. Slave addr select parameter
// 4. Slave addr selects
// 5. Slave input mux logic
// 6. The four different master out mux logics (dat_o mux, and ack, rty & err)
//
`include "orpsoc-defines.v"
module arbiter_bytebus
(
 
// Master in
wbm0_adr_o,
wbm0_dat_o,
wbm0_sel_o,
wbm0_we_o,
wbm0_cyc_o,
wbm0_stb_o,
wbm0_cti_o,
wbm0_bte_o,
wbm0_dat_i,
wbm0_ack_i,
wbm0_err_i,
wbm0_rty_i,
 
// Slave one
// Wishbone Slave interface
wbs0_adr_i,
wbs0_dat_i,
wbs0_we_i,
wbs0_cyc_i,
wbs0_stb_i,
wbs0_cti_i,
wbs0_bte_i,
wbs0_dat_o,
wbs0_ack_o,
wbs0_err_o,
wbs0_rty_o,
 
// Slave two
// Wishbone Slave interface
wbs1_adr_i,
wbs1_dat_i,
wbs1_we_i,
wbs1_cyc_i,
wbs1_stb_i,
wbs1_cti_i,
wbs1_bte_i,
wbs1_dat_o,
wbs1_ack_o,
wbs1_err_o,
wbs1_rty_o,
 
// Slave three
// Wishbone Slave interface
wbs2_adr_i,
wbs2_dat_i,
wbs2_we_i,
wbs2_cyc_i,
wbs2_stb_i,
wbs2_cti_i,
wbs2_bte_i,
wbs2_dat_o,
wbs2_ack_o,
wbs2_err_o,
wbs2_rty_o,
 
// Slave four
// Wishbone Slave interface
wbs3_adr_i,
wbs3_dat_i,
wbs3_we_i,
wbs3_cyc_i,
wbs3_stb_i,
wbs3_cti_i,
wbs3_bte_i,
wbs3_dat_o,
wbs3_ack_o,
wbs3_err_o,
wbs3_rty_o,
 
// Slave five
// Wishbone Slave interface
wbs4_adr_i,
wbs4_dat_i,
wbs4_we_i,
wbs4_cyc_i,
wbs4_stb_i,
wbs4_cti_i,
wbs4_bte_i,
wbs4_dat_o,
wbs4_ack_o,
wbs4_err_o,
wbs4_rty_o,
/*
// Slave six
// Wishbone Slave interface
wbs5_adr_i,
wbs5_dat_i,
wbs5_we_i,
wbs5_cyc_i,
wbs5_stb_i,
wbs5_cti_i,
wbs5_bte_i,
wbs5_dat_o,
wbs5_ack_o,
wbs5_err_o,
wbs5_rty_o,
 
// Slave seven
// Wishbone Slave interface
wbs6_adr_i,
wbs6_dat_i,
wbs6_we_i,
wbs6_cyc_i,
wbs6_stb_i,
wbs6_cti_i,
wbs6_bte_i,
wbs6_dat_o,
wbs6_ack_o,
wbs6_err_o,
wbs6_rty_o,
 
// Slave eight
// Wishbone Slave interface
wbs7_adr_i,
wbs7_dat_i,
wbs7_we_i,
wbs7_cyc_i,
wbs7_stb_i,
wbs7_cti_i,
wbs7_bte_i,
wbs7_dat_o,
wbs7_ack_o,
wbs7_err_o,
wbs7_rty_o,
 
// Slave nine
// Wishbone Slave interface
wbs8_adr_i,
wbs8_dat_i,
wbs8_we_i,
wbs8_cyc_i,
wbs8_stb_i,
wbs8_cti_i,
wbs8_bte_i,
wbs8_dat_o,
wbs8_ack_o,
wbs8_err_o,
wbs8_rty_o,
 
// Slave ten
// Wishbone Slave interface
wbs9_adr_i,
wbs9_dat_i,
wbs9_we_i,
wbs9_cyc_i,
wbs9_stb_i,
wbs9_cti_i,
wbs9_bte_i,
wbs9_dat_o,
wbs9_ack_o,
wbs9_err_o,
wbs9_rty_o,
 
// Slave eleven
// Wishbone Slave interface
wbs10_adr_i,
wbs10_dat_i,
wbs10_we_i,
wbs10_cyc_i,
wbs10_stb_i,
wbs10_cti_i,
wbs10_bte_i,
wbs10_dat_o,
wbs10_ack_o,
wbs10_err_o,
wbs10_rty_o,
 
// Slave twelve
// Wishbone Slave interface
wbs11_adr_i,
wbs11_dat_i,
wbs11_we_i,
wbs11_cyc_i,
wbs11_stb_i,
wbs11_cti_i,
wbs11_bte_i,
wbs11_dat_o,
wbs11_ack_o,
wbs11_err_o,
wbs11_rty_o,
 
// Slave thirteen
// Wishbone Slave interface
wbs12_adr_i,
wbs12_dat_i,
wbs12_we_i,
wbs12_cyc_i,
wbs12_stb_i,
wbs12_cti_i,
wbs12_bte_i,
wbs12_dat_o,
wbs12_ack_o,
wbs12_err_o,
wbs12_rty_o,
 
// Slave fourteen
// Wishbone Slave interface
wbs13_adr_i,
wbs13_dat_i,
wbs13_we_i,
wbs13_cyc_i,
wbs13_stb_i,
wbs13_cti_i,
wbs13_bte_i,
wbs13_dat_o,
wbs13_ack_o,
wbs13_err_o,
wbs13_rty_o,
 
// Slave fifteen
// Wishbone Slave interface
wbs14_adr_i,
wbs14_dat_i,
wbs14_we_i,
wbs14_cyc_i,
wbs14_stb_i,
wbs14_cti_i,
wbs14_bte_i,
wbs14_dat_o,
wbs14_ack_o,
wbs14_err_o,
wbs14_rty_o,
 
// Slave sixteen
// Wishbone Slave interface
wbs15_adr_i,
wbs15_dat_i,
wbs15_we_i,
wbs15_cyc_i,
wbs15_stb_i,
wbs15_cti_i,
wbs15_bte_i,
wbs15_dat_o,
wbs15_ack_o,
wbs15_err_o,
wbs15_rty_o,
 
// Slave seventeen
// Wishbone Slave interface
wbs16_adr_i,
wbs16_dat_i,
wbs16_we_i,
wbs16_cyc_i,
wbs16_stb_i,
wbs16_cti_i,
wbs16_bte_i,
wbs16_dat_o,
wbs16_ack_o,
wbs16_err_o,
wbs16_rty_o,
 
 
// Slave eighteen
// Wishbone Slave interface
wbs17_adr_i,
wbs17_dat_i,
wbs17_we_i,
wbs17_cyc_i,
wbs17_stb_i,
wbs17_cti_i,
wbs17_bte_i,
wbs17_dat_o,
wbs17_ack_o,
wbs17_err_o,
wbs17_rty_o,
// Slave nineteen
// Wishbone Slave interface
wbs18_adr_i,
wbs18_dat_i,
wbs18_we_i,
wbs18_cyc_i,
wbs18_stb_i,
wbs18_cti_i,
wbs18_bte_i,
wbs18_dat_o,
wbs18_ack_o,
wbs18_err_o,
wbs18_rty_o,
// Slave twenty
// Wishbone Slave interface
wbs19_adr_i,
wbs19_dat_i,
wbs19_we_i,
wbs19_cyc_i,
wbs19_stb_i,
wbs19_cti_i,
wbs19_bte_i,
wbs19_dat_o,
wbs19_ack_o,
wbs19_err_o,
wbs19_rty_o,
*/
wb_clk, wb_rst
);
 
parameter wb_dat_width = 32;
parameter wbs_dat_width = 8;
parameter wb_adr_width = 32;
 
parameter wb_addr_match_width = 8;
 
parameter wb_num_slaves = 20; // Currently can handle up to 20
 
// Slave addresses
parameter slave0_adr = 8'h00;
parameter slave1_adr = 8'h00;
parameter slave2_adr = 8'h00;
parameter slave3_adr = 8'h00;
parameter slave4_adr = 8'h00;
parameter slave5_adr = 8'h00;
parameter slave6_adr = 8'h00;
parameter slave7_adr = 8'h00;
parameter slave8_adr = 8'h00;
parameter slave9_adr = 8'h00;
parameter slave10_adr = 8'h00;
parameter slave11_adr = 8'h00;
parameter slave12_adr = 8'h00;
parameter slave13_adr = 8'h00;
parameter slave14_adr = 8'h00;
parameter slave15_adr = 8'h00;
parameter slave16_adr = 8'h00;
parameter slave17_adr = 8'h00;
parameter slave18_adr = 8'h00;
parameter slave19_adr = 8'h00;
 
`define WB_ARB_ADDR_MATCH_SEL wb_adr_width-1:wb_adr_width-wb_addr_match_width
input wb_clk;
input wb_rst;
// WB Master one
input [wb_adr_width-1:0] wbm0_adr_o;
input [wb_dat_width-1:0] wbm0_dat_o;
input [3:0] wbm0_sel_o;
input wbm0_we_o;
input wbm0_cyc_o;
input wbm0_stb_o;
input [2:0] wbm0_cti_o;
input [1:0] wbm0_bte_o;
output [wb_dat_width-1:0] wbm0_dat_i;
output wbm0_ack_i;
output wbm0_err_i;
output wbm0_rty_i;
// Slave one
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs0_adr_i;
output [wbs_dat_width-1:0] wbs0_dat_i;
output wbs0_we_i;
output wbs0_cyc_i;
output wbs0_stb_i;
output [2:0] wbs0_cti_i;
output [1:0] wbs0_bte_i;
input [wbs_dat_width-1:0] wbs0_dat_o;
input wbs0_ack_o;
input wbs0_err_o;
input wbs0_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs1_adr_i;
output [wbs_dat_width-1:0] wbs1_dat_i;
output wbs1_we_i;
output wbs1_cyc_i;
output wbs1_stb_i;
output [2:0] wbs1_cti_i;
output [1:0] wbs1_bte_i;
input [wbs_dat_width-1:0] wbs1_dat_o;
input wbs1_ack_o;
input wbs1_err_o;
input wbs1_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs2_adr_i;
output [wbs_dat_width-1:0] wbs2_dat_i;
output wbs2_we_i;
output wbs2_cyc_i;
output wbs2_stb_i;
output [2:0] wbs2_cti_i;
output [1:0] wbs2_bte_i;
input [wbs_dat_width-1:0] wbs2_dat_o;
input wbs2_ack_o;
input wbs2_err_o;
input wbs2_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs3_adr_i;
output [wbs_dat_width-1:0] wbs3_dat_i;
output wbs3_we_i;
output wbs3_cyc_i;
output wbs3_stb_i;
output [2:0] wbs3_cti_i;
output [1:0] wbs3_bte_i;
input [wbs_dat_width-1:0] wbs3_dat_o;
input wbs3_ack_o;
input wbs3_err_o;
input wbs3_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs4_adr_i;
output [wbs_dat_width-1:0] wbs4_dat_i;
output wbs4_we_i;
output wbs4_cyc_i;
output wbs4_stb_i;
output [2:0] wbs4_cti_i;
output [1:0] wbs4_bte_i;
input [wbs_dat_width-1:0] wbs4_dat_o;
input wbs4_ack_o;
input wbs4_err_o;
input wbs4_rty_o;
/*
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs5_adr_i;
output [wbs_dat_width-1:0] wbs5_dat_i;
output wbs5_we_i;
output wbs5_cyc_i;
output wbs5_stb_i;
output [2:0] wbs5_cti_i;
output [1:0] wbs5_bte_i;
input [wbs_dat_width-1:0] wbs5_dat_o;
input wbs5_ack_o;
input wbs5_err_o;
input wbs5_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs6_adr_i;
output [wbs_dat_width-1:0] wbs6_dat_i;
output wbs6_we_i;
output wbs6_cyc_i;
output wbs6_stb_i;
output [2:0] wbs6_cti_i;
output [1:0] wbs6_bte_i;
input [wbs_dat_width-1:0] wbs6_dat_o;
input wbs6_ack_o;
input wbs6_err_o;
input wbs6_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs7_adr_i;
output [wbs_dat_width-1:0] wbs7_dat_i;
output wbs7_we_i;
output wbs7_cyc_i;
output wbs7_stb_i;
output [2:0] wbs7_cti_i;
output [1:0] wbs7_bte_i;
input [wbs_dat_width-1:0] wbs7_dat_o;
input wbs7_ack_o;
input wbs7_err_o;
input wbs7_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs8_adr_i;
output [wbs_dat_width-1:0] wbs8_dat_i;
output wbs8_we_i;
output wbs8_cyc_i;
output wbs8_stb_i;
output [2:0] wbs8_cti_i;
output [1:0] wbs8_bte_i;
input [wbs_dat_width-1:0] wbs8_dat_o;
input wbs8_ack_o;
input wbs8_err_o;
input wbs8_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs9_adr_i;
output [wbs_dat_width-1:0] wbs9_dat_i;
output wbs9_we_i;
output wbs9_cyc_i;
output wbs9_stb_i;
output [2:0] wbs9_cti_i;
output [1:0] wbs9_bte_i;
input [wbs_dat_width-1:0] wbs9_dat_o;
input wbs9_ack_o;
input wbs9_err_o;
input wbs9_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs10_adr_i;
output [wbs_dat_width-1:0] wbs10_dat_i;
output wbs10_we_i;
output wbs10_cyc_i;
output wbs10_stb_i;
output [2:0] wbs10_cti_i;
output [1:0] wbs10_bte_i;
input [wbs_dat_width-1:0] wbs10_dat_o;
input wbs10_ack_o;
input wbs10_err_o;
input wbs10_rty_o;
 
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs11_adr_i;
output [wbs_dat_width-1:0] wbs11_dat_i;
output wbs11_we_i;
output wbs11_cyc_i;
output wbs11_stb_i;
output [2:0] wbs11_cti_i;
output [1:0] wbs11_bte_i;
input [wbs_dat_width-1:0] wbs11_dat_o;
input wbs11_ack_o;
input wbs11_err_o;
input wbs11_rty_o;
 
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs12_adr_i;
output [wbs_dat_width-1:0] wbs12_dat_i;
output wbs12_we_i;
output wbs12_cyc_i;
output wbs12_stb_i;
output [2:0] wbs12_cti_i;
output [1:0] wbs12_bte_i;
input [wbs_dat_width-1:0] wbs12_dat_o;
input wbs12_ack_o;
input wbs12_err_o;
input wbs12_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs13_adr_i;
output [wbs_dat_width-1:0] wbs13_dat_i;
output wbs13_we_i;
output wbs13_cyc_i;
output wbs13_stb_i;
output [2:0] wbs13_cti_i;
output [1:0] wbs13_bte_i;
input [wbs_dat_width-1:0] wbs13_dat_o;
input wbs13_ack_o;
input wbs13_err_o;
input wbs13_rty_o;
 
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs14_adr_i;
output [wbs_dat_width-1:0] wbs14_dat_i;
output wbs14_we_i;
output wbs14_cyc_i;
output wbs14_stb_i;
output [2:0] wbs14_cti_i;
output [1:0] wbs14_bte_i;
input [wbs_dat_width-1:0] wbs14_dat_o;
input wbs14_ack_o;
input wbs14_err_o;
input wbs14_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs15_adr_i;
output [wbs_dat_width-1:0] wbs15_dat_i;
output wbs15_we_i;
output wbs15_cyc_i;
output wbs15_stb_i;
output [2:0] wbs15_cti_i;
output [1:0] wbs15_bte_i;
input [wbs_dat_width-1:0] wbs15_dat_o;
input wbs15_ack_o;
input wbs15_err_o;
input wbs15_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs16_adr_i;
output [wbs_dat_width-1:0] wbs16_dat_i;
output wbs16_we_i;
output wbs16_cyc_i;
output wbs16_stb_i;
output [2:0] wbs16_cti_i;
output [1:0] wbs16_bte_i;
input [wbs_dat_width-1:0] wbs16_dat_o;
input wbs16_ack_o;
input wbs16_err_o;
input wbs16_rty_o;
 
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs17_adr_i;
output [wbs_dat_width-1:0] wbs17_dat_i;
output wbs17_we_i;
output wbs17_cyc_i;
output wbs17_stb_i;
output [2:0] wbs17_cti_i;
output [1:0] wbs17_bte_i;
input [wbs_dat_width-1:0] wbs17_dat_o;
input wbs17_ack_o;
input wbs17_err_o;
input wbs17_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs18_adr_i;
output [wbs_dat_width-1:0] wbs18_dat_i;
output wbs18_we_i;
output wbs18_cyc_i;
output wbs18_stb_i;
output [2:0] wbs18_cti_i;
output [1:0] wbs18_bte_i;
input [wbs_dat_width-1:0] wbs18_dat_o;
input wbs18_ack_o;
input wbs18_err_o;
input wbs18_rty_o;
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs19_adr_i;
output [wbs_dat_width-1:0] wbs19_dat_i;
output wbs19_we_i;
output wbs19_cyc_i;
output wbs19_stb_i;
output [2:0] wbs19_cti_i;
output [1:0] wbs19_bte_i;
input [wbs_dat_width-1:0] wbs19_dat_o;
input wbs19_ack_o;
input wbs19_err_o;
input wbs19_rty_o;
*/
 
reg watchdog_err;
// Master input mux output wires
wire [wb_adr_width-1:0] wbm_adr_o;
wire [wbs_dat_width-1:0] wbm_dat_o;
wire [3:0] wbm_sel_o;
wire wbm_we_o;
wire wbm_cyc_o;
wire wbm_stb_o;
wire [2:0] wbm_cti_o;
wire [1:0] wbm_bte_o;
wire [wbs_dat_width-1:0] wbm_dat_byte_i;
wire wbm_ack_i;
wire wbm_err_i;
wire wbm_rty_i;
 
// Master input mux (not really used, only one master on this bus)
assign wbm_adr_o = wbm0_adr_o;
 
// Select the right byte and put it on the data out line
// !BIG ENDIAN!
assign wbm_dat_o = wbm0_sel_o[3] ? wbm0_dat_o[31:24] :
wbm0_sel_o[2] ? wbm0_dat_o[23:16] :
wbm0_sel_o[1] ? wbm0_dat_o[15:8] :
wbm0_dat_o[7:0];
assign wbm_we_o = wbm0_we_o;
assign wbm_cyc_o = wbm0_stb_o;
assign wbm_stb_o = wbm0_stb_o;
 
// Will we really need these for byte-peripherals
assign wbm_cti_o = wbm0_cti_o;
assign wbm_bte_o = wbm0_bte_o;
 
// Signals back to the master
assign wbm0_dat_i = (wbm0_sel_o[3]) ? {wbm_dat_byte_i, 24'd0} :
(wbm0_sel_o[2]) ? {8'd0, wbm_dat_byte_i, 16'd0} :
(wbm0_sel_o[1]) ? {16'd0, wbm_dat_byte_i, 8'd0} :
{24'd0, wbm_dat_byte_i};
 
assign wbm0_ack_i = wbm_ack_i;
assign wbm0_err_i = wbm_err_i;
assign wbm0_rty_i = wbm_rty_i;
 
`ifdef ARBITER_BYTEBUS_WATCHDOG
reg [`ARBITER_BYTEBUS_WATCHDOG_TIMER_WIDTH:0] watchdog_timer;
reg wbm_stb_r; // Register strobe
wire wbm_stb_edge; // Detect its edge
 
always @(posedge wb_clk)
wbm_stb_r <= wbm_stb_o;
 
assign wbm_stb_edge = (wbm_stb_o & !wbm_stb_r);
// Counter logic
always @(posedge wb_clk)
if (wb_rst) watchdog_timer <= 0;
else if (wbm_ack_i) // When we see an ack, turn off timer
watchdog_timer <= 0;
else if (wbm_stb_edge) // New access means start timer again
watchdog_timer <= 1;
else if (|watchdog_timer) // Continue counting if counter > 0
watchdog_timer <= watchdog_timer + 1;
 
always @(posedge wb_clk)
watchdog_err <= (&watchdog_timer);
`else // !`ifdef ARBITER_BYTEBUS_WATCHDOG
always @(posedge wb_clk)
watchdog_err <= 0;
`endif // !`ifdef ARBITER_BYTEBUS_WATCHDOG
 
// Wishbone slave mux out wires
wire [wb_adr_width-1:0] wbs_adr_i;
wire [wbs_dat_width-1:0] wbs_dat_i;
wire wbs_we_i;
wire wbs_cyc_i;
wire wbs_stb_i;
wire [2:0] wbs_cti_i;
wire [1:0] wbs_bte_i;
wire [wbs_dat_width-1:0] wbs_dat_o;
wire wbs_ack_o;
wire wbs_err_o;
wire wbs_rty_o;
 
// Slave select wire
wire [wb_num_slaves-1:0] wb_slave_sel;
// Slave out mux in wires
wire [wbs_dat_width-1:0] wbs_dat_o_mux_i [0:wb_num_slaves-1];
wire wbs_ack_o_mux_i [0:wb_num_slaves-1];
wire wbs_err_o_mux_i [0:wb_num_slaves-1];
wire wbs_rty_o_mux_i [0:wb_num_slaves-1];
 
// Slave selects
assign wb_slave_sel[0] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave0_adr;
assign wb_slave_sel[1] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave1_adr;
assign wb_slave_sel[2] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave2_adr;
assign wb_slave_sel[3] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave3_adr;
assign wb_slave_sel[4] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave4_adr;
/*
assign wb_slave_sel[5] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave5_adr;
assign wb_slave_sel[6] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave6_adr;
assign wb_slave_sel[7] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave7_adr;
assign wb_slave_sel[8] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave8_adr;
assign wb_slave_sel[9] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave9_adr;
assign wb_slave_sel[10] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave10_adr;
assign wb_slave_sel[11] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave11_adr;
assign wb_slave_sel[12] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave12_adr;
assign wb_slave_sel[13] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave13_adr;
assign wb_slave_sel[14] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave14_adr;
assign wb_slave_sel[15] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave15_adr;
assign wb_slave_sel[16] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave16_adr;
assign wb_slave_sel[16] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave17_adr;
assign wb_slave_sel[16] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave18_adr;
assign wb_slave_sel[16] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave19_adr;
*/
 
 
// Assign master inputs to slaves and slave inputs for MUXing back to master
 
// Slave 0 inputs
assign wbs0_adr_i = wbm_adr_o;
assign wbs0_dat_i = wbm_dat_o;
assign wbs0_cyc_i = wbm_cyc_o & wb_slave_sel[0];
assign wbs0_stb_i = wbm_stb_o & wb_slave_sel[0];
assign wbs0_we_i = wbm_we_o;
assign wbs0_cti_i = wbm_cti_o;
assign wbs0_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[0] = wbs0_dat_o;
assign wbs_ack_o_mux_i[0] = wbs0_ack_o & wb_slave_sel[0];
assign wbs_err_o_mux_i[0] = wbs0_err_o & wb_slave_sel[0];
assign wbs_rty_o_mux_i[0] = wbs0_rty_o & wb_slave_sel[0];
 
 
// Slave 1 inputs
assign wbs1_adr_i = wbm_adr_o;
assign wbs1_dat_i = wbm_dat_o;
assign wbs1_cyc_i = wbm_cyc_o & wb_slave_sel[1];
assign wbs1_stb_i = wbm_stb_o & wb_slave_sel[1];
assign wbs1_we_i = wbm_we_o;
assign wbs1_cti_i = wbm_cti_o;
assign wbs1_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[1] = wbs1_dat_o;
assign wbs_ack_o_mux_i[1] = wbs1_ack_o & wb_slave_sel[1];
assign wbs_err_o_mux_i[1] = wbs1_err_o & wb_slave_sel[1];
assign wbs_rty_o_mux_i[1] = wbs1_rty_o & wb_slave_sel[1];
 
 
// Slave 2 inputs
assign wbs2_adr_i = wbm_adr_o;
assign wbs2_dat_i = wbm_dat_o;
assign wbs2_cyc_i = wbm_cyc_o & wb_slave_sel[2];
assign wbs2_stb_i = wbm_stb_o & wb_slave_sel[2];
assign wbs2_we_i = wbm_we_o;
assign wbs2_cti_i = wbm_cti_o;
assign wbs2_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[2] = wbs2_dat_o;
assign wbs_ack_o_mux_i[2] = wbs2_ack_o & wb_slave_sel[2];
assign wbs_err_o_mux_i[2] = wbs2_err_o & wb_slave_sel[2];
assign wbs_rty_o_mux_i[2] = wbs2_rty_o & wb_slave_sel[2];
 
 
// Slave 3 inputs
assign wbs3_adr_i = wbm_adr_o;
assign wbs3_dat_i = wbm_dat_o;
assign wbs3_cyc_i = wbm_cyc_o & wb_slave_sel[3];
assign wbs3_stb_i = wbm_stb_o & wb_slave_sel[3];
assign wbs3_we_i = wbm_we_o;
assign wbs3_cti_i = wbm_cti_o;
assign wbs3_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[3] = wbs3_dat_o;
assign wbs_ack_o_mux_i[3] = wbs3_ack_o & wb_slave_sel[3];
assign wbs_err_o_mux_i[3] = wbs3_err_o & wb_slave_sel[3];
assign wbs_rty_o_mux_i[3] = wbs3_rty_o & wb_slave_sel[3];
 
 
// Slave 4 inputs
assign wbs4_adr_i = wbm_adr_o;
assign wbs4_dat_i = wbm_dat_o;
assign wbs4_cyc_i = wbm_cyc_o & wb_slave_sel[4];
assign wbs4_stb_i = wbm_stb_o & wb_slave_sel[4];
assign wbs4_we_i = wbm_we_o;
assign wbs4_cti_i = wbm_cti_o;
assign wbs4_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[4] = wbs4_dat_o;
assign wbs_ack_o_mux_i[4] = wbs4_ack_o & wb_slave_sel[4];
assign wbs_err_o_mux_i[4] = wbs4_err_o & wb_slave_sel[4];
assign wbs_rty_o_mux_i[4] = wbs4_rty_o & wb_slave_sel[4];
 
/*
// Slave 5 inputs
assign wbs5_adr_i = wbm_adr_o;
assign wbs5_dat_i = wbm_dat_o;
assign wbs5_cyc_i = wbm_cyc_o & wb_slave_sel[5];
assign wbs5_stb_i = wbm_stb_o & wb_slave_sel[5];
assign wbs5_we_i = wbm_we_o;
assign wbs5_cti_i = wbm_cti_o;
assign wbs5_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[5] = wbs5_dat_o;
assign wbs_ack_o_mux_i[5] = wbs5_ack_o & wb_slave_sel[5];
assign wbs_err_o_mux_i[5] = wbs5_err_o & wb_slave_sel[5];
assign wbs_rty_o_mux_i[5] = wbs5_rty_o & wb_slave_sel[5];
 
 
// Slave 6 inputs
assign wbs6_adr_i = wbm_adr_o;
assign wbs6_dat_i = wbm_dat_o;
assign wbs6_cyc_i = wbm_cyc_o & wb_slave_sel[6];
assign wbs6_stb_i = wbm_stb_o & wb_slave_sel[6];
assign wbs6_we_i = wbm_we_o;
assign wbs6_cti_i = wbm_cti_o;
assign wbs6_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[6] = wbs6_dat_o;
assign wbs_ack_o_mux_i[6] = wbs6_ack_o & wb_slave_sel[6];
assign wbs_err_o_mux_i[6] = wbs6_err_o & wb_slave_sel[6];
assign wbs_rty_o_mux_i[6] = wbs6_rty_o & wb_slave_sel[6];
 
 
// Slave 7 inputs
assign wbs7_adr_i = wbm_adr_o;
assign wbs7_dat_i = wbm_dat_o;
assign wbs7_cyc_i = wbm_cyc_o & wb_slave_sel[7];
assign wbs7_stb_i = wbm_stb_o & wb_slave_sel[7];
assign wbs7_we_i = wbm_we_o;
assign wbs7_cti_i = wbm_cti_o;
assign wbs7_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[7] = wbs7_dat_o;
assign wbs_ack_o_mux_i[7] = wbs7_ack_o & wb_slave_sel[7];
assign wbs_err_o_mux_i[7] = wbs7_err_o & wb_slave_sel[7];
assign wbs_rty_o_mux_i[7] = wbs7_rty_o & wb_slave_sel[7];
 
 
// Slave 8 inputs
assign wbs8_adr_i = wbm_adr_o;
assign wbs8_dat_i = wbm_dat_o;
assign wbs8_cyc_i = wbm_cyc_o & wb_slave_sel[8];
assign wbs8_stb_i = wbm_stb_o & wb_slave_sel[8];
assign wbs8_we_i = wbm_we_o;
assign wbs8_cti_i = wbm_cti_o;
assign wbs8_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[8] = wbs8_dat_o;
assign wbs_ack_o_mux_i[8] = wbs8_ack_o & wb_slave_sel[8];
assign wbs_err_o_mux_i[8] = wbs8_err_o & wb_slave_sel[8];
assign wbs_rty_o_mux_i[8] = wbs8_rty_o & wb_slave_sel[8];
 
 
// Slave 9 inputs
assign wbs9_adr_i = wbm_adr_o;
assign wbs9_dat_i = wbm_dat_o;
assign wbs9_cyc_i = wbm_cyc_o & wb_slave_sel[9];
assign wbs9_stb_i = wbm_stb_o & wb_slave_sel[9];
assign wbs9_we_i = wbm_we_o;
assign wbs9_cti_i = wbm_cti_o;
assign wbs9_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[9] = wbs9_dat_o;
assign wbs_ack_o_mux_i[9] = wbs9_ack_o & wb_slave_sel[9];
assign wbs_err_o_mux_i[9] = wbs9_err_o & wb_slave_sel[9];
assign wbs_rty_o_mux_i[9] = wbs9_rty_o & wb_slave_sel[9];
 
 
// Slave 10 inputs
assign wbs10_adr_i = wbm_adr_o;
assign wbs10_dat_i = wbm_dat_o;
assign wbs10_cyc_i = wbm_cyc_o & wb_slave_sel[10];
assign wbs10_stb_i = wbm_stb_o & wb_slave_sel[10];
assign wbs10_we_i = wbm_we_o;
assign wbs10_cti_i = wbm_cti_o;
assign wbs10_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[10] = wbs10_dat_o;
assign wbs_ack_o_mux_i[10] = wbs10_ack_o & wb_slave_sel[10];
assign wbs_err_o_mux_i[10] = wbs10_err_o & wb_slave_sel[10];
assign wbs_rty_o_mux_i[10] = wbs10_rty_o & wb_slave_sel[10];
 
// Slave 11 inputs
assign wbs11_adr_i = wbm_adr_o;
assign wbs11_dat_i = wbm_dat_o;
assign wbs11_cyc_i = wbm_cyc_o & wb_slave_sel[11];
assign wbs11_stb_i = wbm_stb_o & wb_slave_sel[11];
assign wbs11_we_i = wbm_we_o;
assign wbs11_cti_i = wbm_cti_o;
assign wbs11_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[11] = wbs11_dat_o;
assign wbs_ack_o_mux_i[11] = wbs11_ack_o & wb_slave_sel[11];
assign wbs_err_o_mux_i[11] = wbs11_err_o & wb_slave_sel[11];
assign wbs_rty_o_mux_i[11] = wbs11_rty_o & wb_slave_sel[11];
 
// Slave 12 inputs
assign wbs12_adr_i = wbm_adr_o;
assign wbs12_dat_i = wbm_dat_o;
assign wbs12_cyc_i = wbm_cyc_o & wb_slave_sel[12];
assign wbs12_stb_i = wbm_stb_o & wb_slave_sel[12];
assign wbs12_we_i = wbm_we_o;
assign wbs12_cti_i = wbm_cti_o;
assign wbs12_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[12] = wbs12_dat_o;
assign wbs_ack_o_mux_i[12] = wbs12_ack_o & wb_slave_sel[12];
assign wbs_err_o_mux_i[12] = wbs12_err_o & wb_slave_sel[12];
assign wbs_rty_o_mux_i[12] = wbs12_rty_o & wb_slave_sel[12];
 
 
// Slave 13 inputs
assign wbs13_adr_i = wbm_adr_o;
assign wbs13_dat_i = wbm_dat_o;
assign wbs13_cyc_i = wbm_cyc_o & wb_slave_sel[13];
assign wbs13_stb_i = wbm_stb_o & wb_slave_sel[13];
assign wbs13_we_i = wbm_we_o;
assign wbs13_cti_i = wbm_cti_o;
assign wbs13_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[13] = wbs13_dat_o;
assign wbs_ack_o_mux_i[13] = wbs13_ack_o & wb_slave_sel[13];
assign wbs_err_o_mux_i[13] = wbs13_err_o & wb_slave_sel[13];
assign wbs_rty_o_mux_i[13] = wbs13_rty_o & wb_slave_sel[13];
 
 
// Slave 14 inputs
assign wbs14_adr_i = wbm_adr_o;
assign wbs14_dat_i = wbm_dat_o;
assign wbs14_cyc_i = wbm_cyc_o & wb_slave_sel[14];
assign wbs14_stb_i = wbm_stb_o & wb_slave_sel[14];
assign wbs14_we_i = wbm_we_o;
assign wbs14_cti_i = wbm_cti_o;
assign wbs14_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[14] = wbs14_dat_o;
assign wbs_ack_o_mux_i[14] = wbs14_ack_o & wb_slave_sel[14];
assign wbs_err_o_mux_i[14] = wbs14_err_o & wb_slave_sel[14];
assign wbs_rty_o_mux_i[14] = wbs14_rty_o & wb_slave_sel[14];
 
 
// Slave 15 inputs
assign wbs15_adr_i = wbm_adr_o;
assign wbs15_dat_i = wbm_dat_o;
assign wbs15_cyc_i = wbm_cyc_o & wb_slave_sel[15];
assign wbs15_stb_i = wbm_stb_o & wb_slave_sel[15];
assign wbs15_we_i = wbm_we_o;
assign wbs15_cti_i = wbm_cti_o;
assign wbs15_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[15] = wbs15_dat_o;
assign wbs_ack_o_mux_i[15] = wbs15_ack_o & wb_slave_sel[15];
assign wbs_err_o_mux_i[15] = wbs15_err_o & wb_slave_sel[15];
assign wbs_rty_o_mux_i[15] = wbs15_rty_o & wb_slave_sel[15];
 
 
// Slave 16 inputs
assign wbs16_adr_i = wbm_adr_o;
assign wbs16_dat_i = wbm_dat_o;
assign wbs16_cyc_i = wbm_cyc_o & wb_slave_sel[16];
assign wbs16_stb_i = wbm_stb_o & wb_slave_sel[16];
assign wbs16_we_i = wbm_we_o;
assign wbs16_cti_i = wbm_cti_o;
assign wbs16_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[16] = wbs16_dat_o;
assign wbs_ack_o_mux_i[16] = wbs16_ack_o & wb_slave_sel[16];
assign wbs_err_o_mux_i[16] = wbs16_err_o & wb_slave_sel[16];
assign wbs_rty_o_mux_i[16] = wbs16_rty_o & wb_slave_sel[16];
 
 
// Slave 17 inputs
assign wbs17_adr_i = wbm_adr_o;
assign wbs17_dat_i = wbm_dat_o;
assign wbs17_cyc_i = wbm_cyc_o & wb_slave_sel[17];
assign wbs17_stb_i = wbm_stb_o & wb_slave_sel[17];
assign wbs17_we_i = wbm_we_o;
assign wbs17_cti_i = wbm_cti_o;
assign wbs17_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[17] = wbs17_dat_o;
assign wbs_ack_o_mux_i[17] = wbs17_ack_o & wb_slave_sel[17];
assign wbs_err_o_mux_i[17] = wbs17_err_o & wb_slave_sel[17];
assign wbs_rty_o_mux_i[17] = wbs17_rty_o & wb_slave_sel[17];
// Slave 18 inputs
assign wbs18_adr_i = wbm_adr_o;
assign wbs18_dat_i = wbm_dat_o;
assign wbs18_cyc_i = wbm_cyc_o & wb_slave_sel[18];
assign wbs18_stb_i = wbm_stb_o & wb_slave_sel[18];
assign wbs18_we_i = wbm_we_o;
assign wbs18_cti_i = wbm_cti_o;
assign wbs18_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[18] = wbs18_dat_o;
assign wbs_ack_o_mux_i[18] = wbs18_ack_o & wb_slave_sel[18];
assign wbs_err_o_mux_i[18] = wbs18_err_o & wb_slave_sel[18];
assign wbs_rty_o_mux_i[18] = wbs18_rty_o & wb_slave_sel[18];
// Slave 19 inputs
assign wbs19_adr_i = wbm_adr_o;
assign wbs19_dat_i = wbm_dat_o;
assign wbs19_cyc_i = wbm_cyc_o & wb_slave_sel[19];
assign wbs19_stb_i = wbm_stb_o & wb_slave_sel[19];
assign wbs19_we_i = wbm_we_o;
assign wbs19_cti_i = wbm_cti_o;
assign wbs19_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[19] = wbs19_dat_o;
assign wbs_ack_o_mux_i[19] = wbs19_ack_o & wb_slave_sel[19];
assign wbs_err_o_mux_i[19] = wbs19_err_o & wb_slave_sel[19];
assign wbs_rty_o_mux_i[19] = wbs19_rty_o & wb_slave_sel[19];
 
*/
 
 
 
// Master out mux from slave in data
assign wbm_dat_byte_i = wb_slave_sel[0] ? wbs_dat_o_mux_i[0] :
wb_slave_sel[1] ? wbs_dat_o_mux_i[1] :
wb_slave_sel[2] ? wbs_dat_o_mux_i[2] :
wb_slave_sel[3] ? wbs_dat_o_mux_i[3] :
wb_slave_sel[4] ? wbs_dat_o_mux_i[4] :
/*
wb_slave_sel[5] ? wbs_dat_o_mux_i[5] :
wb_slave_sel[6] ? wbs_dat_o_mux_i[6] :
wb_slave_sel[7] ? wbs_dat_o_mux_i[7] :
wb_slave_sel[8] ? wbs_dat_o_mux_i[8] :
wb_slave_sel[9] ? wbs_dat_o_mux_i[9] :
wb_slave_sel[10] ? wbs_dat_o_mux_i[10] :
wb_slave_sel[11] ? wbs_dat_o_mux_i[11] :
wb_slave_sel[12] ? wbs_dat_o_mux_i[12] :
wb_slave_sel[13] ? wbs_dat_o_mux_i[13] :
wb_slave_sel[14] ? wbs_dat_o_mux_i[14] :
wb_slave_sel[15] ? wbs_dat_o_mux_i[15] :
wb_slave_sel[16] ? wbs_dat_o_mux_i[16] :
wb_slave_sel[17] ? wbs_dat_o_mux_i[17] :
wb_slave_sel[18] ? wbs_dat_o_mux_i[18] :
wb_slave_sel[19] ? wbs_dat_o_mux_i[19] :
*/
wbs_dat_o_mux_i[0];
// Master out acks, or together
assign wbm_ack_i = wbs_ack_o_mux_i[0] |
wbs_ack_o_mux_i[1] |
wbs_ack_o_mux_i[2] |
wbs_ack_o_mux_i[3] |
wbs_ack_o_mux_i[4] /* |
wbs_ack_o_mux_i[5] |
wbs_ack_o_mux_i[6] |
wbs_ack_o_mux_i[7] |
wbs_ack_o_mux_i[8] |
wbs_ack_o_mux_i[9] |
wbs_ack_o_mux_i[10] |
wbs_ack_o_mux_i[11] |
wbs_ack_o_mux_i[12] |
wbs_ack_o_mux_i[13] |
wbs_ack_o_mux_i[14] |
wbs_ack_o_mux_i[15] |
wbs_ack_o_mux_i[16] |
wbs_ack_o_mux_i[17] |
wbs_ack_o_mux_i[18] |
wbs_ack_o_mux_i[19]
*/
;
 
assign wbm_err_i = wbs_err_o_mux_i[0] |
wbs_err_o_mux_i[1] |
wbs_err_o_mux_i[2] |
wbs_err_o_mux_i[3] |
wbs_err_o_mux_i[4] |/*
wbs_err_o_mux_i[5] |
wbs_err_o_mux_i[6] |
wbs_err_o_mux_i[7] |
wbs_err_o_mux_i[8] |
wbs_err_o_mux_i[9] |
wbs_err_o_mux_i[10] |
wbs_err_o_mux_i[11] |
wbs_err_o_mux_i[12] |
wbs_err_o_mux_i[13] |
wbs_err_o_mux_i[14] |
wbs_err_o_mux_i[15] |
wbs_err_o_mux_i[16] |
wbs_err_o_mux_i[17] |
wbs_err_o_mux_i[18] |
wbs_err_o_mux_i[19] |
*/
watchdog_err ;
 
assign wbm_rty_i = wbs_rty_o_mux_i[0] |
wbs_rty_o_mux_i[1] |
wbs_rty_o_mux_i[2] |
wbs_rty_o_mux_i[3] |
wbs_rty_o_mux_i[4] /*|
wbs_rty_o_mux_i[5] |
wbs_rty_o_mux_i[6] |
wbs_rty_o_mux_i[7] |
wbs_rty_o_mux_i[8] |
wbs_rty_o_mux_i[9] |
wbs_rty_o_mux_i[10] |
wbs_rty_o_mux_i[11] |
wbs_rty_o_mux_i[12] |
wbs_rty_o_mux_i[13] |
wbs_rty_o_mux_i[14] |
wbs_rty_o_mux_i[15] |
wbs_rty_o_mux_i[16] |
wbs_rty_o_mux_i[17] |
wbs_rty_o_mux_i[18] |
wbs_rty_o_mux_i[19]
*/
;
 
endmodule // arbiter_bytebus
/boards/xilinx/ml501/rtl/verilog/arbiter/arbiter_dbus.v
0,0 → 1,1268
//////////////////////////////////////////////////////////////////////
/// ////
/// Wishbone arbiter, burst-compatible ////
/// ////
/// Simple arbiter, multi-master, multi-slave with default slave ////
/// for chaining with peripheral arbiter ////
/// ////
/// Julius Baxter, julius@opencores.org ////
/// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2009, 2010 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
`include "orpsoc-defines.v"
// 2 Masters, a few slaves
module arbiter_dbus
(
// or1200 data master
// Wishbone Master interface
wbm0_adr_o,
wbm0_dat_o,
wbm0_sel_o,
wbm0_we_o,
wbm0_cyc_o,
wbm0_stb_o,
wbm0_cti_o,
wbm0_bte_o,
wbm0_dat_i,
wbm0_ack_i,
wbm0_err_i,
wbm0_rty_i,
 
// or1200 debug master
// Wishbone Master interface
wbm1_adr_o,
wbm1_dat_o,
wbm1_sel_o,
wbm1_we_o,
wbm1_cyc_o,
wbm1_stb_o,
wbm1_cti_o,
wbm1_bte_o,
wbm1_dat_i,
wbm1_ack_i,
wbm1_err_i,
wbm1_rty_i,
 
// Slave one
// Wishbone Slave interface
wbs0_adr_i,
wbs0_dat_i,
wbs0_sel_i,
wbs0_we_i,
wbs0_cyc_i,
wbs0_stb_i,
wbs0_cti_i,
wbs0_bte_i,
wbs0_dat_o,
wbs0_ack_o,
wbs0_err_o,
wbs0_rty_o,
 
// Slave two
// Wishbone Slave interface
wbs1_adr_i,
wbs1_dat_i,
wbs1_sel_i,
wbs1_we_i,
wbs1_cyc_i,
wbs1_stb_i,
wbs1_cti_i,
wbs1_bte_i,
wbs1_dat_o,
wbs1_ack_o,
wbs1_err_o,
wbs1_rty_o,
 
 
// Slave three
// Wishbone Slave interface
wbs2_adr_i,
wbs2_dat_i,
wbs2_sel_i,
wbs2_we_i,
wbs2_cyc_i,
wbs2_stb_i,
wbs2_cti_i,
wbs2_bte_i,
wbs2_dat_o,
wbs2_ack_o,
wbs2_err_o,
wbs2_rty_o,
/*
// Slave four
// Wishbone Slave interface
wbs3_adr_i,
wbs3_dat_i,
wbs3_sel_i,
wbs3_we_i,
wbs3_cyc_i,
wbs3_stb_i,
wbs3_cti_i,
wbs3_bte_i,
wbs3_dat_o,
wbs3_ack_o,
wbs3_err_o,
wbs3_rty_o,
 
// Slave five
// Wishbone Slave interface
wbs4_adr_i,
wbs4_dat_i,
wbs4_sel_i,
wbs4_we_i,
wbs4_cyc_i,
wbs4_stb_i,
wbs4_cti_i,
wbs4_bte_i,
wbs4_dat_o,
wbs4_ack_o,
wbs4_err_o,
wbs4_rty_o,
 
// Slave six
// Wishbone Slave interface
wbs5_adr_i,
wbs5_dat_i,
wbs5_sel_i,
wbs5_we_i,
wbs5_cyc_i,
wbs5_stb_i,
wbs5_cti_i,
wbs5_bte_i,
wbs5_dat_o,
wbs5_ack_o,
wbs5_err_o,
wbs5_rty_o,
 
// Slave seven
// Wishbone Slave interface
wbs6_adr_i,
wbs6_dat_i,
wbs6_sel_i,
wbs6_we_i,
wbs6_cyc_i,
wbs6_stb_i,
wbs6_cti_i,
wbs6_bte_i,
wbs6_dat_o,
wbs6_ack_o,
wbs6_err_o,
wbs6_rty_o,
 
// Slave eight
// Wishbone Slave interface
wbs7_adr_i,
wbs7_dat_i,
wbs7_sel_i,
wbs7_we_i,
wbs7_cyc_i,
wbs7_stb_i,
wbs7_cti_i,
wbs7_bte_i,
wbs7_dat_o,
wbs7_ack_o,
wbs7_err_o,
wbs7_rty_o,
 
// Slave nine
// Wishbone Slave interface
wbs8_adr_i,
wbs8_dat_i,
wbs8_sel_i,
wbs8_we_i,
wbs8_cyc_i,
wbs8_stb_i,
wbs8_cti_i,
wbs8_bte_i,
wbs8_dat_o,
wbs8_ack_o,
wbs8_err_o,
wbs8_rty_o,
 
// Slave ten
// Wishbone Slave interface
wbs9_adr_i,
wbs9_dat_i,
wbs9_sel_i,
wbs9_we_i,
wbs9_cyc_i,
wbs9_stb_i,
wbs9_cti_i,
wbs9_bte_i,
wbs9_dat_o,
wbs9_ack_o,
wbs9_err_o,
wbs9_rty_o,
 
// Slave eleven
// Wishbone Slave interface
wbs10_adr_i,
wbs10_dat_i,
wbs10_sel_i,
wbs10_we_i,
wbs10_cyc_i,
wbs10_stb_i,
wbs10_cti_i,
wbs10_bte_i,
wbs10_dat_o,
wbs10_ack_o,
wbs10_err_o,
wbs10_rty_o,
 
// Slave twelve
// Wishbone Slave interface
wbs11_adr_i,
wbs11_dat_i,
wbs11_sel_i,
wbs11_we_i,
wbs11_cyc_i,
wbs11_stb_i,
wbs11_cti_i,
wbs11_bte_i,
wbs11_dat_o,
wbs11_ack_o,
wbs11_err_o,
wbs11_rty_o,
 
// Slave thirteen
// Wishbone Slave interface
wbs12_adr_i,
wbs12_dat_i,
wbs12_sel_i,
wbs12_we_i,
wbs12_cyc_i,
wbs12_stb_i,
wbs12_cti_i,
wbs12_bte_i,
wbs12_dat_o,
wbs12_ack_o,
wbs12_err_o,
wbs12_rty_o,
 
// Slave fourteen
// Wishbone Slave interface
wbs13_adr_i,
wbs13_dat_i,
wbs13_sel_i,
wbs13_we_i,
wbs13_cyc_i,
wbs13_stb_i,
wbs13_cti_i,
wbs13_bte_i,
wbs13_dat_o,
wbs13_ack_o,
wbs13_err_o,
wbs13_rty_o,
 
// Slave fifteen
// Wishbone Slave interface
wbs14_adr_i,
wbs14_dat_i,
wbs14_sel_i,
wbs14_we_i,
wbs14_cyc_i,
wbs14_stb_i,
wbs14_cti_i,
wbs14_bte_i,
wbs14_dat_o,
wbs14_ack_o,
wbs14_err_o,
wbs14_rty_o,
 
// Slave sixteen
// Wishbone Slave interface
wbs15_adr_i,
wbs15_dat_i,
wbs15_sel_i,
wbs15_we_i,
wbs15_cyc_i,
wbs15_stb_i,
wbs15_cti_i,
wbs15_bte_i,
wbs15_dat_o,
wbs15_ack_o,
wbs15_err_o,
wbs15_rty_o,
 
// Slave seventeen
// Wishbone Slave interface
wbs16_adr_i,
wbs16_dat_i,
wbs16_sel_i,
wbs16_we_i,
wbs16_cyc_i,
wbs16_stb_i,
wbs16_cti_i,
wbs16_bte_i,
wbs16_dat_o,
wbs16_ack_o,
wbs16_err_o,
wbs16_rty_o,
*/
wb_clk,
wb_rst
);
 
parameter wb_dat_width = 32;
parameter wb_adr_width = 32;
 
parameter wb_addr_match_width = 8;
 
parameter wb_num_slaves = 2; // must also (un)comment things if changing
 
// Slave addresses - these should be defparam'd from top level
// Declare them as you need them
parameter slave0_adr = 0;
parameter slave1_adr = 0;
parameter slave2_adr = 0;
parameter slave3_adr = 0;
parameter slave4_adr = 0;
parameter slave5_adr = 0;
parameter slave6_adr = 0;
parameter slave7_adr = 0;
parameter slave8_adr = 0;
parameter slave9_adr = 0;
parameter slave10_adr = 0;
parameter slave11_adr = 0;
parameter slave12_adr = 0;
 
// Select for slave 0
`define WB_ARB_ADDR_MATCH_SEL_SLAVE0 wb_adr_width-1:wb_adr_width-4
`define WB_ARB_ADDR_MATCH_SEL wb_adr_width-1:wb_adr_width-wb_addr_match_width
 
input wb_clk;
input wb_rst;
// WB Master one
input [wb_adr_width-1:0] wbm0_adr_o;
input [wb_dat_width-1:0] wbm0_dat_o;
input [3:0] wbm0_sel_o;
input wbm0_we_o;
input wbm0_cyc_o;
input wbm0_stb_o;
input [2:0] wbm0_cti_o;
input [1:0] wbm0_bte_o;
output [wb_dat_width-1:0] wbm0_dat_i;
output wbm0_ack_i;
output wbm0_err_i;
output wbm0_rty_i;
input [wb_adr_width-1:0] wbm1_adr_o;
input [wb_dat_width-1:0] wbm1_dat_o;
input [3:0] wbm1_sel_o;
input wbm1_we_o;
input wbm1_cyc_o;
input wbm1_stb_o;
input [2:0] wbm1_cti_o;
input [1:0] wbm1_bte_o;
output [wb_dat_width-1:0] wbm1_dat_i;
output wbm1_ack_i;
output wbm1_err_i;
output wbm1_rty_i;
 
// Slave one
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs0_adr_i;
output [wb_dat_width-1:0] wbs0_dat_i;
output [3:0] wbs0_sel_i;
output wbs0_we_i;
output wbs0_cyc_i;
output wbs0_stb_i;
output [2:0] wbs0_cti_i;
output [1:0] wbs0_bte_i;
input [wb_dat_width-1:0] wbs0_dat_o;
input wbs0_ack_o;
input wbs0_err_o;
input wbs0_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs1_adr_i;
output [wb_dat_width-1:0] wbs1_dat_i;
output [3:0] wbs1_sel_i;
output wbs1_we_i;
output wbs1_cyc_i;
output wbs1_stb_i;
output [2:0] wbs1_cti_i;
output [1:0] wbs1_bte_i;
input [wb_dat_width-1:0] wbs1_dat_o;
input wbs1_ack_o;
input wbs1_err_o;
input wbs1_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs2_adr_i;
output [wb_dat_width-1:0] wbs2_dat_i;
output [3:0] wbs2_sel_i;
output wbs2_we_i;
output wbs2_cyc_i;
output wbs2_stb_i;
output [2:0] wbs2_cti_i;
output [1:0] wbs2_bte_i;
input [wb_dat_width-1:0] wbs2_dat_o;
input wbs2_ack_o;
input wbs2_err_o;
input wbs2_rty_o;
/*
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs3_adr_i;
output [wb_dat_width-1:0] wbs3_dat_i;
output [3:0] wbs3_sel_i;
output wbs3_we_i;
output wbs3_cyc_i;
output wbs3_stb_i;
output [2:0] wbs3_cti_i;
output [1:0] wbs3_bte_i;
input [wb_dat_width-1:0] wbs3_dat_o;
input wbs3_ack_o;
input wbs3_err_o;
input wbs3_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs4_adr_i;
output [wb_dat_width-1:0] wbs4_dat_i;
output [3:0] wbs4_sel_i;
output wbs4_we_i;
output wbs4_cyc_i;
output wbs4_stb_i;
output [2:0] wbs4_cti_i;
output [1:0] wbs4_bte_i;
input [wb_dat_width-1:0] wbs4_dat_o;
input wbs4_ack_o;
input wbs4_err_o;
input wbs4_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs5_adr_i;
output [wb_dat_width-1:0] wbs5_dat_i;
output [3:0] wbs5_sel_i;
output wbs5_we_i;
output wbs5_cyc_i;
output wbs5_stb_i;
output [2:0] wbs5_cti_i;
output [1:0] wbs5_bte_i;
input [wb_dat_width-1:0] wbs5_dat_o;
input wbs5_ack_o;
input wbs5_err_o;
input wbs5_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs6_adr_i;
output [wb_dat_width-1:0] wbs6_dat_i;
output [3:0] wbs6_sel_i;
output wbs6_we_i;
output wbs6_cyc_i;
output wbs6_stb_i;
output [2:0] wbs6_cti_i;
output [1:0] wbs6_bte_i;
input [wb_dat_width-1:0] wbs6_dat_o;
input wbs6_ack_o;
input wbs6_err_o;
input wbs6_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs7_adr_i;
output [wb_dat_width-1:0] wbs7_dat_i;
output [3:0] wbs7_sel_i;
output wbs7_we_i;
output wbs7_cyc_i;
output wbs7_stb_i;
output [2:0] wbs7_cti_i;
output [1:0] wbs7_bte_i;
input [wb_dat_width-1:0] wbs7_dat_o;
input wbs7_ack_o;
input wbs7_err_o;
input wbs7_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs8_adr_i;
output [wb_dat_width-1:0] wbs8_dat_i;
output [3:0] wbs8_sel_i;
output wbs8_we_i;
output wbs8_cyc_i;
output wbs8_stb_i;
output [2:0] wbs8_cti_i;
output [1:0] wbs8_bte_i;
input [wb_dat_width-1:0] wbs8_dat_o;
input wbs8_ack_o;
input wbs8_err_o;
input wbs8_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs9_adr_i;
output [wb_dat_width-1:0] wbs9_dat_i;
output [3:0] wbs9_sel_i;
output wbs9_we_i;
output wbs9_cyc_i;
output wbs9_stb_i;
output [2:0] wbs9_cti_i;
output [1:0] wbs9_bte_i;
input [wb_dat_width-1:0] wbs9_dat_o;
input wbs9_ack_o;
input wbs9_err_o;
input wbs9_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs10_adr_i;
output [wb_dat_width-1:0] wbs10_dat_i;
output [3:0] wbs10_sel_i;
output wbs10_we_i;
output wbs10_cyc_i;
output wbs10_stb_i;
output [2:0] wbs10_cti_i;
output [1:0] wbs10_bte_i;
input [wb_dat_width-1:0] wbs10_dat_o;
input wbs10_ack_o;
input wbs10_err_o;
input wbs10_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs11_adr_i;
output [wb_dat_width-1:0] wbs11_dat_i;
output [3:0] wbs11_sel_i;
output wbs11_we_i;
output wbs11_cyc_i;
output wbs11_stb_i;
output [2:0] wbs11_cti_i;
output [1:0] wbs11_bte_i;
input [wb_dat_width-1:0] wbs11_dat_o;
input wbs11_ack_o;
input wbs11_err_o;
input wbs11_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs12_adr_i;
output [wb_dat_width-1:0] wbs12_dat_i;
output [3:0] wbs12_sel_i;
output wbs12_we_i;
output wbs12_cyc_i;
output wbs12_stb_i;
output [2:0] wbs12_cti_i;
output [1:0] wbs12_bte_i;
input [wb_dat_width-1:0] wbs12_dat_o;
input wbs12_ack_o;
input wbs12_err_o;
input wbs12_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs13_adr_i;
output [wb_dat_width-1:0] wbs13_dat_i;
output [3:0] wbs13_sel_i;
output wbs13_we_i;
output wbs13_cyc_i;
output wbs13_stb_i;
output [2:0] wbs13_cti_i;
output [1:0] wbs13_bte_i;
input [wb_dat_width-1:0] wbs13_dat_o;
input wbs13_ack_o;
input wbs13_err_o;
input wbs13_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs14_adr_i;
output [wb_dat_width-1:0] wbs14_dat_i;
output [3:0] wbs14_sel_i;
output wbs14_we_i;
output wbs14_cyc_i;
output wbs14_stb_i;
output [2:0] wbs14_cti_i;
output [1:0] wbs14_bte_i;
input [wb_dat_width-1:0] wbs14_dat_o;
input wbs14_ack_o;
input wbs14_err_o;
input wbs14_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs15_adr_i;
output [wb_dat_width-1:0] wbs15_dat_i;
output [3:0] wbs15_sel_i;
output wbs15_we_i;
output wbs15_cyc_i;
output wbs15_stb_i;
output [2:0] wbs15_cti_i;
output [1:0] wbs15_bte_i;
input [wb_dat_width-1:0] wbs15_dat_o;
input wbs15_ack_o;
input wbs15_err_o;
input wbs15_rty_o;
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs16_adr_i;
output [wb_dat_width-1:0] wbs16_dat_i;
output [3:0] wbs16_sel_i;
output wbs16_we_i;
output wbs16_cyc_i;
output wbs16_stb_i;
output [2:0] wbs16_cti_i;
output [1:0] wbs16_bte_i;
input [wb_dat_width-1:0] wbs16_dat_o;
input wbs16_ack_o;
input wbs16_err_o;
input wbs16_rty_o;
*/
 
reg watchdog_err;
`ifdef ARBITER_DBUS_REGISTERING
 
// Registering setup:
// Masters typically register their outputs, so do the master selection and
// muxing before registering in the arbiter. Keep the common parts outside
// for code brevity.
// Master ins -> |MUX> -> these wires
wire [wb_adr_width-1:0] wbm_adr_o_w;
wire [wb_dat_width-1:0] wbm_dat_o_w;
wire [3:0] wbm_sel_o_w;
wire wbm_we_o_w;
wire wbm_cyc_o_w;
wire wbm_stb_o_w;
wire [2:0] wbm_cti_o_w;
wire [1:0] wbm_bte_o_w;
// Slave ins -> |MUX> -> these wires
wire [wb_dat_width-1:0] wbm_dat_i;
wire wbm_ack_i;
wire wbm_err_i;
wire wbm_rty_i;
 
// Registers after masters input mux
reg [wb_adr_width-1:0] wbm_adr_o_r;
reg [wb_dat_width-1:0] wbm_dat_o_r;
reg [3:0] wbm_sel_o_r;
reg wbm_we_o_r;
reg wbm_cyc_o_r;
reg wbm_stb_o_r;
reg [2:0] wbm_cti_o_r;
reg [1:0] wbm_bte_o_r;
 
// Master input mux register wires
wire [wb_adr_width-1:0] wbm_adr_o;
wire [wb_dat_width-1:0] wbm_dat_o;
wire [3:0] wbm_sel_o;
wire wbm_we_o;
wire wbm_cyc_o;
wire wbm_stb_o;
wire [2:0] wbm_cti_o;
wire [1:0] wbm_bte_o;
 
// Registers after slaves input mux
reg [wb_dat_width-1:0] wbm_dat_i_r;
reg wbm_ack_i_r;
reg wbm_err_i_r;
reg wbm_rty_i_r;
 
// Master select (MUX controls)
wire [1:0] master_sel;
// priority to wbm1, the debug master
assign master_sel[0] = wbm0_cyc_o & !wbm1_cyc_o;
assign master_sel[1] = wbm1_cyc_o;
 
 
// Master input mux, priority to debug master
assign wbm_adr_o_w = master_sel[1] ? wbm1_adr_o :
wbm0_adr_o;
assign wbm_dat_o_w = master_sel[1] ? wbm1_dat_o :
wbm0_dat_o;
assign wbm_sel_o_w = master_sel[1] ? wbm1_sel_o :
wbm0_sel_o;
 
assign wbm_we_o_w = master_sel[1] ? wbm1_we_o :
wbm0_we_o;
assign wbm_cyc_o_w = master_sel[1] ? wbm1_cyc_o :
wbm0_cyc_o;
 
assign wbm_stb_o_w = master_sel[1] ? wbm1_stb_o :
wbm0_stb_o;
 
assign wbm_cti_o_w = master_sel[1] ? wbm1_cti_o :
wbm0_cti_o;
 
assign wbm_bte_o_w = master_sel[1] ? wbm1_bte_o :
wbm0_bte_o;
 
// Register muxed master signals
always @(posedge wb_clk)
begin
wbm_adr_o_r <= wbm_adr_o_w;
wbm_dat_o_r <= wbm_dat_o_w;
wbm_sel_o_r <= wbm_sel_o_w;
wbm_we_o_r <= wbm_we_o_w;
wbm_cyc_o_r <= wbm_cyc_o_w;
wbm_stb_o_r <= wbm_stb_o_w & !wbm_ack_i & !wbm_ack_i_r;
wbm_cti_o_r <= wbm_cti_o_w;
wbm_bte_o_r <= wbm_bte_o_w;
wbm_dat_i_r <= wbm_dat_i;
wbm_ack_i_r <= wbm_ack_i;
wbm_err_i_r <= wbm_err_i;
wbm_rty_i_r <= wbm_rty_i;
end // always @ (posedge wb_clk)
 
assign wbm_adr_o = wbm_adr_o_r;
assign wbm_dat_o = wbm_dat_o_r;
assign wbm_sel_o = wbm_sel_o_r;
assign wbm_we_o = wbm_we_o_r;
assign wbm_cyc_o = wbm_cyc_o_r;
assign wbm_stb_o = wbm_stb_o_r;
assign wbm_cti_o = wbm_cti_o_r;
assign wbm_bte_o = wbm_bte_o_r;
 
// Master input mux, priority to debug master
assign wbm0_dat_i = wbm_dat_i_r;
assign wbm0_ack_i = wbm_ack_i_r & master_sel[0];
assign wbm0_err_i = wbm_err_i_r & master_sel[0];
assign wbm0_rty_i = wbm_rty_i_r & master_sel[0];
assign wbm1_dat_i = wbm_dat_i_r;
assign wbm1_ack_i = wbm_ack_i_r & master_sel[1];
assign wbm1_err_i = wbm_err_i_r & master_sel[1];
assign wbm1_rty_i = wbm_rty_i_r & master_sel[1];
`else // !`ifdef ARBITER_DBUS_REGISTERING
 
// Master input mux output wires
wire [wb_adr_width-1:0] wbm_adr_o;
wire [wb_dat_width-1:0] wbm_dat_o;
wire [3:0] wbm_sel_o;
wire wbm_we_o;
wire wbm_cyc_o;
wire wbm_stb_o;
wire [2:0] wbm_cti_o;
wire [1:0] wbm_bte_o;
// Master select
wire [1:0] master_sel;
// priority to wbm1, the debug master
assign master_sel[0] = wbm0_cyc_o & !wbm1_cyc_o;
assign master_sel[1] = wbm1_cyc_o;
 
 
// Master input mux, priority to debug master
assign wbm_adr_o = master_sel[1] ? wbm1_adr_o :
wbm0_adr_o;
assign wbm_dat_o = master_sel[1] ? wbm1_dat_o :
wbm0_dat_o;
assign wbm_sel_o = master_sel[1] ? wbm1_sel_o :
wbm0_sel_o;
 
assign wbm_we_o = master_sel[1] ? wbm1_we_o :
wbm0_we_o;
assign wbm_cyc_o = master_sel[1] ? wbm1_cyc_o :
wbm0_cyc_o;
 
assign wbm_stb_o = master_sel[1] ? wbm1_stb_o :
wbm0_stb_o;
 
assign wbm_cti_o = master_sel[1] ? wbm1_cti_o :
wbm0_cti_o;
 
assign wbm_bte_o = master_sel[1] ? wbm1_bte_o :
wbm0_bte_o;
 
 
wire [wb_dat_width-1:0] wbm_dat_i;
wire wbm_ack_i;
wire wbm_err_i;
wire wbm_rty_i;
 
 
assign wbm0_dat_i = wbm_dat_i;
assign wbm0_ack_i = wbm_ack_i & master_sel[0];
assign wbm0_err_i = wbm_err_i & master_sel[0];
assign wbm0_rty_i = wbm_rty_i & master_sel[0];
assign wbm1_dat_i = wbm_dat_i;
assign wbm1_ack_i = wbm_ack_i & master_sel[1];
assign wbm1_err_i = wbm_err_i & master_sel[1];
assign wbm1_rty_i = wbm_rty_i & master_sel[1];
 
 
`endif // !`ifdef ARBITER_DBUS_REGISTERING
 
// Slave select wire
wire [wb_num_slaves-1:0] wb_slave_sel;
reg [wb_num_slaves-1:0] wb_slave_sel_r;
 
// Register wb_slave_sel_r to break combinatorial loop when selecting default
// slave
always @(posedge wb_clk)
wb_slave_sel_r <= wb_slave_sel;
// Slave out mux in wires
wire [wb_dat_width-1:0] wbs_dat_o_mux_i [0:wb_num_slaves-1];
wire wbs_ack_o_mux_i [0:wb_num_slaves-1];
wire wbs_err_o_mux_i [0:wb_num_slaves-1];
wire wbs_rty_o_mux_i [0:wb_num_slaves-1];
 
//
// Slave selects
//
assign wb_slave_sel[0] = wbm_adr_o[31:28] == slave0_adr | wbm_adr_o[31:28] == 4'hf; // Special case, point all reads to ROM address to here
assign wb_slave_sel[1] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave1_adr;
// Auto select last slave when others are not selected
assign wb_slave_sel[2] = !(wb_slave_sel_r[0] | wb_slave_sel_r[1]);
 
/*
assign wb_slave_sel[2] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave2_adr;
assign wb_slave_sel[3] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave3_adr;
assign wb_slave_sel[4] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave4_adr;
assign wb_slave_sel[5] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave5_adr;
assign wb_slave_sel[6] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave6_adr;
assign wb_slave_sel[7] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave7_adr;
assign wb_slave_sel[8] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave8_adr;
assign wb_slave_sel[9] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave9_adr;
assign wb_slave_sel[10] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave10_adr;
assign wb_slave_sel[11] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave11_adr;
assign wb_slave_sel[12] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave12_adr;
assign wb_slave_sel[13] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave13_adr;
assign wb_slave_sel[14] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave14_adr;
assign wb_slave_sel[15] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave15_adr;
assign wb_slave_sel[16] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave16_adr;
*/
 
`ifdef ARBITER_DBUS_WATCHDOG
reg [`ARBITER_DBUS_WATCHDOG_TIMER_WIDTH:0] watchdog_timer;
reg wbm_stb_r; // Register strobe
wire wbm_stb_edge; // Detect its edge
 
always @(posedge wb_clk)
wbm_stb_r <= wbm_stb_o;
 
assign wbm_stb_edge = (wbm_stb_o & !wbm_stb_r);
// Counter logic
always @(posedge wb_clk)
if (wb_rst) watchdog_timer <= 0;
else if (wbm_ack_i) // When we see an ack, turn off timer
watchdog_timer <= 0;
else if (wbm_stb_edge) // New access means start timer again
watchdog_timer <= 1;
else if (|watchdog_timer) // Continue counting if counter > 0
watchdog_timer <= watchdog_timer + 1;
 
always @(posedge wb_clk)
watchdog_err <= (&watchdog_timer);
 
`else // !`ifdef ARBITER_DBUS_WATCHDOG
always @(posedge wb_clk)
watchdog_err <= 0;
`endif // !`ifdef ARBITER_DBUS_WATCHDOG
 
// Slave 0 inputs
assign wbs0_adr_i = wbm_adr_o;
assign wbs0_dat_i = wbm_dat_o;
assign wbs0_sel_i = wbm_sel_o;
assign wbs0_cyc_i = wbm_cyc_o & wb_slave_sel_r[0];
assign wbs0_stb_i = wbm_stb_o & wb_slave_sel_r[0];
assign wbs0_we_i = wbm_we_o;
assign wbs0_cti_i = wbm_cti_o;
assign wbs0_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[0] = wbs0_dat_o;
assign wbs_ack_o_mux_i[0] = wbs0_ack_o & wb_slave_sel_r[0];
assign wbs_err_o_mux_i[0] = wbs0_err_o & wb_slave_sel_r[0];
assign wbs_rty_o_mux_i[0] = wbs0_rty_o & wb_slave_sel_r[0];
 
 
// Slave 1 inputs
assign wbs1_adr_i = wbm_adr_o;
assign wbs1_dat_i = wbm_dat_o;
assign wbs1_sel_i = wbm_sel_o;
assign wbs1_cyc_i = wbm_cyc_o & wb_slave_sel_r[1];
assign wbs1_stb_i = wbm_stb_o & wb_slave_sel_r[1];
assign wbs1_we_i = wbm_we_o;
assign wbs1_cti_i = wbm_cti_o;
assign wbs1_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[1] = wbs1_dat_o;
assign wbs_ack_o_mux_i[1] = wbs1_ack_o & wb_slave_sel_r[1];
assign wbs_err_o_mux_i[1] = wbs1_err_o & wb_slave_sel_r[1];
assign wbs_rty_o_mux_i[1] = wbs1_rty_o & wb_slave_sel_r[1];
 
 
// Slave 2 inputs
assign wbs2_adr_i = wbm_adr_o;
assign wbs2_dat_i = wbm_dat_o;
assign wbs2_sel_i = wbm_sel_o;
assign wbs2_cyc_i = wbm_cyc_o & wb_slave_sel_r[2];
assign wbs2_stb_i = wbm_stb_o & wb_slave_sel_r[2];
assign wbs2_we_i = wbm_we_o;
assign wbs2_cti_i = wbm_cti_o;
assign wbs2_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[2] = wbs2_dat_o;
assign wbs_ack_o_mux_i[2] = wbs2_ack_o & wb_slave_sel_r[2];
assign wbs_err_o_mux_i[2] = wbs2_err_o & wb_slave_sel_r[2];
assign wbs_rty_o_mux_i[2] = wbs2_rty_o & wb_slave_sel_r[2];
/*
 
// Slave 3 inputs
assign wbs3_adr_i = wbm_adr_o;
assign wbs3_dat_i = wbm_dat_o;
assign wbs3_sel_i = wbm_sel_o;
assign wbs3_cyc_i = wbm_cyc_o & wb_slave_sel_r[3];
assign wbs3_stb_i = wbm_stb_o & wb_slave_sel_r[3];
assign wbs3_we_i = wbm_we_o;
assign wbs3_cti_i = wbm_cti_o;
assign wbs3_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[3] = wbs3_dat_o;
assign wbs_ack_o_mux_i[3] = wbs3_ack_o & wb_slave_sel_r[3];
assign wbs_err_o_mux_i[3] = wbs3_err_o & wb_slave_sel_r[3];
assign wbs_rty_o_mux_i[3] = wbs3_rty_o & wb_slave_sel_r[3];
 
// Slave 4 inputs
assign wbs4_adr_i = wbm_adr_o;
assign wbs4_dat_i = wbm_dat_o;
assign wbs4_sel_i = wbm_sel_o;
assign wbs4_cyc_i = wbm_cyc_o & wb_slave_sel_r[4];
assign wbs4_stb_i = wbm_stb_o & wb_slave_sel_r[4];
assign wbs4_we_i = wbm_we_o;
assign wbs4_cti_i = wbm_cti_o;
assign wbs4_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[4] = wbs4_dat_o;
assign wbs_ack_o_mux_i[4] = wbs4_ack_o & wb_slave_sel_r[4];
assign wbs_err_o_mux_i[4] = wbs4_err_o & wb_slave_sel_r[4];
assign wbs_rty_o_mux_i[4] = wbs4_rty_o & wb_slave_sel_r[4];
 
 
// Slave 5 inputs
assign wbs5_adr_i = wbm_adr_o;
assign wbs5_dat_i = wbm_dat_o;
assign wbs5_sel_i = wbm_sel_o;
assign wbs5_cyc_i = wbm_cyc_o & wb_slave_sel_r[5];
assign wbs5_stb_i = wbm_stb_o & wb_slave_sel_r[5];
assign wbs5_we_i = wbm_we_o;
assign wbs5_cti_i = wbm_cti_o;
assign wbs5_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[5] = wbs5_dat_o;
assign wbs_ack_o_mux_i[5] = wbs5_ack_o & wb_slave_sel_r[5];
assign wbs_err_o_mux_i[5] = wbs5_err_o & wb_slave_sel_r[5];
assign wbs_rty_o_mux_i[5] = wbs5_rty_o & wb_slave_sel_r[5];
 
 
// Slave 6 inputs
assign wbs6_adr_i = wbm_adr_o;
assign wbs6_dat_i = wbm_dat_o;
assign wbs6_sel_i = wbm_sel_o;
assign wbs6_cyc_i = wbm_cyc_o & wb_slave_sel_r[6];
assign wbs6_stb_i = wbm_stb_o & wb_slave_sel_r[6];
assign wbs6_we_i = wbm_we_o;
assign wbs6_cti_i = wbm_cti_o;
assign wbs6_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[6] = wbs6_dat_o;
assign wbs_ack_o_mux_i[6] = wbs6_ack_o & wb_slave_sel_r[6];
assign wbs_err_o_mux_i[6] = wbs6_err_o & wb_slave_sel_r[6];
assign wbs_rty_o_mux_i[6] = wbs6_rty_o & wb_slave_sel_r[6];
 
 
// Slave 7 inputs
assign wbs7_adr_i = wbm_adr_o;
assign wbs7_dat_i = wbm_dat_o;
assign wbs7_sel_i = wbm_sel_o;
assign wbs7_cyc_i = wbm_cyc_o & wb_slave_sel_r[7];
assign wbs7_stb_i = wbm_stb_o & wb_slave_sel_r[7];
assign wbs7_we_i = wbm_we_o;
assign wbs7_cti_i = wbm_cti_o;
assign wbs7_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[7] = wbs7_dat_o;
assign wbs_ack_o_mux_i[7] = wbs7_ack_o & wb_slave_sel_r[7];
assign wbs_err_o_mux_i[7] = wbs7_err_o & wb_slave_sel_r[7];
assign wbs_rty_o_mux_i[7] = wbs7_rty_o & wb_slave_sel_r[7];
 
 
// Slave 8 inputs
assign wbs8_adr_i = wbm_adr_o;
assign wbs8_dat_i = wbm_dat_o;
assign wbs8_sel_i = wbm_sel_o;
assign wbs8_cyc_i = wbm_cyc_o & wb_slave_sel_r[8];
assign wbs8_stb_i = wbm_stb_o & wb_slave_sel_r[8];
assign wbs8_we_i = wbm_we_o;
assign wbs8_cti_i = wbm_cti_o;
assign wbs8_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[8] = wbs8_dat_o;
assign wbs_ack_o_mux_i[8] = wbs8_ack_o & wb_slave_sel_r[8];
assign wbs_err_o_mux_i[8] = wbs8_err_o & wb_slave_sel_r[8];
assign wbs_rty_o_mux_i[8] = wbs8_rty_o & wb_slave_sel_r[8];
 
 
// Slave 9 inputs
assign wbs9_adr_i = wbm_adr_o;
assign wbs9_dat_i = wbm_dat_o;
assign wbs9_sel_i = wbm_sel_o;
assign wbs9_cyc_i = wbm_cyc_o & wb_slave_sel_r[9];
assign wbs9_stb_i = wbm_stb_o & wb_slave_sel_r[9];
assign wbs9_we_i = wbm_we_o;
assign wbs9_cti_i = wbm_cti_o;
assign wbs9_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[9] = wbs9_dat_o;
assign wbs_ack_o_mux_i[9] = wbs9_ack_o & wb_slave_sel_r[9];
assign wbs_err_o_mux_i[9] = wbs9_err_o & wb_slave_sel_r[9];
assign wbs_rty_o_mux_i[9] = wbs9_rty_o & wb_slave_sel_r[9];
 
 
// Slave 10 inputs
assign wbs10_adr_i = wbm_adr_o;
assign wbs10_dat_i = wbm_dat_o;
assign wbs10_sel_i = wbm_sel_o;
assign wbs10_cyc_i = wbm_cyc_o & wb_slave_sel_r[10];
assign wbs10_stb_i = wbm_stb_o & wb_slave_sel_r[10];
assign wbs10_we_i = wbm_we_o;
assign wbs10_cti_i = wbm_cti_o;
assign wbs10_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[10] = wbs10_dat_o;
assign wbs_ack_o_mux_i[10] = wbs10_ack_o & wb_slave_sel_r[10];
assign wbs_err_o_mux_i[10] = wbs10_err_o & wb_slave_sel_r[10];
assign wbs_rty_o_mux_i[10] = wbs10_rty_o & wb_slave_sel_r[10];
 
// Slave 11 inputs
assign wbs11_adr_i = wbm_adr_o;
assign wbs11_dat_i = wbm_dat_o;
assign wbs11_sel_i = wbm_sel_o;
assign wbs11_cyc_i = wbm_cyc_o & wb_slave_sel_r[11];
assign wbs11_stb_i = wbm_stb_o & wb_slave_sel_r[11];
assign wbs11_we_i = wbm_we_o;
assign wbs11_cti_i = wbm_cti_o;
assign wbs11_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[11] = wbs11_dat_o;
assign wbs_ack_o_mux_i[11] = wbs11_ack_o & wb_slave_sel_r[11];
assign wbs_err_o_mux_i[11] = wbs11_err_o & wb_slave_sel_r[11];
assign wbs_rty_o_mux_i[11] = wbs11_rty_o & wb_slave_sel_r[11];
 
 
// Slave 12 inputs
assign wbs12_adr_i = wbm_adr_o;
assign wbs12_dat_i = wbm_dat_o;
assign wbs12_sel_i = wbm_sel_o;
assign wbs12_cyc_i = wbm_cyc_o & wb_slave_sel_r[12];
assign wbs12_stb_i = wbm_stb_o & wb_slave_sel_r[12];
assign wbs12_we_i = wbm_we_o;
assign wbs12_cti_i = wbm_cti_o;
assign wbs12_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[12] = wbs12_dat_o;
assign wbs_ack_o_mux_i[12] = wbs12_ack_o & wb_slave_sel_r[12];
assign wbs_err_o_mux_i[12] = wbs12_err_o & wb_slave_sel_r[12];
assign wbs_rty_o_mux_i[12] = wbs12_rty_o & wb_slave_sel_r[12];
 
 
// Slave 13 inputs
assign wbs13_adr_i = wbm_adr_o;
assign wbs13_dat_i = wbm_dat_o;
assign wbs13_sel_i = wbm_sel_o;
assign wbs13_cyc_i = wbm_cyc_o & wb_slave_sel_r[13];
assign wbs13_stb_i = wbm_stb_o & wb_slave_sel_r[13];
assign wbs13_we_i = wbm_we_o;
assign wbs13_cti_i = wbm_cti_o;
assign wbs13_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[13] = wbs13_dat_o;
assign wbs_ack_o_mux_i[13] = wbs13_ack_o & wb_slave_sel_r[13];
assign wbs_err_o_mux_i[13] = wbs13_err_o & wb_slave_sel_r[13];
assign wbs_rty_o_mux_i[13] = wbs13_rty_o & wb_slave_sel_r[13];
 
 
// Slave 14 inputs
assign wbs14_adr_i = wbm_adr_o;
assign wbs14_dat_i = wbm_dat_o;
assign wbs14_sel_i = wbm_sel_o;
assign wbs14_cyc_i = wbm_cyc_o & wb_slave_sel_r[14];
assign wbs14_stb_i = wbm_stb_o & wb_slave_sel_r[14];
assign wbs14_we_i = wbm_we_o;
assign wbs14_cti_i = wbm_cti_o;
assign wbs14_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[14] = wbs14_dat_o;
assign wbs_ack_o_mux_i[14] = wbs14_ack_o & wb_slave_sel_r[14];
assign wbs_err_o_mux_i[14] = wbs14_err_o & wb_slave_sel_r[14];
assign wbs_rty_o_mux_i[14] = wbs14_rty_o & wb_slave_sel_r[14];
 
 
// Slave 15 inputs
assign wbs15_adr_i = wbm_adr_o;
assign wbs15_dat_i = wbm_dat_o;
assign wbs15_sel_i = wbm_sel_o;
assign wbs15_cyc_i = wbm_cyc_o & wb_slave_sel_r[15];
assign wbs15_stb_i = wbm_stb_o & wb_slave_sel_r[15];
assign wbs15_we_i = wbm_we_o;
assign wbs15_cti_i = wbm_cti_o;
assign wbs15_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[15] = wbs15_dat_o;
assign wbs_ack_o_mux_i[15] = wbs15_ack_o & wb_slave_sel_r[15];
assign wbs_err_o_mux_i[15] = wbs15_err_o & wb_slave_sel_r[15];
assign wbs_rty_o_mux_i[15] = wbs15_rty_o & wb_slave_sel_r[15];
 
 
// Slave 16 inputs
assign wbs16_adr_i = wbm_adr_o;
assign wbs16_dat_i = wbm_dat_o;
assign wbs16_sel_i = wbm_sel_o;
assign wbs16_cyc_i = wbm_cyc_o & wb_slave_sel_r[16];
assign wbs16_stb_i = wbm_stb_o & wb_slave_sel_r[16];
assign wbs16_we_i = wbm_we_o;
assign wbs16_cti_i = wbm_cti_o;
assign wbs16_bte_i = wbm_bte_o;
assign wbs_dat_o_mux_i[16] = wbs16_dat_o;
assign wbs_ack_o_mux_i[16] = wbs16_ack_o & wb_slave_sel_r[16];
assign wbs_err_o_mux_i[16] = wbs16_err_o & wb_slave_sel_r[16];
assign wbs_rty_o_mux_i[16] = wbs16_rty_o & wb_slave_sel_r[16];
 
*/
 
 
 
// Master out mux from slave in data
assign wbm_dat_i = wb_slave_sel_r[0] ? wbs_dat_o_mux_i[0] :
wb_slave_sel_r[1] ? wbs_dat_o_mux_i[1] :
wb_slave_sel_r[2] ? wbs_dat_o_mux_i[2] :
/* wb_slave_sel_r[3] ? wbs_dat_o_mux_i[3] :
wb_slave_sel_r[4] ? wbs_dat_o_mux_i[4] :
wb_slave_sel_r[5] ? wbs_dat_o_mux_i[5] :
wb_slave_sel_r[6] ? wbs_dat_o_mux_i[6] :
wb_slave_sel_r[7] ? wbs_dat_o_mux_i[7] :
wb_slave_sel_r[8] ? wbs_dat_o_mux_i[8] :
wb_slave_sel_r[9] ? wbs_dat_o_mux_i[9] :
wb_slave_sel_r[10] ? wbs_dat_o_mux_i[10] :
wb_slave_sel_r[11] ? wbs_dat_o_mux_i[11] :
wb_slave_sel_r[12] ? wbs_dat_o_mux_i[12] :
wb_slave_sel_r[13] ? wbs_dat_o_mux_i[13] :
wb_slave_sel_r[14] ? wbs_dat_o_mux_i[14] :
wb_slave_sel_r[15] ? wbs_dat_o_mux_i[15] :
wb_slave_sel_r[16] ? wbs_dat_o_mux_i[16] :
*/
wbs_dat_o_mux_i[0];
// Master out acks, or together
assign wbm_ack_i = wbs_ack_o_mux_i[0] |
wbs_ack_o_mux_i[1] |
wbs_ack_o_mux_i[2] /*|
wbs_ack_o_mux_i[3] |
wbs_ack_o_mux_i[4] |
wbs_ack_o_mux_i[5] |
wbs_ack_o_mux_i[6] |
wbs_ack_o_mux_i[7] |
wbs_ack_o_mux_i[8] |
wbs_ack_o_mux_i[9] |
wbs_ack_o_mux_i[10] |
wbs_ack_o_mux_i[11] |
wbs_ack_o_mux_i[12] |
wbs_ack_o_mux_i[13] |
wbs_ack_o_mux_i[14] |
wbs_ack_o_mux_i[15] |
wbs_ack_o_mux_i[16] */
;
 
assign wbm_err_i = wbs_err_o_mux_i[0] |
wbs_err_o_mux_i[1] |
wbs_err_o_mux_i[2] |/*
wbs_err_o_mux_i[3] |
wbs_err_o_mux_i[4] |
wbs_err_o_mux_i[5] |
wbs_err_o_mux_i[6] |
wbs_err_o_mux_i[7] |
wbs_err_o_mux_i[8] |
wbs_err_o_mux_i[9] |
wbs_err_o_mux_i[10] |
wbs_err_o_mux_i[11] |
wbs_err_o_mux_i[12] |
wbs_err_o_mux_i[13] |
wbs_err_o_mux_i[14] |
wbs_err_o_mux_i[15] |
wbs_err_o_mux_i[16] |*/
watchdog_err ;
 
 
assign wbm_rty_i = wbs_rty_o_mux_i[0] |
wbs_rty_o_mux_i[1] |
wbs_rty_o_mux_i[2] /*|
wbs_rty_o_mux_i[3] |
wbs_rty_o_mux_i[4] |
wbs_rty_o_mux_i[5] |
wbs_rty_o_mux_i[6] |
wbs_rty_o_mux_i[7] |
wbs_rty_o_mux_i[8] |
wbs_rty_o_mux_i[9] |
wbs_rty_o_mux_i[10] |
wbs_rty_o_mux_i[11] |
wbs_rty_o_mux_i[12] |
wbs_rty_o_mux_i[13] |
wbs_rty_o_mux_i[14] |
wbs_rty_o_mux_i[15] |
wbs_rty_o_mux_i[16]*/;
 
endmodule // arbiter_dbus
 
/boards/xilinx/ml501/rtl/verilog/arbiter/arbiter_ibus.v
0,0 → 1,337
//////////////////////////////////////////////////////////////////////
/// ////
/// Wishbone arbiter, burst-compatible ////
/// ////
/// Simple arbiter, single master, dual slave, primarily for ////
/// processor instruction bus, providing access to one main ////
/// memory server and one ROM ////
/// ////
/// Julius Baxter, julius@opencores.org ////
/// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2009, 2010 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
`include "orpsoc-defines.v"
// One master, 2 slaves.
module arbiter_ibus
(
// instruction bus in
// Wishbone Master interface
wbm_adr_o,
wbm_dat_o,
wbm_sel_o,
wbm_we_o,
wbm_cyc_o,
wbm_stb_o,
wbm_cti_o,
wbm_bte_o,
wbm_dat_i,
wbm_ack_i,
wbm_err_i,
wbm_rty_i,
 
 
// Slave one
// Wishbone Slave interface
wbs0_adr_i,
wbs0_dat_i,
wbs0_sel_i,
wbs0_we_i,
wbs0_cyc_i,
wbs0_stb_i,
wbs0_cti_i,
wbs0_bte_i,
wbs0_dat_o,
wbs0_ack_o,
wbs0_err_o,
wbs0_rty_o,
 
// Slave two
// Wishbone Slave interface
wbs1_adr_i,
wbs1_dat_i,
wbs1_sel_i,
wbs1_we_i,
wbs1_cyc_i,
wbs1_stb_i,
wbs1_cti_i,
wbs1_bte_i,
wbs1_dat_o,
wbs1_ack_o,
wbs1_err_o,
wbs1_rty_o,
 
wb_clk,
wb_rst
);
 
 
parameter wb_dat_width = 32;
parameter wb_adr_width = 32;
 
parameter wb_addr_match_width = 8;
 
parameter slave0_adr = 8'hf0; // FLASH ROM
parameter slave1_adr = 8'h00; // Main memory (SDRAM/FPGA SRAM)
 
`define WB_ARB_ADDR_MATCH_SEL wb_adr_width-1:wb_adr_width-wb_addr_match_width
input wb_clk;
input wb_rst;
 
// WB Master
input [wb_adr_width-1:0] wbm_adr_o;
input [wb_dat_width-1:0] wbm_dat_o;
input [3:0] wbm_sel_o;
input wbm_we_o;
input wbm_cyc_o;
input wbm_stb_o;
input [2:0] wbm_cti_o;
input [1:0] wbm_bte_o;
output [wb_dat_width-1:0] wbm_dat_i;
output wbm_ack_i;
output wbm_err_i;
output wbm_rty_i;
 
// WB Slave 0
output [wb_adr_width-1:0] wbs0_adr_i;
output [wb_dat_width-1:0] wbs0_dat_i;
output [3:0] wbs0_sel_i;
output wbs0_we_i;
output wbs0_cyc_i;
output wbs0_stb_i;
output [2:0] wbs0_cti_i;
output [1:0] wbs0_bte_i;
input [wb_dat_width-1:0] wbs0_dat_o;
input wbs0_ack_o;
input wbs0_err_o;
input wbs0_rty_o;
 
// WB Slave 1
output [wb_adr_width-1:0] wbs1_adr_i;
output [wb_dat_width-1:0] wbs1_dat_i;
output [3:0] wbs1_sel_i;
output wbs1_we_i;
output wbs1_cyc_i;
output wbs1_stb_i;
output [2:0] wbs1_cti_i;
output [1:0] wbs1_bte_i;
input [wb_dat_width-1:0] wbs1_dat_o;
input wbs1_ack_o;
input wbs1_err_o;
input wbs1_rty_o;
 
wire [1:0] slave_sel; // One bit per slave
 
reg watchdog_err;
`ifdef ARBITER_IBUS_WATCHDOG
reg [`ARBITER_IBUS_WATCHDOG_TIMER_WIDTH:0] watchdog_timer;
reg wbm_stb_r; // Register strobe
wire wbm_stb_edge; // Detect its edge
reg wbm_stb_edge_r, wbm_ack_i_r; // Reg these, better timing
 
always @(posedge wb_clk)
wbm_stb_r <= wbm_stb_o;
 
assign wbm_stb_edge = (wbm_stb_o & !wbm_stb_r);
 
always @(posedge wb_clk)
wbm_stb_edge_r <= wbm_stb_edge;
always @(posedge wb_clk)
wbm_ack_i_r <= wbm_ack_i;
// Counter logic
always @(posedge wb_clk)
if (wb_rst) watchdog_timer <= 0;
else if (wbm_ack_i_r) // When we see an ack, turn off timer
watchdog_timer <= 0;
else if (wbm_stb_edge_r) // New access means start timer again
watchdog_timer <= 1;
else if (|watchdog_timer) // Continue counting if counter > 0
watchdog_timer <= watchdog_timer + 1;
 
always @(posedge wb_clk)
watchdog_err <= (&watchdog_timer);
`else // !`ifdef ARBITER_IBUS_WATCHDOG
always @(posedge wb_clk)
watchdog_err <= 0;
 
`endif // !`ifdef ARBITER_IBUS_WATCHDOG
 
`ifdef ARBITER_IBUS_REGISTERING
// Master input registers
reg [wb_adr_width-1:0] wbm_adr_o_r;
reg [wb_dat_width-1:0] wbm_dat_o_r;
reg [3:0] wbm_sel_o_r;
reg wbm_we_o_r;
reg wbm_cyc_o_r;
reg wbm_stb_o_r;
reg [2:0] wbm_cti_o_r;
reg [1:0] wbm_bte_o_r;
// Slave output registers
reg [wb_dat_width-1:0] wbs0_dat_o_r;
reg wbs0_ack_o_r;
reg wbs0_err_o_r;
reg wbs0_rty_o_r;
reg [wb_dat_width-1:0] wbs1_dat_o_r;
reg wbs1_ack_o_r;
reg wbs1_err_o_r;
reg wbs1_rty_o_r;
 
wire wbm_ack_i_pre_reg;
 
// Register master input signals
always @(posedge wb_clk)
begin
wbm_adr_o_r <= wbm_adr_o;
wbm_dat_o_r <= wbm_dat_o;
wbm_sel_o_r <= wbm_sel_o;
wbm_we_o_r <= wbm_we_o;
wbm_cyc_o_r <= wbm_cyc_o;
wbm_stb_o_r <= wbm_stb_o & !wbm_ack_i_pre_reg & !wbm_ack_i;//classic
wbm_cti_o_r <= wbm_cti_o;
wbm_bte_o_r <= wbm_bte_o;
 
// Slave signals
wbs0_dat_o_r <= wbs0_dat_o;
wbs0_ack_o_r <= wbs0_ack_o;
wbs0_err_o_r <= wbs0_err_o;
wbs0_rty_o_r <= wbs0_rty_o;
wbs1_dat_o_r <= wbs1_dat_o;
wbs1_ack_o_r <= wbs1_ack_o;
wbs1_err_o_r <= wbs1_err_o;
wbs1_rty_o_r <= wbs1_rty_o;
end // always @ (posedge wb_clk)
 
// Slave select
assign slave_sel[0] = wbm_adr_o_r[`WB_ARB_ADDR_MATCH_SEL] ==
slave0_adr;
 
assign slave_sel[1] = wbm_adr_o_r[`WB_ARB_ADDR_MATCH_SEL] ==
slave1_adr;
 
// Slave out assigns
assign wbs0_adr_i = wbm_adr_o_r;
assign wbs0_dat_i = wbm_dat_o_r;
assign wbs0_we_i = wbm_dat_o_r;
assign wbs0_sel_i = wbm_sel_o_r;
assign wbs0_cti_i = wbm_cti_o_r;
assign wbs0_bte_i = wbm_bte_o_r;
assign wbs0_cyc_i = wbm_cyc_o_r & slave_sel[0];
assign wbs0_stb_i = wbm_stb_o_r & slave_sel[0];
 
assign wbs1_adr_i = wbm_adr_o_r;
assign wbs1_dat_i = wbm_dat_o_r;
assign wbs1_we_i = wbm_dat_o_r;
assign wbs1_sel_i = wbm_sel_o_r;
assign wbs1_cti_i = wbm_cti_o_r;
assign wbs1_bte_i = wbm_bte_o_r;
assign wbs1_cyc_i = wbm_cyc_o_r & slave_sel[1];
assign wbs1_stb_i = wbm_stb_o_r & slave_sel[1];
 
// Master out assigns
// Don't care about none selected...
assign wbm_dat_i = slave_sel[1] ? wbs1_dat_o_r :
wbs0_dat_o_r ;
assign wbm_ack_i = (slave_sel[0] & wbs0_ack_o_r) |
(slave_sel[1] & wbs1_ack_o_r)
;
assign wbm_err_i = (slave_sel[0] & wbs0_err_o_r) |
(slave_sel[1] & wbs1_err_o_r) |
watchdog_err;
assign wbm_rty_i = (slave_sel[0] & wbs0_rty_o_r) |
(slave_sel[1] & wbs1_rty_o_r);
 
// Non-registered ack
assign wbm_ack_i_pre_reg = (slave_sel[0] & wbs0_ack_o) |
(slave_sel[1] & wbs1_ack_o);
`else // !`ifdef ARBITER_IBUS_REGISTERING
 
// Slave select
assign slave_sel[0] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] ==
slave0_adr;
 
assign slave_sel[1] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] ==
slave1_adr;
 
// Slave out assigns
assign wbs0_adr_i = wbm_adr_o;
assign wbs0_dat_i = wbm_dat_o;
assign wbs0_we_i = wbm_we_o;
assign wbs0_sel_i = wbm_sel_o;
assign wbs0_cti_i = wbm_cti_o;
assign wbs0_bte_i = wbm_bte_o;
assign wbs0_cyc_i = wbm_cyc_o & slave_sel[0];
assign wbs0_stb_i = wbm_stb_o & slave_sel[0];
 
assign wbs1_adr_i = wbm_adr_o;
assign wbs1_dat_i = wbm_dat_o;
assign wbs1_we_i = wbm_we_o;
assign wbs1_sel_i = wbm_sel_o;
assign wbs1_cti_i = wbm_cti_o;
assign wbs1_bte_i = wbm_bte_o;
assign wbs1_cyc_i = wbm_cyc_o & slave_sel[1];
assign wbs1_stb_i = wbm_stb_o & slave_sel[1];
 
// Master out assigns
// Don't care about none selected...
assign wbm_dat_i = slave_sel[1] ? wbs1_dat_o :
wbs0_dat_o ;
assign wbm_ack_i = (slave_sel[0] & wbs0_ack_o) |
(slave_sel[1] & wbs1_ack_o);
assign wbm_err_i = (slave_sel[0] & wbs0_err_o) |
(slave_sel[1] & wbs1_err_o) |
watchdog_err;
assign wbm_rty_i = (slave_sel[0] & wbs0_rty_o) |
(slave_sel[1] & wbs1_rty_o);
 
`endif
endmodule // arbiter_ibus
 
/boards/xilinx/ml501/rtl/verilog/gpio/gpio.v
0,0 → 1,159
/*
*
* Simple 24-bit wide GPIO module
*
* Can be made wider as needed, but must be done manually.
*
* First lot of bytes are the GPIO I/O regs
* Second lot are the direction registers
*
* Set direction bit to '1' to output corresponding data bit.
*
* Register mapping:
*
* For 8 GPIOs we would have
* adr 0: gpio data 7:0
* adr 1: gpio data 15:8
* adr 2: gpio data 23:16
* adr 3: gpio dir 7:0
* adr 4: gpio dir 15:8
* adr 5: gpio dir 23:16
*
* Backend pinout file needs to be updated for any GPIO width changes.
*
*/
 
module gpio(
wb_clk,
wb_rst,
wb_adr_i,
wb_dat_i,
wb_we_i,
wb_cyc_i,
wb_stb_i,
wb_cti_i,
wb_bte_i,
 
wb_ack_o,
wb_dat_o,
wb_err_o,
wb_rty_o,
 
gpio_io);
 
 
parameter gpio_io_width = 24;
 
parameter gpio_dir_reset_val = 0;
parameter gpio_o_reset_val = 0;
parameter wb_dat_width = 8;
parameter wb_adr_width = 3; // 8 bytes addressable
input wb_clk;
input wb_rst;
input [wb_adr_width-1:0] wb_adr_i;
input [wb_dat_width-1:0] wb_dat_i;
input wb_we_i;
input wb_cyc_i;
input wb_stb_i;
input [2:0] wb_cti_i;
input [1:0] wb_bte_i;
output reg [wb_dat_width-1:0] wb_dat_o; // constantly sampling gpio in bus
output reg wb_ack_o;
output wb_err_o;
output wb_rty_o;
 
inout [gpio_io_width-1:0] gpio_io;
 
// Internal registers
reg [gpio_io_width-1:0] gpio_dir;
 
reg [gpio_io_width-1:0] gpio_o;
 
wire [gpio_io_width-1:0] gpio_i;
 
// Tristate logic for IO
genvar i;
generate
for (i=0;i<gpio_io_width;i=i+1) begin: gpio_tris
assign gpio_io[i] = (gpio_dir[i]) ? gpio_o[i] : 1'bz;
assign gpio_i[i] = (gpio_dir[i]) ? gpio_o[i] : gpio_io[i];
end
endgenerate
// GPIO data out register
always @(posedge wb_clk)
if (wb_rst)
gpio_o <= 0; // All set to in at reset
else if (wb_stb_i & wb_we_i)
begin
if (wb_adr_i == 0)
gpio_o[7:0] <= wb_dat_i;
if (wb_adr_i == 1)
gpio_o[15:8] <= wb_dat_i;
if (wb_adr_i == 2)
gpio_o[23:16] <= wb_dat_i;
/* Add appropriate address detection here for wider GPIO */
end
 
 
// GPIO dir register
always @(posedge wb_clk)
if (wb_rst)
gpio_dir <= 0; // All set to in at reset
else if (wb_stb_i & wb_we_i)
begin
if (wb_adr_i == ((gpio_io_width/8)))
gpio_dir[7:0] <= wb_dat_i;
if (wb_adr_i == ((gpio_io_width/8)+1))
gpio_dir[15:8] <= wb_dat_i;
if (wb_adr_i == ((gpio_io_width/8)+2))
//gpio_dir[23:16] <= wb_dat_i;
gpio_dir[21:16] <= wb_dat_i[5:0];
 
/* Add appropriate address detection here for wider GPIO */
 
end
 
// Register the gpio in signal
always @(posedge wb_clk)
begin
// Data regs
if (wb_adr_i == 0)
wb_dat_o[7:0] <= gpio_i[7:0];
if (wb_adr_i == 1)
wb_dat_o[7:0] <= gpio_i[15:8];
if (wb_adr_i == 2)
wb_dat_o[7:0] <= gpio_i[23:16];
/* Add appropriate address detection here for wider GPIO */
// Direction regs
if (wb_adr_i == ((gpio_io_width/8)))
wb_dat_o[7:0] <= gpio_dir[7:0];
if (wb_adr_i == ((gpio_io_width/8)+1))
wb_dat_o[7:0] <= gpio_dir[15:8];
if (wb_adr_i == ((gpio_io_width/8)+2))
wb_dat_o[7:0] <= gpio_dir[23:16];
 
/* Add appropriate address detection here for wider GPIO */
 
end
// Ack generation
always @(posedge wb_clk)
if (wb_rst)
wb_ack_o <= 0;
else if (wb_ack_o)
wb_ack_o <= 0;
else if (wb_stb_i & !wb_ack_o)
wb_ack_o <= 1;
 
assign wb_err_o = 0;
assign wb_rty_o = 0;
 
endmodule // gpio
/boards/xilinx/ml501/rtl/verilog/gpio/README
0,0 → 1,7
GPIO RTL
 
This is a simple GPIO implementation. It is variable width, however widths of
multiples of 8 are advised. The first width/8 bytes control are for
reading/writing to the GPIO registers, the second set of width/8 bytes control
the direction.
 
/boards/xilinx/ml501/sim/bin/Makefile
1,161 → 1,543
# Include file for tools, etc (mainly interested in the Xilinx path here)
include ../../../../tools.inc
######################################################################
#### ####
#### ORPSoCv2 Testbenches Makefile ####
#### ####
#### Description ####
#### ORPSoCv2 Testbenches Makefile, containing rules for ####
#### configuring and running different tests on the current ####
#### ORPSoC(v2) design. ####
#### ####
#### To do: ####
#### ####
#### Author(s): ####
#### - Julius Baxter, julius@opencores.org ####
#### ####
#### ####
######################################################################
#### ####
#### Copyright (C) 2009,2010 Authors and OPENCORES.ORG ####
#### ####
#### This source file may be used and distributed without ####
#### restriction provided that this copyright statement is not ####
#### removed from the file and that any derivative work contains ####
#### the original copyright notice and the associated disclaimer. ####
#### ####
#### This source file is free software; you can redistribute it ####
#### and/or modify it under the terms of the GNU Lesser General ####
#### Public License as published by the Free Software Foundation; ####
#### either version 2.1 of the License, or (at your option) any ####
#### later version. ####
#### ####
#### This source is distributed in the hope that it will be ####
#### useful, but WITHOUT ANY WARRANTY; without even the implied ####
#### warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ####
#### PURPOSE. See the GNU Lesser General Public License for more ####
#### details. ####
#### ####
#### You should have received a copy of the GNU Lesser General ####
#### Public License along with this source; if not, download it ####
#### from http://www.opencores.org/lgpl.shtml ####
#### ####
######################################################################
 
ORPSOC_ROOT=../../../../..
BOARD=ml501
# Name of the directory we're currently in
CUR_DIR=$(shell pwd)
 
CUR_DIR=$(shell pwd)
# The root path of the whole project
PROJECT_ROOT =$(CUR_DIR)/$(ORPSOC_ROOT)
PROJECT_ROOT ?=$(CUR_DIR)/../../../../..
 
SIM_DIR=$(CUR_DIR)/../../sim
DESIGN_NAME=orpsoc
RTL_TESTBENCH_TOP=$(DESIGN_NAME)_testbench
 
BOARD_BENCH_DIR=$(CUR_DIR)/../../bench
BOARD_RTL_DIR=$(CUR_DIR)/../../rtl
BOARD_SW_DIR=$(CUR_DIR)/../../sw
BOARD_SYN_DIR=$(CUR_DIR)/../../syn
# Hardset the board name, even though we could probably determine it
FPGA_VENDOR=xilinx
BOARD_NAME=ml501
BOARD_DIR=$(PROJECT_ROOT)/boards/$(FPGA_VENDOR)/$(BOARD_NAME)
 
# Export BOARD_PATH for the software makefiles
BOARD_PATH=$(BOARD_DIR)
export BOARD_PATH
 
# Important!
RTL_TESTBENCH_TOP=ml501_testbench
BENCH_TOP_VERILOG_DIR=$(BOARD_BENCH_DIR)
# Paths to other important parts of this test suite
COMMON_RTL_DIR = $(PROJECT_ROOT)/rtl
COMMON_RTL_VERILOG_DIR = $(COMMON_RTL_DIR)/verilog
#COMMON_RTL_VHDL_DIR = $(COMMON_RTL_DIR)/vhdl
 
# Extra defines passed to testbench compilation
# Used here for DDR2 model defines
EXTRA_BENCH_DEFINES=+define+sg37E +define+x16
BOARD_RTL_DIR=$(BOARD_DIR)/rtl
BOARD_RTL_VERILOG_DIR=$(BOARD_RTL_DIR)/verilog
# Only 1 include path for board builds - their own!
BOARD_RTL_VERILOG_INCLUDE_DIR=$(BOARD_RTL_VERILOG_DIR)/include
 
#MEMORY_MODELS=$(BENCH_VERILOG_DIR)/cy7c1354.v $(BENCH_VERILOG_DIR)/ddr2_model.v
BOARD_BENCH_DIR=$(BOARD_DIR)/bench
BOARD_BENCH_VERILOG_DIR=$(BOARD_BENCH_DIR)/verilog
BOARD_BENCH_VERILOG_INCLUDE_DIR=$(BOARD_BENCH_VERILOG_DIR)/include
 
SIMULATOR=vsim
COMMON_BENCH_DIR=$(PROJECT_ROOT)
COMMON_BENCH_VERILOG_DIR=$(COMMON_BENCH_DIR)/verilog
COMMON_BENCH_VERILOG_INCLUDE_DIR=$(COMMON_BENCH_VERILOG_DIR)/include
 
RTL_VERILOG_INCLUDE_DIR =$(BOARD_RTL_DIR)
# Top level files for DUT and testbench
DUT_TOP=$(BOARD_RTL_VERILOG_DIR)/$(DESIGN_NAME)_top/$(DESIGN_NAME)_top.v
BENCH_TOP=$(BOARD_BENCH_VERILOG_DIR)/$(DESIGN_NAME)_testbench.v
 
# Software tests we'll run
 
include $(ORPSOC_ROOT)/sim/bin/Makefile
# Need this for individual test variables to not break
TEST ?= or1200-simple
 
TESTS ?= or1200-simple or1200-cbasic or1200-dctest or1200-float or1200-mmu or1200-basic or1200-except or1200-tick or1200-ticksyscall uart-simple
 
# Gets turned into verilog `define
SIM_TYPE=RTL
 
# Main defines file is from board include path
PROJECT_VERILOG_DEFINES=$(BOARD_RTL_VERILOG_INCLUDE_DIR)/$(DESIGN_NAME)-defines.v
 
# Detect technology to use for the simulation
DESIGN_DEFINES=$(shell cat $(PROJECT_VERILOG_DEFINES) | sed s://.*::g | sed s:\`:\#:g | sed 's:^[ ]*::' | awk '{print};/^\#define/{printf "_%s=%s\n",$$2,$$2}' | grep -v PERIOD | cpp -P | sed s:^_::g | sed s:=$$::g )
 
# Rule to look at what defines are being extracted from main file
print-defines:
@echo echo; echo "\t### Design defines ###"; echo;
@echo "\tParsing "$(PROJECT_VERILOG_DEFINES)" and exporting:"
@echo $(DESIGN_DEFINES)
 
print-tests:
@echo; echo; echo "\t### Software tests to be run ###"; echo;
@echo $(TESTS)
@echo
 
# Simulation directories
SIM_DIR ?=$(BOARD_DIR)/sim
RTL_SIM_DIR=$(SIM_DIR)
RTL_SIM_RUN_DIR=$(RTL_SIM_DIR)/run
RTL_SIM_BIN_DIR=$(RTL_SIM_DIR)/bin
RTL_SIM_RESULTS_DIR=$(RTL_SIM_DIR)/out
 
# Testbench paths
BOARD_BENCH_DIR=$(BOARD_DIR)/bench
BOARD_BENCH_VERILOG_DIR=$(BOARD_BENCH_DIR)/verilog
COMMON_BENCH_DIR=$(PROJECT_ROOT)/bench
COMMON_BENCH_VERILOG_DIR=$(COMMON_BENCH_DIR)/verilog
 
#BENCH_VHDL_DIR=$(BENCH_DIR)/vhdl
# No SystemC or Verilator support for this build
#BENCH_SYSC_DIR=$(BENCH_DIR)/sysc
#BENCH_SYSC_SRC_DIR=$(BENCH_SYSC_DIR)/src
#BENCH_SYSC_INCLUDE_DIR=$(BENCH_SYSC_DIR)/include
 
# Backend directories
# This one is the board build's backend dir.
BOARD_BACKEND_DIR=$(BOARD_DIR)/backend
BOARD_BACKEND_VERILOG_DIR=$(BOARD_BACKEND_DIR)/rtl/verilog
TECHNOLOGY_BACKEND_DIR=$(BOARD_DIR)/../backend
# This path is for the technology library
TECHNOLOGY_BACKEND_VERILOG_DIR=$(TECHNOLOGY_BACKEND_DIR)/rtl/verilog
 
# Synthesis directory for board
BOARD_SYN_DIR=$(BOARD_DIR)/syn/synplify
BOARD_SYN_OUT_DIR=$(BOARD_SYN_DIR)/out
 
# System software dir
COMMON_SW_DIR=$(PROJECT_ROOT)/sw
BOARD_SW_DIR=$(BOARD_DIR)/sw
 
# BootROM code, which generates a verilog array select values
BOOTROM_FILE=bootrom.v
BOOTROM_SW_DIR=$(BOARD_SW_DIR)/bootrom
BOOTROM_SRC=$(shell ls $(BOOTROM_SW_DIR)/* | grep -v $(BOOTROM_FILE))
BOOTROM_VERILOG=$(BOOTROM_SW_DIR)/$(BOOTROM_FILE)
 
bootrom: $(BOOTROM_VERILOG)
 
$(BOOTROM_VERILOG): $(BOOTROM_SRC)
$(Q)echo; echo "\t### Generating bootup ROM ###"; echo
$(Q)$(MAKE) -C $(BOOTROM_SW_DIR) $(BOOTROM_FILE)
 
# Suffix of file to check after each test for the string
TEST_OUT_FILE_SUFFIX=-general.log
TEST_OK_STRING=8000000d
 
# Dynamically generated verilog file defining configuration for various things
# Rule actually generating this is found in definesgen.inc file.
TEST_DEFINES_VLG=test-defines.v
# Set V=1 when calling make to enable verbose output
# mainly for debugging purposes.
ifeq ($(V), 1)
Q=
QUIET=
else
Q ?=@
QUIET=-quiet
endif
 
# Modelsim variables
MGC_VSIM=vsim
MGC_VLOG_COMP=vlog
MGC_VHDL_COMP=vcom
MODELSIM=modelsim
 
# Default simulator is Modelsim here as we're using the ProASIC3
# libraries which are not compilable with Icarus.
# Set SIMULATOR=modelsim to use Modelsim (Default)
# Set SIMULATOR=ncverilog to use Cadence's NC-Verilog - TODO
# Set SIMULATOR=icarus to use Icarus Verilog (Not supported for this board)
 
SIMULATOR ?= $(MODELSIM)
 
#
# Modelsim-specific settings
#
VOPT_ARGS=$(QUIET) -suppress 2241
# If VCD dump is desired, tell Modelsim not to optimise
# away everything.
ifeq ($(VCD), 1)
VOPT_ARGS=+acc=rnp
#VOPT_ARGS=-voptargs="+acc=rnp"
VOPT_ARGS=+acc=rnpqv
endif
# VSIM commands
# Suppressed warnings - 3009: Failed to open $readmemh() file
# Suppressed warnings - 3009: Module 'blah' does not have a `timescale directive in effect, but previous modules do.
# Suppressed warnings - 8598: Non-positive replication multiplier inside concat. Replication will be ignored
VSIM_ARGS= -suppress 7 -suppress 3009 -suppress 8598 -c $(QUIET) -do "set StdArithNoWarnings 1; run -all; exit"
# Modelsim VPI settings
ifeq ($(VPI), 1)
VPI_LIBS=$(VPI_SRC_C_DIR)/$(MODELTECH_VPILIB)
VSIM_ARGS += -pli $(VPI_SRC_C_DIR)/$(MODELTECH_VPILIB)
endif
# Rule to make the VPI library for modelsim
$(VPI_SRC_C_DIR)/$(MODELTECH_VPILIB): $(VPI_SRCS)
$(MAKE) -C $(VPI_SRC_C_DIR) $(MODELTECH_VPILIB)
 
#
# Verilog DUT source variables
#
 
# Here we re-define the modelsim compilation variable, changing include dirs
# so we use the includes/defines from the board's rtl path instead of the
# normal orpsocv2 bench path.
# First consider any modules we'll use gatelevel descriptions of.
# These will have to be set on the command line
GATELEVEL_MODULES ?=
 
# First we get a list of modules in the RTL path of the board's path.
# Next we check which modules not in the board's RTL path are in the root RTL
# path (modules which can be commonly instantiated, but over which board
# build-specific versions take precedence.)
 
# Modelsim testench compilation - we change this from the standard makefile
# to change:
# 1) The include directory (should be the board RTL path, not the main RTL path)
# 2) Change the define for the name of the top testbench (board dependent)
# 3) Add the board's testbench paths
# 4) Add the various extra memory models we use (maybe should just use a script for this instead? TODO!)
VSIM_COMPILE_TB = vlog $(BENCH_VERILOG_DIR)/or1200_monitor.v $(BENCH_TOP_VERILOG_DIR)/$(RTL_TESTBENCH_TOP).v
VSIM_COMPILE_TB += +incdir+$(BENCH_VERILOG_DIR) +incdir+$(BENCH_TOP_VERILOG_DIR) +incdir+$(BOARD_RTL_DIR) +incdir+$(XILINX_VERILOG_SRC)
VSIM_COMPILE_TB += +define+TEST_DEFINE_FILE
VSIM_COMPILE_TB += +define+OR1200_TOP=$(RTL_TESTBENCH_TOP).dut.i_or1k.i_or1200_top
VSIM_COMPILE_TB += +define+TESTBENCH_DEFINES=\"$(RTL_TESTBENCH_TOP)_defines.v\"
VSIM_COMPILE_TB += -y $(BENCH_VERILOG_DIR) -y $(BOARD_BENCH_DIR) +libext+.v
VSIM_COMPILE_TB += $(EXTRA_BENCH_DEFINES)
# Paths under board/***/rtl/verilog we wish to exclude when getting modules
BOARD_VERILOG_MODULES_EXCLUDE= include $(GATELEVEL_MODULES)
BOARD_VERILOG_MODULES_DIR_LIST=$(shell ls $(BOARD_RTL_VERILOG_DIR))
# Apply exclude to list of modules
BOARD_RTL_VERILOG_MODULES=$(filter-out $(BOARD_VERILOG_MODULES_EXCLUDE),$(BOARD_VERILOG_MODULES_DIR_LIST))
 
VOPT_STEP=vopt -quiet $(VOPT_ARGS) glbl $(RTL_TESTBENCH_TOP) -L $(MGC_ORPSOC_LIB) -o testbench
SIM_COMMANDRUN= $(VSIM_COMPILE_TB); $(VOPT_STEP); $(VSIM) -c -quiet +nowarnTFMPC -L $(MGC_ORPSOC_LIB) -do "run -all; exit" testbench
# Rule for debugging this script
print-board-modules:
@echo echo; echo "\t### Board verilog modules ###"; echo
@echo $(BOARD_RTL_VERILOG_MODULES)
 
# Re-define the command-file generation rule - we add a few extra things to
# our scripts to tell the simulator where the Xilinx tools, other set of
# includes, etc.
$(SIM_RUN_DIR)/$(GENERATED_COMMANDFILE): $(SIM_BIN_DIR)/$(SIM_COMMANDFILE)
$(Q)sed < $(SIM_BIN_DIR)/$(SIM_COMMANDFILE) > $(SIM_RUN_DIR)/$(GENERATED_COMMANDFILE) \
-e s!\$$BENCH_DIR!$(BENCH_VERILOG_DIR)! \
-e s!\$$RTL_DIR!$(RTL_VERILOG_DIR)! \
-e s!\$$BOARD_BENCH_DIR!$(BOARD_BENCH_DIR)! \
-e s!\$$BOARD_RTL_DIR!$(BOARD_RTL_DIR)! \
-e s!\$$BACKEND_DIR!$(BACKEND_DIR)! \
-e s!\$$XILINX_VERILOG_SRC!$(XILINX_VERILOG_SRC)! \
-e \\!^//.*\$$!d -e \\!^\$$!d ; \
echo "+define+TEST_DEFINE_FILE=\"test_define.v\"" >> $(SIM_RUN_DIR)/$(GENERATED_COMMANDFILE); \
if [ ! -z $$VCD ]; \
then echo "+define+VCD" >> $(SIM_RUN_DIR)/$(GENERATED_COMMANDFILE); \
if [ $(SIMULATOR) = $(NCVERILOG) ]; \
then echo "+access+r" >> $(SIM_RUN_DIR)/$(GENERATED_COMMANDFILE); \
fi; \
fi; \
if [ ! -z $$UART_PRINTF ]; \
then echo "+define+UART_PRINTF" >> $(SIM_RUN_DIR)/$(GENERATED_COMMANDFILE); \
fi; \
if [ $(SIMULATOR) = $(NCVERILOG) ]; \
then echo "+nocopyright" >> $(SIM_RUN_DIR)/$(GENERATED_COMMANDFILE); \
echo "+nowarn+MACRDF" >> $(SIM_RUN_DIR)/$(GENERATED_COMMANDFILE); \
# Now get list of modules that we don't have a version of in the board path
COMMON_VERILOG_MODULES_EXCLUDE= include
COMMON_VERILOG_MODULES_EXCLUDE += $(BOARD_RTL_VERILOG_MODULES)
COMMON_VERILOG_MODULES_EXCLUDE += $(GATELEVEL_MODULES)
 
COMMON_RTL_VERILOG_MODULES_DIR_LIST=$(shell ls $(COMMON_RTL_VERILOG_DIR))
COMMON_RTL_VERILOG_MODULES=$(filter-out $(COMMON_VERILOG_MODULES_EXCLUDE), $(COMMON_RTL_VERILOG_MODULES_DIR_LIST))
 
 
# Add these to exclude their RTL directories from being included in scripts
 
 
 
# Rule for debugging this script
print-common-modules-exclude:
@echo echo; echo "\t### Common verilog modules being excluded due to board versions ###"; echo
@echo "$(COMMON_VERILOG_MODULES_EXCLUDE)"
 
print-common-modules:
@echo echo; echo "\t### Verilog modules from common RTL dir ###"; echo
@echo $(COMMON_RTL_VERILOG_MODULES)
 
# List of verilog source files (only .v files!)
# Board RTL modules first
RTL_VERILOG_SRC=$(shell for module in $(BOARD_RTL_VERILOG_MODULES); do if [ -d $(BOARD_RTL_VERILOG_DIR)/$$module ]; then ls $(BOARD_RTL_VERILOG_DIR)/$$module/*.v; fi; done)
# Common RTL module source
RTL_VERILOG_SRC +=$(shell for module in $(COMMON_RTL_VERILOG_MODULES); do if [ -d $(COMMON_RTL_VERILOG_DIR)/$$module ]; then ls $(COMMON_RTL_VERILOG_DIR)/$$module/*.v; fi; done)
 
# List of verilog includes from board RTL path - only for rule sensitivity
RTL_VERILOG_INCLUDES=$(shell ls $(BOARD_RTL_VERILOG_INCLUDE_DIR)/*.*)
 
print-verilog-src:
@echo echo; echo "\t### Verilog source ###"; echo
@echo $(RTL_VERILOG_SRC)
 
# Rules to make RTL we might need
# Expects modules, if they need making, to have their top verilog file to
# correspond to their module name, and the directory should have a make file
# and rule which works for this command.
# Add name of module to this list, currently only does verilog ones.
# Rule 'rtl' is called just before generating DUT modelsim compilation script
RTL_TO_CHECK=
rtl:
$(Q)for module in $(RTL_TO_CHECK); do \
$(MAKE) -C $(RTL_VERILOG_DIR)/$$module $$module.v; \
done
 
#
# VHDL DUT source variables
#
# VHDL modules
#RTL_VHDL_MODULES=$(shell ls $(RTL_VHDL_DIR))
# VHDL sources
#RTL_VHDL_SRC=$(shell for module in $(RTL_VHDL_MODULES); do if [ -d $(RTL_VHDL_DIR)/$$module ]; then ls $(RTL_VHDL_DIR)/$$module/*.vhd; fi; done)
#print-vhdl-src:
# @echo echo; echo "\t### VHDL modules and source ###"; echo
# @echo "modules: "; echo $(RTL_VHDL_MODULES); echo
# @echo "source: "$(RTL_VHDL_SRC)
 
#
# Testbench source
#
BOARD_BENCH_VERILOG_SRC=$(shell ls $(BOARD_BENCH_VERILOG_DIR)/*.v | grep -v $(DESIGN_NAME)_testbench )
BOARD_BENCH_VERILOG_SRC_FILES=$(notdir $(BOARD_BENCH_VERILOG_SRC))
 
# Now only take the source from the common path that we don't already have in
# our board's
COMMON_BENCH_VERILOG_DIR_LS=$(shell ls $(COMMON_BENCH_VERILOG_DIR)/*.v)
COMMON_BENCH_VERILOG_SRC_FILES=$(notdir $(COMMON_BENCH_VERILOG_DIR_LS))
COMMON_BENCH_VERILOG_SRC_FILTERED=$(filter-out $(BOARD_BENCH_VERILOG_SRC_FILES) $(DESIGN_NAME)_testbench.v,$(COMMON_BENCH_VERILOG_SRC_FILES))
COMMON_BENCH_VERILOG_SRC=$(addprefix $(COMMON_BENCH_VERILOG_DIR)/, $(COMMON_BENCH_VERILOG_SRC_FILTERED))
 
print-board-bench-src:
$(Q)echo "\tBoard bench verilog source"; \
echo $(BOARD_BENCH_VERILOG_SRC)
 
print-common-bench-src:
$(Q)echo "\Common bench verilog source"; \
echo $(COMMON_BENCH_VERILOG_SRC)
 
# Testbench source subdirectory detection (exclude include, we always use
# board bench include directory!)
BOARD_BENCH_VERILOG_SUBDIRS=$(shell cd $(BOARD_BENCH_VERILOG_DIR) && ls -d */ | grep -v include)
COMMON_BENCH_VERILOG_SUBDIRS=$(shell cd $(COMMON_BENCH_VERILOG_DIR) && ls -d */ | grep -v include)
 
# Get rid of ones we have a copy of locally
COMMON_BENCH_VERILOG_SUBDIRS_EXCLUDE_BOARDS=$(filter-out $(BOARD_BENCH_VERILOG_SUBDIRS),$(COMMON_BENCH_VERILOG_SUBDIRS))
 
# Construct list of paths we will want to include
BENCH_VERILOG_SUBDIRS=$(addprefix $(COMMON_BENCH_VERILOG_DIR)/,$(COMMON_BENCH_VERILOG_SUBDIRS_EXCLUDE_BOARDS))
BENCH_VERILOG_SUBDIRS += $(addprefix $(BOARD_BENCH_VERILOG_DIR)/,$(BOARD_BENCH_VERILOG_SUBDIRS))
 
# Finally, add include path from local bench path
BENCH_VERILOG_SUBDIRS += $(BOARD_BENCH_VERILOG_DIR)/include
 
print-board-bench-subdirs:
$(Q)echo "\tBoard bench subdirectories"; \
echo $(BOARD_BENCH_VERILOG_SUBDIRS)
 
print-common-bench-subdirs:
$(Q)echo "\tCommon bench subdirectories"; \
echo $(COMMON_BENCH_VERILOG_SUBDIRS)
 
print-bench-subdirs:
$(Q)echo "\tBench subdirectories"; \
echo $(BENCH_VERILOG_SUBDIRS)
 
 
# Backend technology library files
# We don't do this for the board backend stuff - that should all be properly
# named, and so we only need to pass the "-y" option for that path.
BOARD_BACKEND_VERILOG_SRC=$(shell ls $(BOARD_BACKEND_VERILOG_DIR)/*.v )
 
#
# Compile script generation rules:
#
 
# Modelsim library compilation rules
# $(Q)echo "-y " $(BOARD_BACKEND_VERILOG_DIR) >> $@;
# DUT compile script
modelsim_dut.scr: rtl $(RTL_VERILOG_SRC) $(RTL_VERILOG_INCLUDES) $(BOOTROM_VERILOG)
$(Q)echo "+incdir+"$(BOARD_RTL_VERILOG_INCLUDE_DIR) > $@;
$(Q)echo "+incdir+"$(BOOTROM_SW_DIR) >> $@;
$(Q)echo "+incdir+"$(BOARD_BENCH_VERILOG_INCLUDE_DIR) >> $@;
$(Q)echo "+libext+.v" >> $@;
$(Q)for module in $(BOARD_RTL_VERILOG_MODULES); do if [ -d $(BOARD_RTL_VERILOG_DIR)/$$module ]; then echo "-y " $(BOARD_RTL_VERILOG_DIR)/$$module >> $@; fi; done
$(Q)for module in $(COMMON_RTL_VERILOG_MODULES); do if [ -d $(COMMON_RTL_VERILOG_DIR)/$$module ]; then echo "-y " $(COMMON_RTL_VERILOG_DIR)/$$module >> $@; fi; done
$(Q)echo "-y "$(TECHNOLOGY_BACKEND_VERILOG_DIR)"/src/unisims" >> $@;
$(Q)echo "-y "$(TECHNOLOGY_BACKEND_VERILOG_DIR)"/src/XilinxCoreLib" >> $@;
$(Q)if [ ! -z "$$GATELEVEL_MODULES" ]; \
then echo "-y " $(BOARD_SYN_OUT_DIR) >> $@; \
echo "+libext+.vm" >> $@; \
fi
$(Q)echo >> $@
 
modelsim_bench.scr: $(BOARD_BENCH_VERILOG_SRC) $(COMMON_BENCH_VERILOG_SRC)
$(Q)echo "+incdir+"$(BOARD_BENCH_VERILOG_INCLUDE_DIR) > $@;
$(Q)echo "+incdir+"$(COMMON_BENCH_VERILOG_INCLUDE_DIR) >> $@;
$(Q)for path in $(BENCH_VERILOG_SUBDIRS); do echo "+incdir+"$$path >> $@; done
$(Q)for path in $(BENCH_VERILOG_SUBDIRS); do echo "-y "$$path >> $@; done
$(Q)echo "+incdir+"$(BOARD_RTL_VERILOG_INCLUDE_DIR) >> $@;
$(Q)echo "+libext+.v" >> $@;
$(Q)echo "+incdir+"$(TECHNOLOGY_BACKEND_VERILOG_DIR)"/src" >> $@;
$(Q)for vsrc in $(BOARD_BENCH_VERILOG_SRC); do echo $$vsrc >> $@; done
$(Q)for vsrc in $(COMMON_BENCH_VERILOG_SRC); do echo $$vsrc >> $@; done
$(Q)echo >> $@
 
# Modelsim library compilation rules
 
# A new set of tests for software which will run only on this board
# eth board test doesn't quit properly for some reason
BOARD_TESTS=boot memtest gpio
# Compile DUT into "work" library
work: modelsim_dut.scr
$(Q)if [ ! -e $@ ]; then vlib $@; fi
$(Q)echo; echo "\t### Compiling Verilog design library ###"; echo
$(Q)vlog $(QUIET) -f $< $(DUT_TOP)
# $(Q)echo; echo "\t### Compiling VHDL design library ###"; echo
# $(Q)vcom -93 $(QUIET) $(RTL_VHDL_SRC)
 
rtl-board-tests: $(SIM_RUN_DIR)/$(GENERATED_COMMANDFILE) prepare-sw prepare-rtl prepare-dirs
@echo
@echo "Beginning loop that will complete the following tests for $(BOARD) board: $(BOARD_TESTS)"
@echo
$(Q)for TEST in $(BOARD_TESTS); do \
echo "################################################################################"; \
echo; \
echo "\t#### Current test: $$TEST ####"; echo; \
echo "\t#### Compiling software ####"; echo; \
CURRENT_TEST_SW_DIR=$(BOARD_SW_DIR)/`echo $$TEST | cut -d "-" -f 1`; \
$(MAKE) -C $$CURRENT_TEST_SW_DIR clean $$TEST $(TEST_SW_MAKE_OPTS); \
rm -f $(SIM_RUN_DIR)/$(SIM_FLASH_MEM_FILE); \
rm -f $(SIM_RUN_DIR)/$(SIM_SRAM_MEM_FILE); \
ln -s $$CURRENT_TEST_SW_DIR/$$TEST.vmem $(SIM_RUN_DIR)/$(SIM_SRAM_MEM_FILE); \
echo "\`define TEST_NAME_STRING \"$$TEST\"" > $(SIM_RUN_DIR)/test_define.v; \
echo "\`define TEST_RESULTS_DIR \"$(SIM_RESULTS_DIR)/\" " >> $(SIM_RUN_DIR)/test_define.v; \
if [ ! -z $$VCD ]; \
then echo "\`define VCD" >> $(SIM_RUN_DIR)/test_define.v; \
fi; \
if [ ! -z $$UART_PRINTF ]; \
then echo "\`define UART_PRINTF" >> $(SIM_RUN_DIR)/test_define.v; \
fi; \
if [ -z $$NO_SIM_LOGGING ]; then \
echo "\`define OR1200_DISPLAY_ARCH_STATE" >> $(SIM_RUN_DIR)/test_define.v; \
fi; \
echo ; \
echo "\t#### Compiling RTL ####"; \
$(SIM_COMMANDCOMPILE); \
echo; \
echo "\t#### Beginning simulation ####"; \
time -p $(SIM_COMMANDRUN) ; \
if [ $$? -gt 0 ]; then exit $$?; fi; \
TEST_RESULT=`cat $(SIM_RESULTS_DIR)/$$TEST-general.log | grep report | grep $(SIM_SUCCESS_MESSAGE) -c`; \
echo; echo "\t####"; \
if [ $$TEST_RESULT -gt 0 ]; then \
echo "\t#### Test $$TEST PASSED ####";TESTS_PASSED=`expr $$TESTS_PASSED + 1`;\
else echo "\t#### Test $$TEST FAILED ####";\
fi; \
echo "\t####"; echo; \
TESTS_PERFORMED=`expr $$TESTS_PERFORMED + 1`;\
done; \
echo "Test results: "$$TESTS_PASSED" out of "$$TESTS_PERFORMED" tests passed"; echo
# Single compile rule
.PHONY : $(MODELSIM)
$(MODELSIM): modelsim_bench.scr $(TEST_DEFINES_VLG) $(VPI_LIBS) work
$(Q)echo; echo "\t### Compiling Xilinx support libs, user design & testbench ###"; echo
$(Q)vlog $(QUIET) -nologo -incr $(BENCH_TOP) -f $<
$(Q)vopt $(QUIET) glbl $(RTL_TESTBENCH_TOP) $(VOPT_ARGS) -o tb
$(Q)echo; echo "\t### Launching simulation ###"; echo
$(Q)vsim $(VSIM_ARGS) tb
 
 
SYN_SIM_COMMANDCOMPILE=if [ ! -e work ]; then vlib work; vlib $(MGC_ORPSOC_LIB); vlog -work $(MGC_ORPSOC_LIB) +libext+.v -y $(XILINX_VERILOG_SRC) +incdir+$(XILINX_VERILOG_SRC) -y $(XILINX_VERILOG_SRC)/unisims +incdir+$(XILINX_VERILOG_SRC)/unisims -y $(XILINX_VERILOG_SRC)/XilinxCoreLib +incdir+$(XILINX_VERILOG_SRC)/XilinxCoreLib $(BOARD_SYN_DIR)/$(BOARD).v $(BOARD_RTL_DIR)/ml501_ddr2_wb_if_cache.v ; fi
syn-board-test: prepare-dirs $(BOARD_SYN_DIR)/$(BOARD).v
$(Q)echo "\`define TEST_NAME_STRING \"ml501-post-synthesis\"" > $(SIM_RUN_DIR)/test_define.v; \
echo "\`define POST_SYNTHESIS_SIM" >> $(SIM_RUN_DIR)/test_define.v; \
.PHONY: rtl-test
rtl-test: clean-sim-test-sw sw clean-test-defines $(TEST_DEFINES_VLG) \
$(SIMULATOR)
 
echo "\`define TEST_RESULTS_DIR \"$(SIM_RESULTS_DIR)/\" " >> $(SIM_RUN_DIR)/test_define.v; \
if [ ! -z $$VCD ]; \
then echo "\`define VCD" >> $(SIM_RUN_DIR)/test_define.v; \
if [ ! -z $$VCD_DEPTH ]; \
then echo "\`define VCD_DEPTH "$(VCD_DEPTH) >> $(SIM_RUN_DIR)/test_define.v; \
fi; \
fi; \
if [ ! -z $$UART_PRINTF ]; \
then echo "\`define UART_PRINTF" >> $(SIM_RUN_DIR)/test_define.v; \
fi; \
echo "\t#### Compiling RTL ####"; \
$(SYN_SIM_COMMANDCOMPILE); \
echo; \
echo "\t#### Beginning simulation ####"; \
time -p $(SIM_COMMANDRUN) ; \
echo
# Run an RTL test followed by checking of generated results
rtl-test-with-check: rtl-test
$(Q)$(MAKE) check-test-log; \
if [ $$? -ne 0 ]; then \
echo; echo "\t### "$(TEST)" test FAIL ###"; echo; \
else \
echo; echo "\t### "$(TEST)" test OK ###"; echo; \
fi
 
# Do check, don't print anything out
rtl-test-with-check-no-print: rtl-test check-test-log
 
# Main RTL test loop
rtl-tests:
$(Q)for test in $(TESTS); do \
export TEST=$$test; \
$(MAKE) rtl-test-with-check-no-print; \
if [ $$? -ne 0 ]; then break; fi; \
echo; echo "\t### $$test test OK ###"; echo; \
done
 
 
.PHONY: check-test-log
check-test-log:
$(Q)echo "#!/bin/bash" > $@
$(Q)echo "function check-test-log { if [ \`grep -c -i "$(TEST_OK_STRING)" "$(RTL_SIM_RESULTS_DIR)"/"$(TEST)$(TEST_OUT_FILE_SUFFIX)"\` -gt 0 ]; then return 0; else return 1; fi; }" >> $@
$(Q)echo "check-test-log" >> $@
$(Q)chmod +x $@
$(Q) echo; echo "\t### Checking simulation results for "$(TEST)" test ###"; echo;
$(Q)./$@
 
# Include the test-defines.v generation rule
include $(PROJECT_ROOT)/sim/bin/definesgen.inc
 
#
# Software make rules (called recursively)
#
 
# Path for the current test
# First check for a local copy of the test. If it doesn't exist then we
# default to the software tests in the root directory
TEST_MODULE=$(shell echo $(TEST) | cut -d "-" -f 1)
BOARD_SW_TEST_DIR=$(BOARD_SW_DIR)/tests/$(TEST_MODULE)/sim
COMMON_SW_TEST_DIR=$(COMMON_SW_DIR)/tests/$(TEST_MODULE)/sim
# Do this by testing for the file's existence
SW_TEST_DIR=$(shell if [ -e $(BOARD_SW_TEST_DIR)/$(TEST).[cS] ]; then echo $(BOARD_SW_TEST_DIR); else echo $(COMMON_SW_TEST_DIR); fi)
 
print-test-sw-dir:
@echo; echo "\tTest software is in the following path"; echo;
@echo $(BOARD_SW_DIR); echo;
@echo $(BOARD_SW_TEST_DIR); echo;
@echo $(SW_TEST_DIR); echo;
 
print-sw-tests:
$(Q) $(MAKE) -C $(COMMON_SW_DIR)/lib print-sw-tests
$(Q) $(MAKE) -C $(COMMON_SW_DIR)/lib print-sw-tests-subdirs
 
 
# Name of the image the RAM model will attempt to load via Verilog $readmemh
# system function.
 
# Set PRELOAD_RAM=1 to preload the system memory - be sure the bootROM program
# chosen in board.h is the one booting from the reset vector.
ifeq ($(PRELOAD_RAM), 1)
SIM_SW_IMAGE ?=sram.vmem
else
SIM_SW_IMAGE ?=flash.in
endif
 
.PHONY : sw
sw: $(SIM_SW_IMAGE)
 
 
flash.in: $(SW_TEST_DIR)/$(TEST).flashin
$(Q)if [ -L $@ ]; then unlink $@; fi
$(Q)ln -s $< $@
 
sram.vmem: $(SW_TEST_DIR)/$(TEST).vmem
$(Q)if [ -L $@ ]; then unlink $@; fi
$(Q)ln -s $< $@
 
.PHONY: $(SW_TEST_DIR)/$(TEST).flashin
$(SW_TEST_DIR)/$(TEST).flashin:
$(Q) echo; echo "\t### Compiling software ###"; echo;
$(Q)$(MAKE) -C $(SW_TEST_DIR) $(TEST).flashin
 
.PHONY: $(SW_TEST_DIR)/$(TEST).vmem
$(SW_TEST_DIR)/$(TEST).vmem:
$(Q) echo; echo "\t### Compiling software ###"; echo;
$(Q)$(MAKE) -C $(SW_TEST_DIR) $(TEST).vmem
 
# Create test software disassembly
 
sw-dis: $(SW_TEST_DIR)/$(TEST).dis
$(Q)cp -v $< .
 
$(SW_TEST_DIR)/$(TEST).dis:
$(Q)$(MAKE) -C $(SW_TEST_DIR) $(TEST).dis
 
#
# Cleaning rules
#
clean: clean-sim clean-sim-test-sw clean-bootrom clean-out clean-sw
 
clean-sim:
$(Q) echo; echo "\t### Cleaning simulation run directory ###"; echo;
$(Q)rm -rf *.* lib_* work transcript check-test-log
# No VPI support for now. $(Q) if [ -e $(VPI_SRC_C_DIR) ]; then $(MAKE) -C $(VPI_SRC_C_DIR) clean; fi
 
clean-bootrom:
$(MAKE) -C $(BOOTROM_SW_DIR) clean
 
clean-out:
$(Q)rm -rf $(RTL_SIM_RESULTS_DIR)/*.*
 
clean-test-defines:
$(Q)rm -f $(TEST_DEFINES_VLG)
 
clean-sim-test-sw:
$(Q)if [ -e $(SIM_SW_IMAGE) ]; then unlink $(SIM_SW_IMAGE); fi
 
clean-sw:
$(Q) echo; echo "\t### Cleaning simulation sw directories ###"; echo;
$(Q) $(MAKE) -C $(COMMON_SW_DIR)/lib clean-all
 
clean-rtl:
$(Q) echo; echo "\t### Cleaning generated verilog RTL ###"; echo;
for module in $(RTL_TO_CHECK); do \
$(MAKE) -C $(RTL_VERILOG_DIR)/$$module clean; \
done
 
# Removes any checked out RTL
distclean: clean
$(Q) echo; echo "\t### Cleaning generated verilog RTL ###"; echo;
$(Q)for module in $(RTL_TO_CHECK); do \
$(MAKE) -C $(RTL_VERILOG_DIR)/$$module distclean; \
done
/boards/xilinx/ml501/sw/bootrom/Makefile
0,0 → 1,27
# Makefile for bootROM Verilog
# We will do it by building the main one, and applying our local board's
# settings.
# To rebuild after board.h is changed, a clean must be done first.
 
# Set the path to our board's root directory
BOARD_SW_ROOT=..
 
include $(BOARD_SW_ROOT)/Makefile.inc
 
all: bootrom.v
 
# Copy the one build in the root software path to here.
bootrom.v: $(SW_ROOT)/bootrom/bootrom.v
$(Q)cp -v $< .
 
export BOARD_PATH
 
# Pass BOARD_PATH so the Make script in the root software path knows we're to
# use our board.h file, not theirs.
$(SW_ROOT)/bootrom/bootrom.v:
$(Q)$(MAKE) -C $(SW_ROOT)/bootrom bootrom.v
 
clean:
$(Q)rm -f *.o *.bin *.hex *.in *.dis *.v
$(Q)$(MAKE) -C $(SW_ROOT)/bootrom clean
 
/boards/xilinx/ml501/sw/Makefile.inc
0,0 → 1,26
 
# Expecting BOARD_SW_ROOT already set to indicate how far below directory we're
# in the board's software root path is.
 
# Root from the board's sw/ path
PROJ_ROOT=../../../..
 
# Figure out actual path the common software directory
SW_ROOT=$(BOARD_SW_ROOT)/$(PROJ_ROOT)/sw
 
# Set the BOARD_PATH to point to the root of this board build
BOARD_PATH=$(shell pwd)/$(BOARD_SW_ROOT)/..
 
# Set RTL_VERILOG_INCLUDE_DIR so software
RTL_VERILOG_INCLUDE_DIR=$(BOARD_PATH)/rtl/verilog/include
 
# Set the processor capability flags
# This doesn't work! :-( Need to figure out way to set these and have them
# carry through to things like the liborpsoc driver modules etc.
#MARCH_FLAGS =-mhard-mul -mhard-div -msoft-float
#MARCH_FLAGS =-mhard-mul -msoft-div -msoft-float
#export MARCH_FLAGS
 
# Finally include the main software include file
 
include $(SW_ROOT)/Makefile.inc
/boards/xilinx/ml501/sw/board/include/board.h
0,0 → 1,60
#ifndef _BOARD_H_
#define _BOARD_H_
 
#define IN_CLK 50000000 // Hz
//#define IN_CLK 32000000 // Hz
//#define IN_CLK 30000000 // HZ
//#define IN_CLK 24000000 // HZ
//#define IN_CLK 20000000 // HZ
//#define IN_CLK 18000000 // HZ
//#define IN_CLK 16000000 // HZ
 
//
// ROM bootloader
//
// Uncomment the appropriate bootloader define. This will effect the bootrom.S
// file, which is compiled and converted into Verilog for inclusion at
// synthesis time. See bootloader/bootloader.S for details on each option.
 
//#define BOOTROM_SPI_FLASH
#define BOOTROM_GOTO_RESET
//#define BOOTROM_LOOP_AT_ZERO
//#define BOOTROM_LOOP_IN_ROM
 
//
// Defines for each core (memory map base, OR1200 interrupt line number, etc.)
//
#define SDRAM_BASE 0x0
 
#define GPIO_0_BASE 0x91000000
 
#define UART0_BASE 0x90000000
#define UART0_IRQ 2
#define UART0_BAUD_RATE 115200
 
 
#define SPI0_BASE 0xb0000000
#define SPI0_IRQ 6
 
#define I2C_0_BASE 0xa0000000
#define I2C_0_IRQ 10
 
#define I2C_1_BASE 0xa1000000
#define I2C_1_IRQ 11
 
#define ETH0_BASE 0x92000000
#define ETH0_IRQ 4
 
#define ETH_MACADDR0 0x00
#define ETH_MACADDR1 0x12
#define ETH_MACADDR2 0x34
#define ETH_MACADDR3 0x56
#define ETH_MACADDR4 0x78
#define ETH_MACADDR5 0x9a
 
//
// OR1200 tick timer period define
//
#define TICKS_PER_SEC 100
 
#endif
/boards/xilinx/ml501/README
0,0 → 1,59
Xilinx ML501 board build
 
This board contains a Xilinx Virtex5 LX50 part. The key supported features in board build are the DDR2 SODIMM, the ZBT SRAM and the Ethernet MAC (only 10/100, no Gigabit support). Additionally configured features of the ML501 include the GPIO and UART.
 
For more information on the ML501, see Xilinx's page: http://www.xilinx.com/products/devkits/HW-V5-ML501-UNI-G.htm
 
Configuring the build:
 
The Verilog include file rtl/ml501_defines.v contains the defines which control how the RTL is configured. This is where the desired memory controller, and internal blockRAM memory configuration is set, as well as which peripherals to include. See that file for further details.
 
There are seperate defines files for each of the componenets in ORPSoC also included in the board's RTL directory, allowing an individual configuration of the OR1200, ethernet and Wishbone arbiter for this board.
 
How to simulate:
 
Ensure the Xilinx tools are installed on your system and their path is configured in the board/tools.inc file.
 
Mentor Graphics' Modelsim is required to perform the simulations (Icarus Verilog cannot compile the Xilinx libraries).
 
Go into boards/xilinx/ml501/sim/run and do a "make rtl-board-tests". This will start a loop which will run 3 tests, a boot test (UART printout, simulation may take several minutes to complete), a memory test, testing the selected memory controller, and a GPIO test. To see VCD dumps of these tests, also set "VCD=1" when running the tests. If any changes were made to the RTL configuration, it's recommended a clean is run before re-running the simulations.
 
How to synthesize:
 
It is possible to run a single make command to run the flow from RTL synthesis through to programming file generation. To do this, go to the par/ directory and run "make ml501.bit".
 
The design is configured with the DDR2 SDRAM controller, ethernet MAC, and GPIO enabled by default. If any of these are disabled, or say the ZBT SRAM controller is used instead of the DDR2, the Xilinx mapper will fail when attemping to assign pins to nonexistant ports on the design. The UCF will need to be changed to fix this, so edit the par/ml501_xst.ucf UCF file, commenting or uncommenting, as necessary, the required clearly-marked sections.
 
The resulting FPGA .bit file can be downloaded and is configured to run the sw/boot program on reset (as long as that section of the memory has not been written over.)
 
Debugging on the board:
 
The standard OpenRISC debug interface, controlled via the JTAG bus, is included in this design. A seperate JTAG TAP is included with ORPSoC and is used in this build, its pins connected to the expansion header, J4 (the middle column), in the following order:
Pin 2: UART Rx
Pin 4: UART Tx
Pin 6: JTAG Tdo
Pin 8: JTAG Tdi
Pin 10: JTAG Tms
Pin 12: JTAG Tck
 
This debugging interface has been tested with the ORSoC debug cable and seen to work. These UART pins go to the same UART as the 9-pin DSUB connector, either one can be used for the UART interface.
 
To do:
 
Notes:
 
* The design currently runs the Wishbone bus and processor at 50MHz, the ZBT SRAM at 200MHz, the DDR2 SDRAM at 266 MHz. There are a few multi-cycle paths in the design for these memory controllers and these are defined in the UCF.
 
* The DDR2 SDRAM controller was generated using the Xilinx Memory Interface Generator (MIG) tool and has been modified slightly. The small cache RAM that sits between the DDR2 MIG controller and Wishbone interface must convert from 128-bit wide 266MHz domain generated memory signals to the 32-bit wide Wishbone domain words, and to do this another Xilinx Coregen blockRAM setup has been used. The RTL instantiating it is in the rtl/ path and the NGC is included in the syn/ path.
 
* The mapper complains that the debug interface's JTAG tck signal isn't going on on an optimal pin, but we override that. So far it has not been seen to exhibit any problematic effects.
 
* There are several errors reported in the timing report, after place and route, related to some clock domain crossover signals in the ethernet MAC core. Despite timing ignore (TIG) markings in the UCF these remain. Please contact the maintainer if this looks like it really is an issue, or can be solved somehow.
 
* As the Ethernet MAC core is only 10/100, it cannot handle gigabit mode. There is software included which resets the Marvell ethernet PHY and disables advertisement of gigabit capability.
 
* There is a user-driven reset feature, meaning the user is able to reset the system by accessing any address starting at 0xe0000000. For this to be enabled, however, the pins 62 and 64 on expansion header J4 (bottom two pins on same column as JTAG debug pins) must be connected. This is useful for debugging the system and not requiring that the reset button be pushed to restart it.
 
* A post-synthesis netlist can be made by going so syn/ and running "make ml501.v", and a post-PAR netlist can be made by going to par/ and running "make ml501.netlist". It is possible to run the post-synthesis simulation in sim/run/ running "make syn-board-test", however no target for post-PAR netlist simulation exists yet, although it shouldn't be too hard to configure.
 
Maintained by Julius Baxter, julius.baxter@orsoc.se
/boards/README
0,0 → 1,15
ORPSoCv2 board builds
 
This directory contains scripts and support RTL for synthesizing ORPSoC to run on various vendors' FPGAs and boards.
 
The directory hierarchy should first be organised by target FPGA vendor, and then by board model. Various configurations for each board may exist, and it's up to the maintainer of the board support to decide how that is handled (either several different make targets, or user modifiable scripts/constraints.)
 
The boards/tools.inc file:
 
This file contains various paths to vendor-specific FPGA development tools. It can be included in any Makefile used to synthesize the design, and is designed to provide a single place where users can set their own paths to tools, rather than having several hard-set paths throughout the scripts.
 
Add path variables to this file if it's likely a user will need to supply their own due to differing installation locations of tools.
 
Board build documentation
 
Please include a readme in each board's path, containing a rundown on the different configurations possible and the commands necessary to start synthesis.

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.