├── bench ├── README └── wb_sdram_ctrl_tb.v ├── wb_sdram_ctrl.core └── rtl └── verilog ├── dpram_generic.v ├── bufram.v ├── dpram_altera.v ├── dual_clock_fifo.v ├── wb_sdram_ctrl.v ├── dpram_ecp5.v ├── wb_port_arbiter.v ├── wb_port.v └── sdram_ctrl.v /bench/README: -------------------------------------------------------------------------------- 1 | In order to run the test bench, two additional packages are required 2 | vlog_tb_utils : Adds support for generating VCD files and being able 3 | to abort simulation after a set time 4 | wb_bfm : Wishbone Bus Functional Model that generates wishbone 5 | write/read requests to wb_sdram_ctrl and checks that 6 | the correct data is read back after a write 7 | 8 | Both these packages are available from github.com/openrisc/orpsoc-cores 9 | -------------------------------------------------------------------------------- /wb_sdram_ctrl.core: -------------------------------------------------------------------------------- 1 | CAPI=2: 2 | name : ::wb_sdram_ctrl:0-r4 3 | filesets: 4 | rtl: 5 | files: 6 | - rtl/verilog/wb_port_arbiter.v 7 | - rtl/verilog/bufram.v 8 | - rtl/verilog/dpram_altera.v 9 | - rtl/verilog/dpram_ecp5.v 10 | - rtl/verilog/dpram_generic.v 11 | - rtl/verilog/dual_clock_fifo.v 12 | - rtl/verilog/sdram_ctrl.v 13 | - rtl/verilog/wb_port.v 14 | - rtl/verilog/wb_sdram_ctrl.v 15 | file_type : verilogSource 16 | 17 | tb: 18 | files : [bench/wb_sdram_ctrl_tb.v] 19 | file_type : verilogSource 20 | depend: 21 | [mt48lc16m16a2, ">=vlog_tb_utils-1.0", ">=wb_bfm-1.0"] 22 | 23 | parameters: 24 | transactions: 25 | datatype : int 26 | description : Number of wishbone transactions to run in test bench 27 | paramtype : plusarg 28 | 29 | subtransactions: 30 | datatype : int 31 | description : Number of wishbone transactions to run in test bench 32 | paramtype : plusarg 33 | 34 | seed: 35 | datatype : int 36 | description : Initial random seed 37 | paramtype : plusarg 38 | 39 | technology: 40 | datatype : str 41 | description : Select DPRAM implementation. Legal values are ALTERA, ECP5 or GENERIC (default) 42 | paramtype : vlogparam 43 | 44 | USE_LATTICE_GSR_PUR: 45 | datatype: bool 46 | paramtype : vlogdefine 47 | targets: 48 | default: 49 | filesets: [rtl] 50 | sim: &sim 51 | default_tool : icarus 52 | filesets : [rtl, tb] 53 | parameters : [transactions, subtransactions, seed, technology] 54 | tools: 55 | modelsim: 56 | vlog_options : [-timescale=1ns/1ps] 57 | vsim_options : [-t, 1ps] 58 | toplevel : [wb_sdram_ctrl_tb] 59 | sim_altsyncram: 60 | <<: *sim 61 | parameters : [transactions, subtransactions, seed, technology=ALTERA] 62 | tools: 63 | icarus: 64 | iverilog_options : [-l, $(QUARTUS_ROOTDIR)/eda/sim_lib/altera_mf.v] 65 | modelsim: 66 | vlog_options : [-timescale=1ns/1ps] 67 | vsim_options : [-t, 1ps, -L, altera_mf_ver] 68 | sim_ecp5: 69 | <<: *sim 70 | parameters : [transactions, subtransactions, seed, technology=ECP5, USE_LATTICE_GSR_PUR=true] 71 | tools: 72 | icarus: 73 | iverilog_options : [-y, $(FOUNDRY)/verilog/data/ecp5u] 74 | -------------------------------------------------------------------------------- /rtl/verilog/dpram_generic.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011, Stefan Kristiansson 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and non-source forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in non-source form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * 13 | * THIS WORK IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 17 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | * WORK, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | module dpram_generic #( 27 | parameter ADDR_WIDTH = 3 28 | ) 29 | ( 30 | input clk_a, 31 | input [ADDR_WIDTH-1:0] addr_a, 32 | input [3:0] we_a, 33 | input [31:0] di_a, 34 | output reg [31:0] do_a, 35 | 36 | input clk_b, 37 | input [ADDR_WIDTH-1:0] addr_b, 38 | input [3:0] we_b, 39 | input [31:0] di_b, 40 | output reg [31:0] do_b 41 | ); 42 | 43 | reg [7:0] mem0[(1< 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and non-source forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in non-source form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * 13 | * THIS WORK IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 17 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | * WORK, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | module bufram #( 27 | parameter TECHNOLOGY = "GENERIC", 28 | parameter ADDR_WIDTH = 3 29 | ) 30 | ( 31 | input clk_a, 32 | input [ADDR_WIDTH-1:0] addr_a, 33 | input [3:0] we_a, 34 | input [31:0] di_a, 35 | output [31:0] do_a, 36 | 37 | input clk_b, 38 | input [ADDR_WIDTH-1:0] addr_b, 39 | input [3:0] we_b, 40 | input [31:0] di_b, 41 | output [31:0] do_b 42 | ); 43 | generate 44 | if (TECHNOLOGY == "GENERIC") begin : dpram_generic 45 | dpram_generic #( 46 | .ADDR_WIDTH(ADDR_WIDTH) 47 | ) dpram_generic ( 48 | .clk_a (clk_a), 49 | .addr_a (addr_a), 50 | .we_a (we_a), 51 | .di_a (di_a), 52 | .do_a (do_a), 53 | 54 | .clk_b (clk_b), 55 | .addr_b (addr_b), 56 | .we_b (we_b), 57 | .di_b (di_b), 58 | .do_b (do_b) 59 | ); 60 | end else if (TECHNOLOGY == "ALTERA") begin : dpram_altera 61 | dpram_altera #( 62 | .ADDR_WIDTH(ADDR_WIDTH) 63 | ) dpram_altera ( 64 | .clk_a (clk_a), 65 | .addr_a (addr_a), 66 | .we_a (we_a), 67 | .di_a (di_a), 68 | .do_a (do_a), 69 | 70 | .clk_b (clk_b), 71 | .addr_b (addr_b), 72 | .we_b (we_b), 73 | .di_b (di_b), 74 | .do_b (do_b) 75 | ); 76 | end else if (TECHNOLOGY == "ECP5") begin : dpram_ecp5 77 | dpram_ecp5 #( 78 | .ADDR_WIDTH(ADDR_WIDTH) 79 | ) dpram_ecp5 ( 80 | .clk_a (clk_a), 81 | .addr_a (addr_a), 82 | .we_a (we_a), 83 | .di_a (di_a), 84 | .do_a (do_a), 85 | 86 | .clk_b (clk_b), 87 | .addr_b (addr_b), 88 | .we_b (we_b), 89 | .di_b (di_b), 90 | .do_b (do_b) 91 | ); 92 | end 93 | endgenerate 94 | endmodule 95 | -------------------------------------------------------------------------------- /rtl/verilog/dpram_altera.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011, Stefan Kristiansson 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and non-source forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in non-source form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * 13 | * THIS WORK IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 17 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | * WORK, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | module dpram_altera #( 27 | parameter ADDR_WIDTH = 3 28 | ) 29 | ( 30 | input clk_a, 31 | input [ADDR_WIDTH-1:0] addr_a, 32 | input [3:0] we_a, 33 | input [31:0] di_a, 34 | output [31:0] do_a, 35 | 36 | input clk_b, 37 | input [ADDR_WIDTH-1:0] addr_b, 38 | input [3:0] we_b, 39 | input [31:0] di_b, 40 | output [31:0] do_b 41 | ); 42 | 43 | altsyncram altsyncram_component ( 44 | .byteena_a (we_a), 45 | .clock0 (clk_a), 46 | .wren_a (|we_a), 47 | .address_b ({{(3-(ADDR_WIDTH-1)){1'b0}},addr_b}), 48 | .byteena_b (we_b), 49 | .clock1 (clk_b), 50 | .data_b (di_b), 51 | .wren_b (|we_b), 52 | .address_a ({{(3-(ADDR_WIDTH-1)){1'b0}},addr_a}), 53 | .data_a (di_a), 54 | .q_a (do_a), 55 | .q_b (do_b), 56 | .aclr0 (1'b0), 57 | .aclr1 (1'b0), 58 | .addressstall_a (1'b0), 59 | .addressstall_b (1'b0), 60 | .clocken0 (1'b1), 61 | .clocken1 (1'b1), 62 | .clocken2 (1'b1), 63 | .clocken3 (1'b1), 64 | .eccstatus (), 65 | .rden_a (1'b1), 66 | .rden_b (1'b1)); 67 | defparam 68 | altsyncram_component.address_reg_b = "CLOCK1", 69 | altsyncram_component.byteena_reg_b = "CLOCK1", 70 | altsyncram_component.byte_size = 8, 71 | altsyncram_component.indata_reg_b = "CLOCK1", 72 | altsyncram_component.lpm_type = "altsyncram", 73 | altsyncram_component.numwords_a = 16, 74 | altsyncram_component.numwords_b = 16, 75 | altsyncram_component.operation_mode = "BIDIR_DUAL_PORT", 76 | altsyncram_component.outdata_aclr_a = "NONE", 77 | altsyncram_component.outdata_aclr_b = "NONE", 78 | altsyncram_component.outdata_reg_a = "UNREGISTERED", 79 | altsyncram_component.outdata_reg_b = "UNREGISTERED", 80 | altsyncram_component.power_up_uninitialized = "FALSE", 81 | altsyncram_component.widthad_a = 4, 82 | altsyncram_component.widthad_b = 4, 83 | altsyncram_component.width_a = 32, 84 | altsyncram_component.width_b = 32, 85 | altsyncram_component.width_byteena_a = 4, 86 | altsyncram_component.width_byteena_b = 4, 87 | altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK1"; 88 | endmodule 89 | -------------------------------------------------------------------------------- /rtl/verilog/dual_clock_fifo.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Stefan Kristiansson 3 | * All rights reserved. 4 | * 5 | * Based on vga_fifo_dc.v in Richard Herveille's VGA/LCD core 6 | * Copyright (C) 2001 Richard Herveille 7 | * 8 | * Redistribution and use in source and non-source forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in non-source form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS WORK IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 18 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | * WORK, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | module dual_clock_fifo #( 30 | parameter ADDR_WIDTH = 3, 31 | parameter DATA_WIDTH = 32 32 | ) 33 | ( 34 | input wire wr_rst_i, 35 | input wire wr_clk_i, 36 | input wire wr_en_i, 37 | input wire [DATA_WIDTH-1:0] wr_data_i, 38 | 39 | input wire rd_rst_i, 40 | input wire rd_clk_i, 41 | input wire rd_en_i, 42 | output reg [DATA_WIDTH-1:0] rd_data_o, 43 | 44 | output reg full_o, 45 | output reg empty_o 46 | ); 47 | 48 | reg [ADDR_WIDTH-1:0] wr_addr; 49 | reg [ADDR_WIDTH-1:0] wr_addr_gray; 50 | reg [ADDR_WIDTH-1:0] wr_addr_gray_rd; 51 | reg [ADDR_WIDTH-1:0] wr_addr_gray_rd_r; 52 | reg [ADDR_WIDTH-1:0] rd_addr; 53 | reg [ADDR_WIDTH-1:0] rd_addr_gray; 54 | reg [ADDR_WIDTH-1:0] rd_addr_gray_wr; 55 | reg [ADDR_WIDTH-1:0] rd_addr_gray_wr_r; 56 | 57 | function [ADDR_WIDTH-1:0] gray_conv; 58 | input [ADDR_WIDTH-1:0] in; 59 | begin 60 | gray_conv = {in[ADDR_WIDTH-1], 61 | in[ADDR_WIDTH-2:0] ^ in[ADDR_WIDTH-1:1]}; 62 | end 63 | endfunction 64 | 65 | always @(posedge wr_clk_i) begin 66 | if (wr_rst_i) begin 67 | wr_addr <= 0; 68 | wr_addr_gray <= 0; 69 | end else if (wr_en_i) begin 70 | wr_addr <= wr_addr + 1; 71 | wr_addr_gray <= gray_conv(wr_addr + 1); 72 | end 73 | end 74 | 75 | // synchronize read address to write clock domain 76 | always @(posedge wr_clk_i) begin 77 | rd_addr_gray_wr <= rd_addr_gray; 78 | rd_addr_gray_wr_r <= rd_addr_gray_wr; 79 | end 80 | 81 | always @(posedge wr_clk_i) 82 | if (wr_rst_i) 83 | full_o <= 0; 84 | else if (wr_en_i) 85 | full_o <= gray_conv(wr_addr + 2) == rd_addr_gray_wr_r; 86 | else 87 | full_o <= full_o & (gray_conv(wr_addr + 1) == rd_addr_gray_wr_r); 88 | 89 | always @(posedge rd_clk_i) begin 90 | if (rd_rst_i) begin 91 | rd_addr <= 0; 92 | rd_addr_gray <= 0; 93 | end else if (rd_en_i) begin 94 | rd_addr <= rd_addr + 1'b1; 95 | rd_addr_gray <= gray_conv(rd_addr + 1'b1); 96 | end 97 | end 98 | 99 | // synchronize write address to read clock domain 100 | always @(posedge rd_clk_i) begin 101 | wr_addr_gray_rd <= wr_addr_gray; 102 | wr_addr_gray_rd_r <= wr_addr_gray_rd; 103 | end 104 | 105 | always @(posedge rd_clk_i) 106 | if (rd_rst_i) 107 | empty_o <= 1'b1; 108 | else if (rd_en_i) 109 | empty_o <= gray_conv(rd_addr + 1) == wr_addr_gray_rd_r; 110 | else 111 | empty_o <= empty_o & (gray_conv(rd_addr) == wr_addr_gray_rd_r); 112 | 113 | // generate dual clocked memory 114 | reg [DATA_WIDTH-1:0] mem[(1< 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and non-source forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in non-source form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * 13 | * THIS WORK IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 17 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | * WORK, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | module wb_sdram_ctrl #( 27 | parameter TECHNOLOGY = "GENERIC", 28 | parameter CLK_FREQ_MHZ = 100, // sdram_clk freq in MHZ 29 | parameter POWERUP_DELAY = 200, // power up delay in us 30 | parameter REFRESH_MS = 64, // time to wait between refreshes in ms 31 | parameter BURST_LENGTH = 8, // 0, 1, 2, 4 or 8 (0 = full page) 32 | parameter WB_PORTS = 3, // Number of wishbone ports 33 | parameter BUF_WIDTH = 3, // Buffer size = 2^BUF_WIDTH 34 | parameter ROW_WIDTH = 13, // Row width 35 | parameter COL_WIDTH = 9, // Column width 36 | parameter BA_WIDTH = 2, // Ba width 37 | parameter tCAC = 2, // CAS Latency 38 | parameter tRAC = 5, // RAS Latency 39 | parameter tRP = 2, // Command Period (PRE to ACT) 40 | parameter tRC = 7, // Command Period (REF to REF / ACT to ACT) 41 | parameter tMRD = 2 // Mode Register Set To Command Delay time 42 | ) 43 | ( 44 | // SDRAM interface 45 | input sdram_rst, 46 | input sdram_clk, 47 | output [BA_WIDTH-1:0] ba_pad_o, 48 | output [12:0] a_pad_o, 49 | output cs_n_pad_o, 50 | output ras_pad_o, 51 | output cas_pad_o, 52 | output we_pad_o, 53 | output [15:0] dq_o, 54 | output [1:0] dqm_pad_o, 55 | input [15:0] dq_i, 56 | output dq_oe, 57 | output cke_pad_o, 58 | 59 | // Wishbone interface 60 | input wb_clk, 61 | input wb_rst, 62 | input [WB_PORTS*32-1:0] wb_adr_i, 63 | input [WB_PORTS-1:0] wb_stb_i, 64 | input [WB_PORTS-1:0] wb_cyc_i, 65 | input [WB_PORTS*3-1:0] wb_cti_i, 66 | input [WB_PORTS*2-1:0] wb_bte_i, 67 | input [WB_PORTS-1:0] wb_we_i, 68 | input [WB_PORTS*4-1:0] wb_sel_i, 69 | input [WB_PORTS*32-1:0] wb_dat_i, 70 | output [WB_PORTS*32-1:0] wb_dat_o, 71 | output [WB_PORTS-1:0] wb_ack_o 72 | ); 73 | 74 | wire sdram_if_idle; 75 | wire [31:0] sdram_if_adr_i; 76 | wire [31:0] sdram_if_adr_o; 77 | wire [15:0] sdram_if_dat_i; 78 | wire [15:0] sdram_if_dat_o; 79 | wire [1:0] sdram_if_sel_i; 80 | wire sdram_if_acc; 81 | wire sdram_if_we; 82 | wire sdram_if_ack; 83 | 84 | sdram_ctrl #( 85 | .CLK_FREQ_MHZ (CLK_FREQ_MHZ), 86 | .POWERUP_DELAY (POWERUP_DELAY), 87 | .REFRESH_MS (REFRESH_MS), 88 | .BURST_LENGTH (BURST_LENGTH), 89 | .ROW_WIDTH (ROW_WIDTH), 90 | .COL_WIDTH (COL_WIDTH), 91 | .BA_WIDTH (BA_WIDTH), 92 | .tCAC (tCAC), 93 | .tRAC (tRAC), 94 | .tRP (tRP), 95 | .tRC (tRC), 96 | .tMRD (tMRD) 97 | ) 98 | sdram_ctrl ( 99 | // SDRAM interface 100 | .sdram_rst (sdram_rst), 101 | .sdram_clk (sdram_clk), 102 | .ba_o (ba_pad_o), 103 | .a_o (a_pad_o), 104 | .cs_n_o (cs_n_pad_o), 105 | .ras_o (ras_pad_o), 106 | .cas_o (cas_pad_o), 107 | .we_o (we_pad_o), 108 | .dq_o (dq_o), 109 | .dqm_o (dqm_pad_o), 110 | .dq_i (dq_i), 111 | .dq_oe_o (dq_oe), 112 | .cke_o (cke_pad_o), 113 | // Internal interface 114 | .idle_o (sdram_if_idle), 115 | .adr_i (sdram_if_adr_i), 116 | .adr_o (sdram_if_adr_o), 117 | .dat_i (sdram_if_dat_i), 118 | .dat_o (sdram_if_dat_o), 119 | .sel_i (sdram_if_sel_i), 120 | .acc_i (sdram_if_acc), 121 | .ack_o (sdram_if_ack), 122 | .we_i (sdram_if_we) 123 | ); 124 | 125 | wb_port_arbiter #( 126 | .TECHNOLOGY (TECHNOLOGY), 127 | .WB_PORTS (WB_PORTS), 128 | .BUF_WIDTH (BUF_WIDTH) 129 | ) 130 | wb_port_arbiter ( 131 | .wb_clk (wb_clk), 132 | .wb_rst (wb_rst), 133 | 134 | .wb_adr_i (wb_adr_i), 135 | .wb_stb_i (wb_stb_i), 136 | .wb_cyc_i (wb_cyc_i), 137 | .wb_cti_i (wb_cti_i), 138 | .wb_bte_i (wb_bte_i), 139 | .wb_we_i (wb_we_i), 140 | .wb_sel_i (wb_sel_i), 141 | .wb_dat_i (wb_dat_i), 142 | .wb_dat_o (wb_dat_o), 143 | .wb_ack_o (wb_ack_o), 144 | 145 | // Internal interface 146 | .sdram_rst (sdram_rst), 147 | .sdram_clk (sdram_clk), 148 | .sdram_idle_i (sdram_if_idle), 149 | .adr_i (sdram_if_adr_o), 150 | .adr_o (sdram_if_adr_i), 151 | .dat_i (sdram_if_dat_o), 152 | .dat_o (sdram_if_dat_i), 153 | .sel_o (sdram_if_sel_i), 154 | .acc_o (sdram_if_acc), 155 | .ack_i (sdram_if_ack), 156 | .we_o (sdram_if_we) 157 | ); 158 | endmodule 159 | -------------------------------------------------------------------------------- /bench/wb_sdram_ctrl_tb.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013, Olof Kindgren 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and non-source forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in non-source form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * 13 | * THIS WORK IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 17 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | * WORK, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | module wb_sdram_ctrl_tb; 27 | 28 | parameter technology = "GENERIC"; 29 | 30 | localparam MEMORY_SIZE_WORDS = 4096; 31 | 32 | localparam WB_PORTS = 3; 33 | 34 | localparam BA_WIDTH = 2; 35 | 36 | vlog_tb_utils vlog_tb_utils0(); 37 | 38 | reg wbm_rst = 1'b1; 39 | 40 | reg wb_clk = 1'b1; 41 | reg wb_rst = 1'b1; 42 | 43 | reg sdram_clk = 1'b1; 44 | reg sdram_rst = 1'b1; 45 | 46 | `ifdef USE_LATTICE_GSR_PUR 47 | GSR GSR_INST(.GSR (sdram_rst)); 48 | PUR PUR_INST(.PUR (sdram_rst)); 49 | `endif 50 | 51 | initial #1800000 wbm_rst <= 1'b0; 52 | 53 | initial #200000 wb_rst <= 1'b0; 54 | always #10000 wb_clk <= !wb_clk; 55 | 56 | initial #100000 sdram_rst <= 1'b0; 57 | always #5000 sdram_clk <= !sdram_clk; 58 | 59 | assign #1 sdram_clk_d = sdram_clk; 60 | 61 | wire [BA_WIDTH-1:0] ba; 62 | wire [12:0] a; 63 | wire cs_n; 64 | wire ras; 65 | wire cas; 66 | wire we; 67 | wire [15:0] dq_o; 68 | wire [1:0] dqm; 69 | wire [15:0] dq_i; 70 | wire dq_oe; 71 | wire cke; 72 | 73 | wire [15:0] dq; 74 | 75 | wire [WB_PORTS*32-1:0] wb_adr; 76 | wire [WB_PORTS-1:0] wb_stb; 77 | wire [WB_PORTS-1:0] wb_cyc; 78 | wire [WB_PORTS*3-1:0] wb_cti; 79 | wire [WB_PORTS*2-1:0] wb_bte; 80 | wire [WB_PORTS-1:0] wb_we; 81 | wire [WB_PORTS*4-1:0] wb_sel; 82 | wire [WB_PORTS*32-1:0] wb_dat; 83 | wire [WB_PORTS*32-1:0] wb_rdt; 84 | wire [WB_PORTS-1:0] wb_ack; 85 | 86 | wire [31:0] slave_writes; 87 | wire [31:0] slave_reads; 88 | wire [WB_PORTS-1:0] done_int; 89 | 90 | genvar i; 91 | 92 | integer TRANSACTIONS; 93 | integer SUBTRANSACTIONS; 94 | integer SEED; 95 | 96 | generate 97 | for(i=0;i 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and non-source forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in non-source form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * 13 | * THIS WORK IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 17 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | * WORK, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | module dpram_ecp5 #( 27 | parameter ADDR_WIDTH = 3 28 | ) 29 | ( 30 | input clk_a, 31 | input [ADDR_WIDTH-1:0] addr_a, 32 | input [3:0] we_a, 33 | input [31:0] di_a, 34 | output [31:0] do_a, 35 | 36 | input clk_b, 37 | input [ADDR_WIDTH-1:0] addr_b, 38 | input [3:0] we_b, 39 | input [31:0] di_b, 40 | output [31:0] do_b 41 | ); 42 | 43 | wire [9:0] ada_ext = addr_a, adb_ext = addr_b; 44 | wire [17:0] dia_1 = {1'b0, di_a[15:8], 1'b0, di_a[7:0]}; 45 | wire [17:0] dib_1 = {1'b0, di_b[15:8], 1'b0, di_b[7:0]}; 46 | wire [17:0] dia_2 = {1'b0, di_a[31:24], 1'b0, di_a[23:16]}; 47 | wire [17:0] dib_2 = {1'b0, di_b[31:24], 1'b0, di_b[23:16]}; 48 | wire [17:0] doa_1, dob_1, doa_2, dob_2; 49 | 50 | assign do_a[7:0] = doa_1[7:0]; 51 | assign do_a[15:8] = doa_1[16:9]; 52 | assign do_a[23:16] = doa_2[7:0]; 53 | assign do_a[31:24] = doa_2[16:9]; 54 | 55 | assign do_b[7:0] = dob_1[7:0]; 56 | assign do_b[15:8] = dob_1[16:9]; 57 | assign do_b[23:16] = dob_2[7:0]; 58 | assign do_b[31:24] = dob_2[16:9]; 59 | 60 | DP16KD #( 61 | .DATA_WIDTH_A(18), 62 | .DATA_WIDTH_B(18), 63 | .WRITEMODE_A("READBEFOREWRITE"), 64 | .WRITEMODE_B("READBEFOREWRITE"), 65 | .GSR("DISABLED") 66 | ) dpram_1 ( 67 | .ADA0(we_a[0]), .ADA1(we_a[1]), .ADA2(1'b0), .ADA3(1'b0), .ADA4(ada_ext[0]), .ADA5(ada_ext[1]), .ADA6(ada_ext[2]), .ADA7(ada_ext[3]), .ADA8(ada_ext[4]), .ADA9(ada_ext[5]), .ADA10(ada_ext[6]), .ADA11(ada_ext[7]), .ADA12(ada_ext[8]), .ADA13(ada_ext[9]), 68 | .ADB0(we_b[0]), .ADB1(we_b[1]), .ADB2(1'b0), .ADB3(1'b0), .ADB4(adb_ext[0]), .ADB5(adb_ext[1]), .ADB6(adb_ext[2]), .ADB7(adb_ext[3]), .ADB8(adb_ext[4]), .ADB9(adb_ext[5]), .ADB10(adb_ext[6]), .ADB11(adb_ext[7]), .ADB12(adb_ext[8]), .ADB13(adb_ext[9]), 69 | .DIA0(dia_1[0]), .DIA1(dia_1[1]), .DIA2(dia_1[2]), .DIA3(dia_1[3]), .DIA4(dia_1[4]), .DIA5(dia_1[5]), .DIA6(dia_1[6]), .DIA7(dia_1[7]), .DIA8(dia_1[8]), .DIA9(dia_1[9]), .DIA10(dia_1[10]), .DIA11(dia_1[11]), .DIA12(dia_1[12]), .DIA13(dia_1[13]), .DIA14(dia_1[14]), .DIA15(dia_1[15]), .DIA16(dia_1[16]), .DIA17(dia_1[17]), 70 | .DIB0(dib_1[0]), .DIB1(dib_1[1]), .DIB2(dib_1[2]), .DIB3(dib_1[3]), .DIB4(dib_1[4]), .DIB5(dib_1[5]), .DIB6(dib_1[6]), .DIB7(dib_1[7]), .DIB8(dib_1[8]), .DIB9(dib_1[9]), .DIB10(dib_1[10]), .DIB11(dib_1[11]), .DIB12(dib_1[12]), .DIB13(dib_1[13]), .DIB14(dib_1[14]), .DIB15(dib_1[15]), .DIB16(dib_1[16]), .DIB17(dib_1[17]), 71 | .DOA0(doa_1[0]), .DOA1(doa_1[1]), .DOA2(doa_1[2]), .DOA3(doa_1[3]), .DOA4(doa_1[4]), .DOA5(doa_1[5]), .DOA6(doa_1[6]), .DOA7(doa_1[7]), .DOA8(doa_1[8]), .DOA9(doa_1[9]), .DOA10(doa_1[10]), .DOA11(doa_1[11]), .DOA12(doa_1[12]), .DOA13(doa_1[13]), .DOA14(doa_1[14]), .DOA15(doa_1[15]), .DOA16(doa_1[16]), .DOA17(doa_1[17]), 72 | .DOB0(dob_1[0]), .DOB1(dob_1[1]), .DOB2(dob_1[2]), .DOB3(dob_1[3]), .DOB4(dob_1[4]), .DOB5(dob_1[5]), .DOB6(dob_1[6]), .DOB7(dob_1[7]), .DOB8(dob_1[8]), .DOB9(dob_1[9]), .DOB10(dob_1[10]), .DOB11(dob_1[11]), .DOB12(dob_1[12]), .DOB13(dob_1[13]), .DOB14(dob_1[14]), .DOB15(dob_1[15]), .DOB16(dob_1[16]), .DOB17(dob_1[17]), 73 | .CLKA(clk_a), .CLKB(clk_b), 74 | .WEA(|we_a), .CEA(1'b1), .OCEA(1'b1), 75 | .WEB(|we_b), .CEB(1'b1), .OCEB(1'b1), 76 | .CSA2 (1'b0), .CSA1 (1'b0), .CSA0 (1'b0), .CSB2 (1'b0), .CSB1 (1'b0), .CSB0 (1'b0), 77 | .RSTA(1'b0), .RSTB(1'b0) 78 | ); 79 | 80 | DP16KD #( 81 | .DATA_WIDTH_A(18), 82 | .DATA_WIDTH_B(18), 83 | .WRITEMODE_A("READBEFOREWRITE"), 84 | .WRITEMODE_B("READBEFOREWRITE"), 85 | .GSR("DISABLED") 86 | ) dpram_2 ( 87 | .ADA0(we_a[2]), .ADA1(we_a[3]), .ADA2(1'b0), .ADA3(1'b0), .ADA4(ada_ext[0]), .ADA5(ada_ext[1]), .ADA6(ada_ext[2]), .ADA7(ada_ext[3]), .ADA8(ada_ext[4]), .ADA9(ada_ext[5]), .ADA10(ada_ext[6]), .ADA11(ada_ext[7]), .ADA12(ada_ext[8]), .ADA13(ada_ext[9]), 88 | .ADB0(we_b[2]), .ADB1(we_b[3]), .ADB2(1'b0), .ADB3(1'b0), .ADB4(adb_ext[0]), .ADB5(adb_ext[1]), .ADB6(adb_ext[2]), .ADB7(adb_ext[3]), .ADB8(adb_ext[4]), .ADB9(adb_ext[5]), .ADB10(adb_ext[6]), .ADB11(adb_ext[7]), .ADB12(adb_ext[8]), .ADB13(adb_ext[9]), 89 | .DIA0(dia_2[0]), .DIA1(dia_2[1]), .DIA2(dia_2[2]), .DIA3(dia_2[3]), .DIA4(dia_2[4]), .DIA5(dia_2[5]), .DIA6(dia_2[6]), .DIA7(dia_2[7]), .DIA8(dia_2[8]), .DIA9(dia_2[9]), .DIA10(dia_2[10]), .DIA11(dia_2[11]), .DIA12(dia_2[12]), .DIA13(dia_2[13]), .DIA14(dia_2[14]), .DIA15(dia_2[15]), .DIA16(dia_2[16]), .DIA17(dia_2[17]), 90 | .DIB0(dib_2[0]), .DIB1(dib_2[1]), .DIB2(dib_2[2]), .DIB3(dib_2[3]), .DIB4(dib_2[4]), .DIB5(dib_2[5]), .DIB6(dib_2[6]), .DIB7(dib_2[7]), .DIB8(dib_2[8]), .DIB9(dib_2[9]), .DIB10(dib_2[10]), .DIB11(dib_2[11]), .DIB12(dib_2[12]), .DIB13(dib_2[13]), .DIB14(dib_2[14]), .DIB15(dib_2[15]), .DIB16(dib_2[16]), .DIB17(dib_2[17]), 91 | .DOA0(doa_2[0]), .DOA1(doa_2[1]), .DOA2(doa_2[2]), .DOA3(doa_2[3]), .DOA4(doa_2[4]), .DOA5(doa_2[5]), .DOA6(doa_2[6]), .DOA7(doa_2[7]), .DOA8(doa_2[8]), .DOA9(doa_2[9]), .DOA10(doa_2[10]), .DOA11(doa_2[11]), .DOA12(doa_2[12]), .DOA13(doa_2[13]), .DOA14(doa_2[14]), .DOA15(doa_2[15]), .DOA16(doa_2[16]), .DOA17(doa_2[17]), 92 | .DOB0(dob_2[0]), .DOB1(dob_2[1]), .DOB2(dob_2[2]), .DOB3(dob_2[3]), .DOB4(dob_2[4]), .DOB5(dob_2[5]), .DOB6(dob_2[6]), .DOB7(dob_2[7]), .DOB8(dob_2[8]), .DOB9(dob_2[9]), .DOB10(dob_2[10]), .DOB11(dob_2[11]), .DOB12(dob_2[12]), .DOB13(dob_2[13]), .DOB14(dob_2[14]), .DOB15(dob_2[15]), .DOB16(dob_2[16]), .DOB17(dob_2[17]), 93 | .CLKA(clk_a), .CLKB(clk_b), 94 | .WEA(|we_a), .CEA(1'b1), .OCEA(1'b1), 95 | .WEB(|we_b), .CEB(1'b1), .OCEB(1'b1), 96 | .CSA2 (1'b0), .CSA1 (1'b0), .CSA0 (1'b0), .CSB2 (1'b0), .CSB1 (1'b0), .CSB0 (1'b0), 97 | .RSTA(1'b0), .RSTB(1'b0) 98 | ); 99 | 100 | endmodule 101 | -------------------------------------------------------------------------------- /rtl/verilog/wb_port_arbiter.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011, Stefan Kristiansson 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and non-source forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in non-source form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * 13 | * THIS WORK IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 17 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | * WORK, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | module wb_port_arbiter #( 27 | parameter TECHNOLOGY = "GENERIC", 28 | parameter WB_PORTS = 3, 29 | parameter BUF_WIDTH = 3 30 | ) 31 | ( 32 | // Wishbone 33 | input wb_clk, 34 | input wb_rst, 35 | input [WB_PORTS*32-1:0] wb_adr_i, 36 | input [WB_PORTS-1:0] wb_stb_i, 37 | input [WB_PORTS-1:0] wb_cyc_i, 38 | input [WB_PORTS*3-1:0] wb_cti_i, 39 | input [WB_PORTS*2-1:0] wb_bte_i, 40 | input [WB_PORTS-1:0] wb_we_i, 41 | input [WB_PORTS*4-1:0] wb_sel_i, 42 | input [WB_PORTS*32-1:0] wb_dat_i, 43 | output [WB_PORTS*32-1:0] wb_dat_o, 44 | output [WB_PORTS-1:0] wb_ack_o, 45 | 46 | // Internal interface 47 | input sdram_rst, 48 | input sdram_clk, 49 | input sdram_idle_i, 50 | input [31:0] adr_i, 51 | output [31:0] adr_o, 52 | input [15:0] dat_i, 53 | output [15:0] dat_o, 54 | output [1:0] sel_o, 55 | output acc_o, 56 | input ack_i, 57 | output we_o 58 | ); 59 | 60 | wire [31:0] wbp_adr_i[WB_PORTS-1:0]; 61 | wire wbp_stb_i[WB_PORTS-1:0]; 62 | wire wbp_cyc_i[WB_PORTS-1:0]; 63 | wire [2:0] wbp_cti_i[WB_PORTS-1:0]; 64 | wire [1:0] wbp_bte_i[WB_PORTS-1:0]; 65 | wire wbp_we_i[WB_PORTS-1:0]; 66 | wire [3:0] wbp_sel_i[WB_PORTS-1:0]; 67 | wire [31:0] wbp_dat_i[WB_PORTS-1:0]; 68 | wire [31:0] wbp_dat_o[WB_PORTS-1:0]; 69 | wire wbp_ack_o[WB_PORTS-1:0]; 70 | 71 | wire wb_cycle[WB_PORTS-1:0]; 72 | 73 | wire [31:0] p_adr_i[WB_PORTS-1:0]; 74 | wire [31:0] p_adr_o[WB_PORTS-1:0]; 75 | wire [15:0] p_dat_i[WB_PORTS-1:0]; 76 | wire [15:0] p_dat_o[WB_PORTS-1:0]; 77 | wire [1:0] p_sel_o[WB_PORTS-1:0]; 78 | wire [WB_PORTS-1:0] p_acc_o; 79 | wire p_ack_i[WB_PORTS-1:0]; 80 | wire p_we_o[WB_PORTS-1:0]; 81 | 82 | reg [31:0] p_bufw_adr[WB_PORTS-1:0]; 83 | reg [31:0] p_bufw_dat[WB_PORTS-1:0]; 84 | reg [3:0] p_bufw_sel[WB_PORTS-1:0]; 85 | reg p_bufw_we[WB_PORTS-1:0]; 86 | 87 | reg [WB_PORTS-1:0] port_sel; 88 | reg [WB_PORTS-1:0] port_enc; 89 | 90 | wire safe_to_switch; 91 | 92 | genvar i; 93 | generate 94 | for (i = 0; i < WB_PORTS; i=i+1) begin : wbports 95 | assign wbp_adr_i[i] = wb_adr_i[31+i*32:i*32]; 96 | assign wbp_stb_i[i] = wb_stb_i[i]; 97 | assign wbp_cyc_i[i] = wb_cyc_i[i]; 98 | assign wbp_cti_i[i] = wb_cti_i[2+i*3:i*3]; 99 | assign wbp_bte_i[i] = wb_bte_i[1+i*2:i*2]; 100 | assign wbp_we_i[i] = wb_we_i[i]; 101 | assign wbp_sel_i[i] = wb_sel_i[3+i*4:i*4]; 102 | assign wbp_dat_i[i] = wb_dat_i[31+i*32:i*32]; 103 | assign wb_dat_o[31+i*32:i*32] = wbp_dat_o[i]; 104 | assign wb_ack_o[i] = wbp_ack_o[i]; 105 | assign wb_cycle[i] = wb_cyc_i[i] & wb_stb_i[i]; 106 | 107 | assign p_adr_i[i] = adr_i; 108 | assign p_dat_i[i] = dat_i; 109 | assign p_ack_i[i] = ack_i & port_sel[i]; 110 | 111 | wb_port #( 112 | .TECHNOLOGY (TECHNOLOGY), 113 | .BUF_WIDTH (BUF_WIDTH) 114 | ) 115 | wb_port ( 116 | // Wishbone 117 | .wb_clk (wb_clk), 118 | .wb_rst (wb_rst), 119 | .wb_adr_i (wbp_adr_i[i]), 120 | .wb_stb_i (wbp_stb_i[i]), 121 | .wb_cyc_i (wbp_cyc_i[i]), 122 | .wb_cti_i (wbp_cti_i[i]), 123 | .wb_bte_i (wbp_bte_i[i]), 124 | .wb_we_i (wbp_we_i[i]), 125 | .wb_sel_i (wbp_sel_i[i]), 126 | .wb_dat_i (wbp_dat_i[i]), 127 | .wb_dat_o (wbp_dat_o[i]), 128 | .wb_ack_o (wbp_ack_o[i]), 129 | 130 | // Internal interface 131 | .sdram_rst (sdram_rst), 132 | .sdram_clk (sdram_clk), 133 | .adr_i (p_adr_i[i]), 134 | .adr_o (p_adr_o[i]), 135 | .dat_i (p_dat_i[i]), 136 | .dat_o (p_dat_o[i]), 137 | .sel_o (p_sel_o[i]), 138 | .acc_o (p_acc_o[i]), 139 | .ack_i (p_ack_i[i]), 140 | .we_o (p_we_o[i]), 141 | 142 | // Buffer write 143 | .bufw_adr_i (p_bufw_adr[i]), 144 | .bufw_dat_i (p_bufw_dat[i]), 145 | .bufw_sel_i (p_bufw_sel[i]), 146 | .bufw_we_i (p_bufw_we[i]) 147 | ); 148 | 149 | end 150 | endgenerate 151 | 152 | assign adr_o = p_adr_o[port_enc]; 153 | assign dat_o = p_dat_o[port_enc]; 154 | assign acc_o = p_acc_o[port_enc]; 155 | assign sel_o = p_sel_o[port_enc]; 156 | assign we_o = p_we_o[port_enc]; 157 | 158 | assign safe_to_switch = sdram_idle_i & !p_acc_o[port_enc]; 159 | 160 | // simple round robin arbitration between ports 161 | function [WB_PORTS-1:0] round_robin; 162 | input [WB_PORTS-1:0] current; 163 | input [WB_PORTS-1:0] req; 164 | reg [WB_PORTS-1:0] grant; 165 | reg [WB_PORTS-1:0] temp; 166 | integer i; 167 | begin 168 | grant = 0; 169 | temp = current; 170 | for (i = 0; i < WB_PORTS; i=i+1) begin 171 | temp[WB_PORTS-1:0] = {temp[0],temp[WB_PORTS-1:1]}; 172 | if (|(temp & req) & !(|grant)) 173 | grant = temp; 174 | end 175 | 176 | if (|grant) 177 | round_robin = grant; 178 | else 179 | round_robin = current; 180 | end 181 | endfunction 182 | 183 | function [WB_PORTS-1:0] ff1; 184 | input [WB_PORTS-1:0] in; 185 | integer i; 186 | begin 187 | ff1 = 0; 188 | for (i = WB_PORTS-1; i >= 0; i=i-1) 189 | if (in[i]) ff1 = i; 190 | end 191 | endfunction 192 | 193 | always @(posedge sdram_clk) 194 | if (sdram_rst) begin 195 | // default to first port after reset 196 | port_sel[WB_PORTS-1:1] <= {(WB_PORTS-1){1'b0}}; 197 | port_sel[0] <= 1'b1; 198 | port_enc <= 0; 199 | end else if (safe_to_switch) begin 200 | port_sel <= round_robin(port_sel, p_acc_o); 201 | port_enc <= ff1(round_robin(port_sel, p_acc_o)); 202 | end 203 | 204 | // Signal when a write have happened to all ports, so they can write 205 | // the data into their buffer in case of a hit 206 | integer j,k; 207 | always @(posedge wb_clk) begin 208 | for (k = 0; k < WB_PORTS; k=k+1) begin 209 | p_bufw_we[k] <= 1'b0; 210 | p_bufw_adr[k] <= 0; 211 | p_bufw_dat[k] <= 0; 212 | p_bufw_sel[k] <= 0; 213 | for (j = 0; j < WB_PORTS; j=j+1) begin 214 | if (j!=k & wb_cycle[j] & wb_we_i[j]) begin 215 | p_bufw_we[k] <= wbp_ack_o[j]; 216 | p_bufw_adr[k] <= wbp_adr_i[j]; 217 | p_bufw_dat[k] <= wbp_dat_i[j]; 218 | p_bufw_sel[k] <= wbp_sel_i[j]; 219 | end 220 | end 221 | 222 | end 223 | end 224 | endmodule 225 | -------------------------------------------------------------------------------- /rtl/verilog/wb_port.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011, Stefan Kristiansson 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and non-source forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in non-source form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * 13 | * THIS WORK IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 17 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | * WORK, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | module wb_port #( 27 | parameter TECHNOLOGY = "GENERIC", 28 | parameter BUF_WIDTH = 3 29 | ) 30 | ( 31 | // Wishbone 32 | input wb_clk, 33 | input wb_rst, 34 | input [31:0] wb_adr_i, 35 | input wb_stb_i, 36 | input wb_cyc_i, 37 | input [2:0] wb_cti_i, 38 | input [1:0] wb_bte_i, 39 | input wb_we_i, 40 | input [3:0] wb_sel_i, 41 | input [31:0] wb_dat_i, 42 | output [31:0] wb_dat_o, 43 | output wb_ack_o, 44 | 45 | // Internal interface 46 | input sdram_rst, 47 | input sdram_clk, 48 | input [31:0] adr_i, 49 | output [31:0] adr_o, 50 | input [15:0] dat_i, 51 | output [15:0] dat_o, 52 | output [1:0] sel_o, 53 | output reg acc_o, 54 | input ack_i, 55 | output reg we_o, 56 | 57 | // Buffer write 58 | input [31:0] bufw_adr_i, 59 | input [31:0] bufw_dat_i, 60 | input [3:0] bufw_sel_i, 61 | input bufw_we_i 62 | ); 63 | 64 | reg [31:0] wb_adr; 65 | reg [31:0] wb_dat; 66 | reg [3:0] wb_sel; 67 | reg wb_read_ack; 68 | reg wb_write_ack; 69 | wire [31:0] next_wb_adr; 70 | 71 | reg wb_write_bufram; 72 | reg sdram_write_bufram; 73 | wire [3:0] wb_bufram_we; 74 | wire [BUF_WIDTH-1:0] wb_bufram_addr; 75 | wire [31:0] wb_bufram_di; 76 | wire [3:0] sdram_bufram_we; 77 | 78 | reg [31:BUF_WIDTH+2] buf_adr; 79 | reg [(1< 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and non-source forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in non-source form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * 13 | * THIS WORK IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 17 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | * WORK, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | module sdram_ctrl #( 27 | parameter CLK_FREQ_MHZ = 100, // sdram_clk freq in MHZ 28 | parameter POWERUP_DELAY = 200, // power up delay in us 29 | parameter REFRESH_MS = 64, // time to wait between refreshes in ms 30 | parameter BURST_LENGTH = 8, // 0, 1, 2, 4 or 8 (0 = full page) 31 | parameter ROW_WIDTH = 13, // Row width 32 | parameter COL_WIDTH = 9, // Column width 33 | parameter BA_WIDTH = 2, // Ba width 34 | parameter tCAC = 2, // CAS Latency 35 | parameter tRAC = 5, // RAS Latency 36 | parameter tRP = 2, // Command Period (PRE to ACT) 37 | parameter tRC = 7, // Command Period (REF to REF / ACT to ACT) 38 | parameter tMRD = 2 // Mode Register Set To Command Delay time 39 | ) 40 | ( 41 | // SDRAM interface 42 | input sdram_rst, 43 | input sdram_clk, 44 | output [BA_WIDTH-1:0] ba_o, 45 | output [12:0] a_o, 46 | output cs_n_o, 47 | output ras_o, 48 | output cas_o, 49 | output we_o, 50 | output reg [15:0] dq_o, 51 | output reg [1:0] dqm_o, 52 | input [15:0] dq_i, 53 | output reg dq_oe_o, 54 | output cke_o, 55 | 56 | // Internal interface 57 | output idle_o, 58 | input [31:0] adr_i, 59 | output reg [31:0] adr_o, 60 | input [15:0] dat_i, 61 | output reg [15:0] dat_o, 62 | input [1:0] sel_i, 63 | input acc_i, 64 | output reg ack_o, 65 | input we_i 66 | ); 67 | // Active Command To Read/Write Command Delay Time 68 | localparam tRCD = tRAC - tCAC; 69 | 70 | localparam POWERUP_CNT = CLK_FREQ_MHZ*POWERUP_DELAY; 71 | // refresh should be done for each row every 64 ms => 64e-3/2^ROW_WIDTH 72 | localparam REFRESH_TIMEOUT = (CLK_FREQ_MHZ*REFRESH_MS*1000)/(1< POWERUP_CNT) begin 173 | cmd <= CMD_PALL; 174 | state <= INIT_PRE; 175 | cycle_count <= 0; 176 | end 177 | end 178 | 179 | INIT_PRE: begin 180 | if (cycle_count > tRP) begin 181 | cmd <= CMD_REF; 182 | state <= INIT_REF; 183 | state_count <= 0; 184 | cycle_count <= 0; 185 | end 186 | end 187 | 188 | INIT_REF: begin 189 | refresh_count <= 0; 190 | if (cycle_count > tRC) begin 191 | cmd <= CMD_REF; 192 | state_count <= state_count + 1; 193 | cycle_count <= 0; 194 | end 195 | // 8 refresh cycles 196 | if (state_count == 4'd7 & cycle_count == tRC) begin 197 | cmd <= CMD_MRS; 198 | state <= INIT_PGM_MODE; 199 | ba <= 2'b00; 200 | a[12:10] <= 0; // Reserved 201 | a[9] <= SINGLE_LOCATION; 202 | a[8:7] <= 0; // Standard operation 203 | a[6:4] <= tCAC; 204 | a[3] <= SEQUENTIAL; 205 | a[2:0] <= bl; 206 | cycle_count <= 0; 207 | end 208 | end 209 | 210 | INIT_PGM_MODE: begin 211 | if (cycle_count > tMRD) 212 | state <= IDLE; 213 | end 214 | 215 | IDLE: begin 216 | cycle_count <= 0; 217 | ba <= curr_bank; 218 | if (refresh_count >= REFRESH_TIMEOUT) begin 219 | refresh_count <= 0; 220 | if (|bank_active) begin 221 | cmd <= CMD_PALL; 222 | state <= PRE_ALL; 223 | end else begin 224 | cmd <= CMD_REF; 225 | state <= REF; 226 | end 227 | end else if (acc_i & curr_row_active) begin 228 | a[12:11] <= adr_i[12:11]; 229 | a[9:0] <= adr_i[10:1]; 230 | adr_o <= adr_i; 231 | if (we_i) begin 232 | ack_o <= 1'b1; 233 | dqm_o <= ~sel_i; 234 | dq_oe_o <= 1'b1; 235 | dq_o <= dat_i; 236 | cmd <= CMD_WRITE; 237 | state <= WRITE; 238 | end else begin 239 | dqm_o <= 2'b00; 240 | cmd <= CMD_READ; 241 | state <= READ; 242 | end 243 | end else if (acc_i & curr_bank_active) begin 244 | cmd <= CMD_PRE; 245 | state <= PRE; 246 | we_r <= we_i; 247 | end else if (acc_i) begin 248 | a <= curr_row; 249 | cmd <= CMD_ACT; 250 | state <= ACTIVATE; 251 | we_r <= we_i; 252 | end 253 | end 254 | 255 | REF: begin 256 | if (cycle_count >= tRC-1) 257 | state <= IDLE; 258 | end 259 | 260 | PRE: begin 261 | if (cycle_count >= tRP-1) begin 262 | bank_active[curr_bank] <= 1'b0; 263 | a <= curr_row; 264 | cmd <= CMD_ACT; 265 | state <= ACTIVATE; 266 | cycle_count <= 0; 267 | end 268 | end 269 | 270 | PRE_ALL: begin 271 | if (cycle_count >= tRP-1) begin 272 | bank_active <= 0; 273 | cmd <= CMD_REF; 274 | state <= REF; 275 | cycle_count <= 0; 276 | end 277 | end 278 | 279 | ACTIVATE: begin 280 | if (cycle_count >= tRCD-1) begin 281 | bank_active[curr_bank] <= 1'b1; 282 | row_active[curr_bank] <= curr_row; 283 | a[12:11] <= adr_i[12:11]; 284 | a[9:0] <= adr_i[10:1]; 285 | adr_o <= adr_i; 286 | if (we_r) begin 287 | ack_o <= 1'b1; 288 | dq_oe_o <= 1'b1; 289 | dq_o <= dat_i; 290 | dqm_o <= ~sel_i; 291 | cmd <= CMD_WRITE; 292 | state <= WRITE; 293 | end else begin 294 | dqm_o <= 2'b00; 295 | cmd <= CMD_READ; 296 | state <= READ; 297 | end 298 | cycle_count <= 0; 299 | end 300 | end 301 | 302 | READ: begin 303 | /* TODO: support for full page burst */ 304 | dqm_o <= 2'b00; 305 | if (cycle_count == 0) begin 306 | next_cycle_count <= 0; 307 | next_state <= IDLE; 308 | end 309 | 310 | if (cycle_count == tCAC) begin 311 | ack_o <= 1'b1; 312 | adr_o <= adr_i; 313 | end 314 | 315 | if (cycle_count >= tCAC) begin 316 | dat_o <= dq_i; 317 | end 318 | 319 | if (cycle_count > tCAC) begin 320 | if (BURST_LENGTH == 8) 321 | adr_o[3:1] <= adr_o[3:1] + 3'b1; 322 | else if (BURST_LENGTH == 4) 323 | adr_o[2:1] <= adr_o[2:1] + 2'b1; 324 | else if (BURST_LENGTH == 2) 325 | adr_o[1] <= adr_o[1] + 1'b1; 326 | end 327 | 328 | /* dqm has a latency of 2 cycles */ 329 | if (cycle_count >= (BURST_LENGTH-1 + tCAC - 2) & 330 | next_state != READ) 331 | dqm_o <= 2'b11; 332 | 333 | if (cycle_count >= (BURST_LENGTH-1) & next_state == IDLE) begin 334 | if (acc_i & curr_row_active & !we_i) begin 335 | dqm_o <= 2'b00; 336 | ba <= curr_bank; 337 | a[12:11] <= adr_i[12:11]; 338 | a[9:0] <= adr_i[10:1]; 339 | cmd <= CMD_READ; 340 | next_cycle_count <= tCAC - (cycle_count - (BURST_LENGTH-1)); 341 | next_state <= READ; 342 | end else if (acc_i & curr_bank_active) begin 343 | we_r <= we_i; 344 | cmd <= CMD_PRE; 345 | next_cycle_count <= tCAC - (cycle_count - (BURST_LENGTH-1)); 346 | next_state <= PRE; 347 | end else if (acc_i) begin 348 | we_r <= we_i; 349 | a <= curr_row; 350 | cmd <= CMD_ACT; 351 | next_cycle_count <= tCAC - (cycle_count - (BURST_LENGTH-1)); 352 | next_state <= ACTIVATE; 353 | end 354 | end 355 | 356 | if (cycle_count >= (tCAC + BURST_LENGTH-1)) begin 357 | cycle_count <= next_cycle_count; 358 | state <= next_state; 359 | next_state <= IDLE; 360 | if (next_state == IDLE) begin 361 | cycle_count <= 0; 362 | if (acc_i & curr_row_active & we_i) begin 363 | ack_o <= 1'b1; 364 | ba <= curr_bank; 365 | a[12:11] <= adr_i[12:11]; 366 | a[9:0] <= adr_i[10:1]; 367 | adr_o <= adr_i; 368 | dq_o <= dat_i; 369 | dqm_o <= ~sel_i; 370 | dq_oe_o <= 1'b1; 371 | cmd <= CMD_WRITE; 372 | end else if (acc_i & curr_row_active & !we_i) begin 373 | ba <= curr_bank; 374 | a[12:11] <= adr_i[12:11]; 375 | a[9:0] <= adr_i[10:1]; 376 | dqm_o <= 2'b00; 377 | cmd <= CMD_READ; 378 | end else if (acc_i & curr_bank_active) begin 379 | we_r <= we_i; 380 | cmd <= CMD_PRE; 381 | state <= PRE; 382 | end else if (acc_i) begin 383 | we_r <= we_i; 384 | a <= curr_row; 385 | cmd <= CMD_ACT; 386 | state <= ACTIVATE; 387 | end else begin 388 | cmd <= CMD_NOP; 389 | state <= IDLE; 390 | end 391 | end 392 | end 393 | end 394 | 395 | WRITE: begin 396 | /* TODO: support for burst writes */ 397 | cycle_count <= 0; 398 | if (acc_i & curr_row_active & we_i) begin 399 | ack_o <= 1'b1; 400 | ba <= curr_bank; 401 | a[12:11] <= adr_i[12:11]; 402 | a[9:0] <= adr_i[10:1]; 403 | adr_o <= adr_i; 404 | dq_o <= dat_i; 405 | dqm_o <= ~sel_i; 406 | dq_oe_o <= 1'b1; 407 | cmd <= CMD_WRITE; 408 | end else if (acc_i & curr_row_active & !we_i) begin 409 | ba <= curr_bank; 410 | a[12:11] <= adr_i[12:11]; 411 | a[9:0] <= adr_i[10:1]; 412 | dqm_o <= 2'b00; 413 | cmd <= CMD_READ; 414 | state <= READ; 415 | end else if (acc_i & curr_bank_active) begin 416 | we_r <= we_i; 417 | cmd <= CMD_PRE; 418 | state <= PRE; 419 | end else if (acc_i) begin 420 | we_r <= we_i; 421 | a <= curr_row; 422 | cmd <= CMD_ACT; 423 | state <= ACTIVATE; 424 | end else begin 425 | cmd <= CMD_NOP; 426 | state <= IDLE; 427 | end 428 | end 429 | endcase 430 | end 431 | end 432 | endmodule 433 | --------------------------------------------------------------------------------