📄 top_func.v
字号:
end //add IO buffers to get out of FPGA OBUF ddr_ba0 (.O(ddr_ba[0]), .I(ddr_ba_o_P1[0] )); OBUF ddr_ba1 (.O(ddr_ba[1]), .I(ddr_ba_o_P1[1] )); wire [11:0] ddr_ad_o_dly = ddr_ad_o_P1; // ddr_addr_io_12.v OBUF ddr_ad0 (.O(ddr_ad[0]), .I(ddr_ad_o_dly[0] )); OBUF ddr_ad1 (.O(ddr_ad[1]), .I(ddr_ad_o_dly[1] )); OBUF ddr_ad2 (.O(ddr_ad[2]), .I(ddr_ad_o_dly[2] )); OBUF ddr_ad3 (.O(ddr_ad[3]), .I(ddr_ad_o_dly[3] )); OBUF ddr_ad4 (.O(ddr_ad[4]), .I(ddr_ad_o_dly[4] )); OBUF ddr_ad5 (.O(ddr_ad[5]), .I(ddr_ad_o_dly[5] )); OBUF ddr_ad6 (.O(ddr_ad[6]), .I(ddr_ad_o_dly[6] )); OBUF ddr_ad7 (.O(ddr_ad[7]), .I(ddr_ad_o_dly[7] )); OBUF ddr_ad8 (.O(ddr_ad[8]), .I(ddr_ad_o_dly[8] )); OBUF ddr_ad9 (.O(ddr_ad[9]), .I(ddr_ad_o_dly[9] )); OBUF ddr_ad10 (.O(ddr_ad[10]), .I(ddr_ad_o_dly[10])); OBUF ddr_ad11 (.O(ddr_ad[11]), .I(ddr_ad_o_dly[11])); //`include "ddr_addr_io_12.v"endmodule // addr_latchmodule brst_cntr ( /*AUTOARG*/ // Outputs brst_end, // Inputs clk, ld_brst ); input clk, ld_brst; output brst_end; reg b_1, brst_end; always @ (posedge clk) begin b_1 <= ~ld_brst; brst_end <= b_1; end endmodule // brst_cntrmodule clk_dlls(/*AUTOARG*/ // Outputs ddr_clk_out, ddr_clk180_out, fpga_clk2x_out, fpga_clk_out, fpga_clk270_out,// fpga_clk90_out, dlls_locked_out, fpga_lac_clk_out, fpga_lac_clk90_out, // Inputs sys_clk_in, sys_clk_fb_in, reset_in ); input sys_clk_in, sys_clk_fb_in, reset_in; output ddr_clk_out, ddr_clk180_out; output fpga_clk2x_out, fpga_clk_out, fpga_clk270_out; output dlls_locked_out; output fpga_lac_clk_out, fpga_lac_clk90_out; //Logic Accessible Clock IBUFG ibufg_sys_clk (.I(sys_clk_in), .O(sys_clk)); IBUFG ibufg_sys_clk_fb (.I(sys_clk_fb_in), .O(sys_clk_fb)); CLKDLL dll_ext (.CLKIN(sys_clk), .CLKFB(sys_clk_fb), .RST(1'b0), .CLK0(ddr_clk_out_o), .CLK90(), .CLK180(), .CLK270(), .CLK2X(), .CLKDV(), .LOCKED(dll_ext_locked)); //dll_int gets CLKIN from ddr_clk //since ddr_clk is not stable until dll_ext achieve lock, //we need to hold dll_int in reset untill dll_ext_lock goes high wire dll_int_reset = ~dll_ext_locked; CLKDLL dll_int (.CLKIN(sys_clk_fb), .CLKFB(fpga_clk_out), .RST(dll_int_reset), .CLK0(fpga_clk_out_o), .CLK90(), .CLK180(), .CLK270(fpga_clk270_out_o), .CLK2X(fpga_clk2x_out_o), .CLKDV(), .LOCKED(dll_int_locked)); OBUF obuf_ddr_clk_out (.I(ddr_clk_out_o), .O(ddr_clk_out)); OBUF obuf_ddr_clk180_out (.I(~ddr_clk_out_o), .O(ddr_clk180_out)); BUFG bufg_clk2x (.I(fpga_clk2x_out_o), .O(fpga_clk2x_out)); BUFG bufg_clk (.I(fpga_clk_out_o),.O(fpga_clk_out)); BUFG bufg_clk270 (.I(fpga_clk270_out_o), .O(fpga_clk270_out)); // BUFG bufg_clk90 (.I(fpga_clk90_out_o), .O(fpga_clk90_out)); assign dlls_locked_out = dll_int_locked & dll_ext_locked; //In data_path module, we need to use clk to select b/t lower and // higher bits of system data and use clk2x to generate double data output //However, the clk signal cannot drive non clock CLB pins in Virtex, so //we need to generate Logic Accessible Clock signals //generate Logic Accessible Clock signals wire #6 sys_clk_dly = sys_clk; //simulate routing delay FD LAC1 (.D(~sys_clk_dly), .C(fpga_clk2x_out), .Q(lac_clk1)); FD LAC2 (.D(~lac_clk1), .C(fpga_clk2x_out), .Q(lac_clk2)); FD LAC3 (.D(~lac_clk2), .C(fpga_clk2x_out), .Q(fpga_lac_clk_out)); //BUFG bufg_lac_clk ( .I(fpga_lac_clk_out_o), .O(fpga_lac_clk_out)); // BUFG bufg_lac_clk90 ( .I(fpga_lac_clk90_out_o), .O(fpga_lac_clk90_out)); FD LAC4 (.D(sys_clk_dly), .C(~fpga_clk2x_out), .Q(lac_clk90_1)); FD LAC5 (.D(~lac_clk90_1), .C(~fpga_clk2x_out), .Q(lac_clk90_2)); FD LAC6 (.D(~lac_clk90_2), .C(~fpga_clk2x_out), .Q(lac_clk90_3)); FD LAC7 (.D(~lac_clk90_3), .C(~fpga_clk2x_out), .Q(lac_clk90_4)); FD LAC8 (.D(~lac_clk90_4), .C(~fpga_clk2x_out), .Q(fpga_lac_clk90_out)); endmodule // clk_dllsmodule controller (/*AUTOARG*/ // Outputs ddr_read_en, ddr_write_en, u_data_valid_en, ddr_dqs_t, ddr_rasb, ddr_casb, ddr_web, ld_burst, ld_rcd, ld_cas_lat, u_ref_ack, mrs_addr, row_addr, // Inputs u_cmd, cntlr_reset1, cntlr_reset2, cntlr_reset3, clk, clk2x, // clk90, lac_clk_in, burst_end, cas_lat_end, rcd_end, burst_8, burst_2 ); output [3:0] ddr_read_en; output [7:0] ddr_write_en; output u_data_valid_en; output ddr_dqs_t; output ddr_rasb, ddr_casb, ddr_web; output ld_burst, ld_rcd, ld_cas_lat; output u_ref_ack; output mrs_addr; output row_addr; input [7:1] u_cmd; input cntlr_reset1, cntlr_reset2, cntlr_reset3; input clk, clk2x, lac_clk_in, burst_end, cas_lat_end, rcd_end; input burst_8, burst_2; reg [2:0] ddr_cmd, next_ddr_cmd; reg [12:1] state, next_state; reg row_addr, ld_cas_lat, ld_burst; reg ld_rcd; reg [7:0] ddr_write_en; reg ddr_dqs_t_wire; reg u_ref_ack; reg mrs_addr; reg ddr_rasb_o, ddr_casb_o, ddr_web_o; wire data_read = state[`CTLR_READ_DATA]; wire data_write = state[`CTLR_WRITE_DATA]; wire data_read_write = data_read || data_write; reg read_cmd; reg read_cmd_reg; //need to register u_cmd[`SYS_READ] because it's needed to generate burst_end after the user has released the READ command /*****************/ /* state machine */ /*****************/ always @ (read_cmd_reg or burst_8 or burst_2 or u_cmd or state or burst_end or cas_lat_end or rcd_end) begin //has default values for outputs so synthesis tool don't infer latches next_state = 12'b0000_0000_0000; read_cmd = 0; casex (1'b1) state[`CTLR_IDLE] : begin casex (1'b1) u_cmd[`SYS_REFRESH]: next_state[`CTLR_REFRESH] = 1; u_cmd[`SYS_PRECHARGE]: next_state[`CTLR_PRECHARGE] = 1; u_cmd[`SYS_LOAD_MR]: next_state[`CTLR_LOAD_MR] = 1; u_cmd[`SYS_WRITE]: next_state[`CTLR_ACT] = 1; u_cmd[`SYS_READ]: begin next_state[`CTLR_ACT] = 1; read_cmd = 1; end default: next_state[`CTLR_IDLE] = 1; endcase end // case: state[`CTLR_IDLE] state[`CTLR_ACT] : //issue ACTIVE command if (rcd_end) begin if (read_cmd_reg) begin next_state[`CTLR_READ] = 1; read_cmd = 1; end else begin next_state[`CTLR_WRITE] =1; end end else begin next_state[`CTLR_ACT_WAIT] = 1; if (read_cmd_reg) read_cmd = 1; end state[`CTLR_ACT_WAIT] : //issue NOP command, wait for rcd_end if (rcd_end) begin if (read_cmd_reg) next_state[`CTLR_READ] = 1; else next_state[`CTLR_WRITE] =1; end else begin next_state[`CTLR_ACT_WAIT] = 1; if (read_cmd_reg) read_cmd = 1; end state[`CTLR_READ] : if (~cas_lat_end) next_state[`CTLR_READ_WAIT] = 1; else next_state[`CTLR_READ_DATA] = 1; state[`CTLR_READ_WAIT] : if (~cas_lat_end) next_state[`CTLR_READ_WAIT] = 1; else if (burst_2) next_state[`CTLR_IDLE] = 1; else next_state[`CTLR_READ_DATA] = 1; state[`CTLR_WRITE] : begin if (burst_2) next_state[`CTLR_IDLE] = 1; else next_state[`CTLR_WRITE_DATA] = 1; end state[`CTLR_READ_DATA] : if (burst_8 && ~burst_end) next_state[`CTLR_READ_DATA] = 1; else next_state[`CTLR_IDLE] = 1; state[`CTLR_WRITE_DATA] : begin if (burst_8 && ~burst_end) next_state[`CTLR_WRITE_DATA] = 1; else begin next_state[`CTLR_IDLE] = 1; end end default : next_state[`CTLR_IDLE] = 1; endcase end /*********************************************/ /* combinatorial next state and output logic */ /*********************************************/ wire next_mrs_addr = u_cmd[`SYS_LOAD_MR]; wire next_row_addr = ~(next_state[`CTLR_PRECHARGE]|| next_state[`CTLR_READ]|| next_state[`CTLR_WRITE]); wire next_ld_cas_lat = ~(state[`CTLR_READ] || state[`CTLR_READ_WAIT]); wire next_ld_burst = ~(state[`CTLR_READ] || state[`CTLR_WRITE] || data_read_write); wire next_ld_rcd = ~(state[`CTLR_ACT] || state[`CTLR_ACT_WAIT]); wire next_u_ref_ack = next_state[`CTLR_REFRESH]; wire next_ddr_rasb_o = ~(state[`CTLR_REFRESH] || state[`CTLR_PRECHARGE] || state[`CTLR_LOAD_MR] || state[`CTLR_ACT]); wire next_ddr_casb_o = ~(state[`CTLR_REFRESH] || state[`CTLR_LOAD_MR] || state[`CTLR_READ] || state[`CTLR_WRITE]); wire next_ddr_web_o = ~(state[`CTLR_PRECHARGE] || state[`CTLR_LOAD_MR] || state[`CTLR_WRITE]); wire next_ddr_write_en = (state[`CTLR_WRITE] || state[`CTLR_WRITE_DATA]); wire next_ddr_read_en = state[`CTLR_READ_WAIT] || state[`CTLR_READ_DATA]; reg next_ddr_read_en_P1, u_data_valid_en; always @(posedge clk) next_ddr_read_en_P1 <= next_ddr_read_en; wire next_u_data_valid_en = burst_8 ? next_state[`CTLR_READ_WAIT] || next_state[`CTLR_READ_DATA]: (next_state[`CTLR_READ_WAIT] || next_ddr_read_en);//for burst of 4 or 2, need to delay u_data_valid_en /******************************/ /* output and state registers */ /******************************/ reg [3:0] ddr_read_en; reg ddr_rasb_o_P1, ddr_casb_o_P1, ddr_web_o_P1; //ddr control signals are generated on negative edge clock to guarantee DDR hold time always @ (negedge clk or posedge cntlr_reset1) begin if (cntlr_reset1) begin ddr_rasb_o <= 1; ddr_casb_o <= 1; ddr_web_o <=1; end else begin ddr_rasb_o <= ddr_rasb_o_P1; ddr_casb_o <= ddr_casb_o_P1; ddr_web_o <= ddr_web_o_P1; end end // always @ (posedge clk or posedge cntlr_reset1) always @ (posedge clk) begin ddr_rasb_o_P1 <= next_ddr_rasb_o; ddr_casb_o_P1 <= next_ddr_casb_o; ddr_web_o_P1 <= next_ddr_web_o; end always @ (posedge clk or posedge cntlr_reset2) begin if (cntlr_reset2) begin state[`CTLR_IDLE] <= 1; state[`CTLR_REFRESH] <= 0; state[`CTLR_PRECHARGE] <= 0; state[`CTLR_LOAD_MR] <= 0; state[`CTLR_ACT] <= 0; state[`CTLR_ACT_WAIT] <= 0; state[`CTLR_READ] <= 0; state[`CTLR_WRITE] <= 0; state[`CTLR_READ_WAIT] <= 0; state[`CTLR_READ_DATA] <= 0; state[`CTLR_WRITE_DATA] <= 0; read_cmd_reg <= 0; end else begin read_cmd_reg <= read_cmd; ddr_read_en <= {4{next_ddr_read_en_P1}}; mrs_addr <= next_mrs_addr; row_addr <= next_row_addr; ld_cas_lat <= next_ld_cas_lat; ld_burst <= next_ld_burst; ld_rcd <= next_ld_rcd; u_ref_ack <= next_u_ref_ack; state <= next_state; u_data_valid_en <= next_u_data_valid_en; end end // always @ (posedge clk) //ddr_write_en is used to enable ddr_dq signals reg next_ddr_write_en_P1; always @(posedge clk) next_ddr_write_en_P1 <= next_ddr_write_en; always @(posedge clk2x) ddr_write_en <= {8{next_ddr_write_en_P1}}; //ddr_dqs_t is used to generate ddr_dqs signals reg ddr_dqs_t_tmp1, ddr_dqs_t_tmp2; always @(posedge clk) begin ddr_dqs_t_tmp1 <= next_ddr_write_en; ddr_dqs_t_tmp2 <= ddr_dqs_t_tmp1; end //create local lac_clk and also generate lac_clk_out FD LAC1 (.D(~lac_clk_in), .C(~clk2x), .Q(lac_clk_out)); FD LAC2 (.D(~lac_clk_in), .C(~clk2x), .Q(lac_clk_wire)); wire #15 lac_clk = lac_clk_wire; reg ddr_dqs_t; always @ (negedge clk2x or posedge cntlr_reset3) if (cntlr_reset3) ddr_dqs_t <= 1; else if (lac_clk) ddr_dqs_t <= ~(ddr_dqs_t_tmp1 || next_ddr_write_en); /* always @ (negedge clk90 or posedge cntlr_reset3) if (cntlr_reset3) ddr_dqs_t <= 1; else if (lac_clk) ddr_dqs_t <= ~(ddr_dqs_t_tmp1 || next_ddr_write_en); */ /********************************************/ /* IO buffers for DDR SDRAM control signals */ /********************************************/ OBUF O_ddr_ras (.O(ddr_rasb), .I(ddr_rasb_o)); OBUF O_ddr_cas (.O(ddr_casb), .I(ddr_casb_o)); OBUF O_ddr_we (.O(ddr_web), .I(ddr_web_o));endmodule // controllermodule cslt_cntr ( cslt_end, cslt_max, clk, clk2x, ld_cslt, cas_lat_half ); input [1:0] cslt_max; input clk, clk2x, ld_cslt, cas_lat_half; output cslt_end; reg [1:0]count; reg cslt_end1_5; //for CAS lat of 1.5 and 2.5, need to delay cslt_end by 1/2 a clk cycle wire cslt_end1 = ~(|count); //cslt_end goes high when count=0 reg cslt_end; always @ (posedge clk) cslt_end <= cas_lat_half ? cslt_end1 : cslt_end1_5; always @ (posedge clk or posedge ld_cslt) if (ld_cslt) count <= (cslt_max); else count <= count - 1; always @ (posedge clk2x) cslt_end1_5 <= cslt_end1; endmodulemodule data_path (/*AUTOARG*/ // Outputs u_data_o, ddr_dqs, u_data_valid, // Inouts ddr_dq, // Inputs u_data_i, ddr_write_en, ddr_dqs_t, ddr_read_en, u_data_valid_en, clk2x, clk, lac_clk_in, cas_lat_half, burst_8, clk270 ); input [`U_DATA_MSB:0] u_data_i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -