Hardware Design: SIE
Sign in or create your account | Project List | Help
Hardware Design: SIE Git Source Tree
Root/
| 1 | //---------------------------------------------------------------------------- |
| 2 | // Wishbone DDR Controller -- fast write data-path |
| 3 | // |
| 4 | // (c) Joerg Bornschein (<jb@capsec.org>) |
| 5 | //---------------------------------------------------------------------------- |
| 6 | `include "ddr_include.v" |
| 7 | |
| 8 | module ddr_wpath ( |
| 9 | input clk, |
| 10 | input clk90, |
| 11 | input reset, |
| 12 | // CBA async fifo |
| 13 | input cba_clk, |
| 14 | input [`CBA_RNG] cba_din, |
| 15 | input cba_wr, |
| 16 | output cba_full, |
| 17 | // WDATA async fifo |
| 18 | input wdata_clk, |
| 19 | input [`WFIFO_RNG] wdata_din, |
| 20 | input wdata_wr, |
| 21 | output wdata_full, |
| 22 | // sample to rdata |
| 23 | output sample, |
| 24 | // DDR |
| 25 | output [2:0] ddr_clk, |
| 26 | output [2:0] ddr_clk_n, |
| 27 | output ddr_ras_n, |
| 28 | output ddr_cas_n, |
| 29 | output ddr_we_n, |
| 30 | output [ `A_RNG] ddr_a, |
| 31 | output [ `BA_RNG] ddr_ba, |
| 32 | output [ `DM_RNG] ddr_dm, |
| 33 | output [ `DQ_RNG] ddr_dq, |
| 34 | output [`DQS_RNG] ddr_dqs, |
| 35 | output ddr_dqs_oe |
| 36 | ); |
| 37 | |
| 38 | wire gnd = 1'b0; |
| 39 | wire vcc = 1'b1; |
| 40 | |
| 41 | //---------------------------------------------------------------------------- |
| 42 | // CBA async. fifo |
| 43 | //---------------------------------------------------------------------------- |
| 44 | wire [`CBA_RNG] cba_data; |
| 45 | wire cba_empty; |
| 46 | wire cba_ack; |
| 47 | |
| 48 | wire cba_avail = ~cba_empty; |
| 49 | |
| 50 | async_fifo #( |
| 51 | .DATA_WIDTH( `CBA_WIDTH ), |
| 52 | .ADDRESS_WIDTH( 4 ) |
| 53 | ) cba_fifo ( |
| 54 | .Data_out( cba_data ), |
| 55 | .Empty_out( cba_empty ), |
| 56 | .ReadEn_in( cba_ack ), |
| 57 | .RClk( clk ), |
| 58 | // |
| 59 | .Data_in( cba_din ), |
| 60 | .WriteEn_in( cba_wr ), |
| 61 | .Full_out( cba_full ), |
| 62 | .WClk( cba_clk ), |
| 63 | .Clear_in( reset ) |
| 64 | ); |
| 65 | |
| 66 | //---------------------------------------------------------------------------- |
| 67 | // WDATA async. fifo |
| 68 | //---------------------------------------------------------------------------- |
| 69 | wire [`WFIFO_RNG] wdata_data; |
| 70 | wire wdata_empty; |
| 71 | wire wdata_ack; |
| 72 | |
| 73 | wire wdata_avail = ~wdata_empty; |
| 74 | |
| 75 | async_fifo #( |
| 76 | .DATA_WIDTH( `WFIFO_WIDTH ), |
| 77 | .ADDRESS_WIDTH( 4 ) |
| 78 | ) wdata_fifo ( |
| 79 | .Data_out( wdata_data ), |
| 80 | .Empty_out( wdata_empty ), |
| 81 | .ReadEn_in( wdata_ack ), |
| 82 | .RClk( ~clk90 ), |
| 83 | // |
| 84 | .Data_in( wdata_din ), |
| 85 | .WriteEn_in( wdata_wr ), |
| 86 | .Full_out( wdata_full ), |
| 87 | .WClk( wdata_clk ), |
| 88 | .Clear_in( reset ) |
| 89 | ); |
| 90 | |
| 91 | |
| 92 | //---------------------------------------------------------------------------- |
| 93 | // Handle CBA |
| 94 | //---------------------------------------------------------------------------- |
| 95 | reg [3:0] delay_count; |
| 96 | |
| 97 | reg [`CBA_RNG] ddr_cba; |
| 98 | wire [`CBA_RNG] CBA_NOP = { `DDR_CMD_NOP, 15'b0 }; |
| 99 | |
| 100 | assign cba_ack = cba_avail & (delay_count == 0); |
| 101 | |
| 102 | wire [`CMD_RNG] cba_cmd = cba_data[(`CBA_WIDTH-1):(`CBA_WIDTH-3)]; |
| 103 | |
| 104 | always @(posedge clk) |
| 105 | begin |
| 106 | if (reset) begin |
| 107 | delay_count <= 0; |
| 108 | ddr_cba <= CBA_NOP; |
| 109 | end else begin |
| 110 | if (delay_count != 0) begin |
| 111 | delay_count <= delay_count - 1; |
| 112 | ddr_cba <= CBA_NOP; |
| 113 | end |
| 114 | |
| 115 | if (!cba_ack) begin |
| 116 | ddr_cba <= CBA_NOP; |
| 117 | end else begin |
| 118 | ddr_cba <= cba_data; |
| 119 | |
| 120 | case (cba_cmd) |
| 121 | `DDR_CMD_MRS : delay_count <= 2; |
| 122 | `DDR_CMD_AR : delay_count <= 14; |
| 123 | `DDR_CMD_ACT : delay_count <= 4; |
| 124 | `DDR_CMD_PRE : delay_count <= 2; |
| 125 | `DDR_CMD_READ : delay_count <= 6; // XXX |
| 126 | `DDR_CMD_WRITE : delay_count <= 8; // XXX |
| 127 | endcase |
| 128 | end |
| 129 | end |
| 130 | end |
| 131 | |
| 132 | |
| 133 | //---------------------------------------------------------------------------- |
| 134 | // READ-SHIFT-REGISTER |
| 135 | //---------------------------------------------------------------------------- |
| 136 | reg [7:0] read_shr; |
| 137 | wire read_cmd = (cba_cmd == `DDR_CMD_READ) & cba_ack; |
| 138 | assign sample = read_shr[6]; |
| 139 | |
| 140 | always @(posedge clk) |
| 141 | begin |
| 142 | if (reset) |
| 143 | read_shr <= 'b0; |
| 144 | else begin |
| 145 | if (read_cmd) |
| 146 | read_shr <= { 8'b00011000 }; |
| 147 | else |
| 148 | read_shr <= { read_shr[6:0], 1'b0 }; |
| 149 | end |
| 150 | end |
| 151 | |
| 152 | //---------------------------------------------------------------------------- |
| 153 | // WRITE-SHIFT-REGISTER |
| 154 | //---------------------------------------------------------------------------- |
| 155 | |
| 156 | reg [0:4] write_shr; |
| 157 | wire write_cmd = (cba_cmd == `DDR_CMD_WRITE) & cba_ack; |
| 158 | |
| 159 | always @(posedge clk) |
| 160 | begin |
| 161 | if (reset) |
| 162 | write_shr <= 'b0; |
| 163 | else begin |
| 164 | if (write_cmd) |
| 165 | write_shr <= { 5'b11111 }; |
| 166 | else |
| 167 | write_shr <= { write_shr[1:4], 1'b0 }; |
| 168 | end |
| 169 | end |
| 170 | |
| 171 | //---------------------------------------------------------------------------- |
| 172 | // DDR_DQS, DDR_DQS_OE |
| 173 | //---------------------------------------------------------------------------- |
| 174 | genvar i; |
| 175 | |
| 176 | reg ddr_dqs_oe_reg; |
| 177 | assign ddr_dqs_oe = ddr_dqs_oe_reg; |
| 178 | |
| 179 | always @(negedge clk) |
| 180 | begin |
| 181 | ddr_dqs_oe_reg <= write_shr[0]; |
| 182 | end |
| 183 | |
| 184 | generate |
| 185 | for (i=0; i<3; i=i+1) begin : CLK |
| 186 | FDDRRSE ddr_clk_reg ( |
| 187 | .Q( ddr_clk[i] ), |
| 188 | .C0( clk90 ), |
| 189 | .C1( ~clk90 ), |
| 190 | .CE( vcc ), |
| 191 | .D0( vcc ), |
| 192 | .D1( gnd ), |
| 193 | .R( gnd ), |
| 194 | .S( gnd ) |
| 195 | ); |
| 196 | |
| 197 | FDDRRSE ddr_clk_n_reg ( |
| 198 | .Q( ddr_clk_n[i] ), |
| 199 | .C0( clk90 ), |
| 200 | .C1( ~clk90 ), |
| 201 | .CE( vcc ), |
| 202 | .D0( gnd ), |
| 203 | .D1( vcc ), |
| 204 | .R( gnd ), |
| 205 | .S( gnd ) |
| 206 | ); |
| 207 | end |
| 208 | endgenerate |
| 209 | |
| 210 | generate |
| 211 | for (i=0; i<`DQS_WIDTH; i=i+1) begin : DQS |
| 212 | FDDRRSE ddr_dqs_reg ( |
| 213 | .Q( ddr_dqs[i] ), |
| 214 | .C0( clk ), |
| 215 | .C1( ~clk ), |
| 216 | .CE( vcc ), |
| 217 | .D0( write_shr[1] ), |
| 218 | .D1( gnd ), |
| 219 | .R( gnd ), |
| 220 | .S( gnd ) |
| 221 | ); |
| 222 | end |
| 223 | endgenerate |
| 224 | |
| 225 | |
| 226 | //---------------------------------------------------------------------------- |
| 227 | // DQ data output |
| 228 | //---------------------------------------------------------------------------- |
| 229 | wire [`DQ_RNG] buf_d0; |
| 230 | wire [`DM_RNG] buf_m0; |
| 231 | reg [`DQ_RNG] buf_d1; // pipleine high word data |
| 232 | reg [`DM_RNG] buf_m1; // pipleine high word mask |
| 233 | |
| 234 | assign buf_d0 = wdata_data[`WFIFO_D0_RNG]; |
| 235 | assign buf_m0 = wdata_data[`WFIFO_M0_RNG]; |
| 236 | |
| 237 | always @(negedge clk90) |
| 238 | begin |
| 239 | buf_d1 <= wdata_data[`WFIFO_D1_RNG]; |
| 240 | buf_m1 <= wdata_data[`WFIFO_M1_RNG]; |
| 241 | end |
| 242 | |
| 243 | assign wdata_ack = write_shr[1]; |
| 244 | |
| 245 | // generate DDR_DQ register |
| 246 | generate |
| 247 | for (i=0; i<`DQ_WIDTH; i=i+1) begin : DQ_REG |
| 248 | FDDRRSE ddr_dq_reg ( |
| 249 | .Q( ddr_dq[i] ), |
| 250 | .C0( ~clk90 ), |
| 251 | .C1( clk90 ), |
| 252 | .CE( vcc ), |
| 253 | .D0( buf_d0[i] ), |
| 254 | .D1( buf_d1[i] ), |
| 255 | .R( gnd ), |
| 256 | .S( gnd ) |
| 257 | ); |
| 258 | end |
| 259 | endgenerate |
| 260 | |
| 261 | // generate DDR_DM register |
| 262 | generate |
| 263 | for (i=0; i<`DM_WIDTH; i=i+1) begin : DM_REG |
| 264 | FDDRRSE ddr_dm_reg ( |
| 265 | .Q( ddr_dm[i] ), |
| 266 | .C0( ~clk90 ), |
| 267 | .C1( clk90 ), |
| 268 | .CE( vcc ), |
| 269 | .D0( buf_m0[i] ), |
| 270 | .D1( buf_m1[i] ), |
| 271 | .R( gnd ), |
| 272 | .S( gnd ) |
| 273 | ); |
| 274 | end |
| 275 | endgenerate |
| 276 | |
| 277 | //---------------------------------------------------------------------------- |
| 278 | // Connect ddr_cba to actual DDR pins |
| 279 | //---------------------------------------------------------------------------- |
| 280 | assign ddr_a = ddr_cba[(`A_WIDTH-1):0]; |
| 281 | assign ddr_ba = ddr_cba[(`A_WIDTH+`BA_WIDTH-1):(`A_WIDTH)]; |
| 282 | assign ddr_ras_n = ddr_cba[(`CBA_WIDTH-1)]; |
| 283 | assign ddr_cas_n = ddr_cba[(`CBA_WIDTH-2)]; |
| 284 | assign ddr_we_n = ddr_cba[(`CBA_WIDTH-3)]; |
| 285 | |
| 286 | endmodule |
| 287 |
Branches:
master
