Advertisement
Guest User

Untitled

a guest
Feb 7th, 2019
76
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // bddram.sv
  2. // Copyright (c) 2019 Alynna
  3. //
  4. //
  5. // This source file is free software: you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published
  7. // by the Free Software Foundation, either version 3 of the License, or
  8. // (at your option) any later version.
  9. //
  10. // This source file is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. // GNU General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program.  If not, see <http://www.gnu.org/licenses/>.
  17. //
  18. // ------------------------------------------
  19. //
  20.  
  21. module single_port_ram
  22. #(
  23. parameter DATA_WIDTH=64,
  24. parameter ADDR_WIDTH=7,
  25. parameter PAGE_WIDTH=7)
  26. (
  27.    input [(DATA_WIDTH-1):0] data,
  28.    input [(ADDR_WIDTH-1):0] addr,
  29.    input [(PAGE_WIDTH-1):0] page,
  30.    input we, clk,
  31.    output [(DATA_WIDTH-1):0] q
  32. );
  33.  
  34.    // Declare the RAM variable
  35.    reg [DATA_WIDTH-1:0] ram[(2**PAGE_WIDTH)-1:0][(2**ADDR_WIDTH)-1:0];
  36.  
  37.    // Variable to hold the registered read address
  38.    reg [ADDR_WIDTH-1:0] addr_reg;
  39.    reg [PAGE_WIDTH-1:0] page_reg;
  40.  
  41.    always @ (posedge clk)
  42.    begin
  43.       // Write
  44.       if (we)
  45.          ram[page][addr] <= data;
  46.       page_reg <= page;
  47.       addr_reg <= addr;
  48.    end
  49.  
  50.    // Continuous assignment implies read returns NEW data.
  51.    // This is the natural behavior of the TriMatrix memory
  52.    // blocks in Single Port mode.  
  53.    assign q = ram[page_reg][addr_reg];
  54. endmodule
  55. module ddram #(
  56.    parameter MODE = 0
  57.    // MODE=0: 512M addressing space, risk to ASCAL (avoid using lowest 32M memory)
  58.    // MODE=1: 256M addressing space at top of HPS RAM, use freely
  59. )
  60. (
  61.    input         DDRAM_CLK,
  62.    inout  [7:0]  debug,
  63.    
  64.    input         DDRAM_BUSY,       // waitrequest
  65.    output [7:0]  DDRAM_BURSTCNT,    // burstcount
  66.    output [28:0] DDRAM_ADDR,       // Exact HPS memory address
  67.    input  [63:0] DDRAM_DOUT,       // readdata
  68.    input         DDRAM_DOUT_READY, // readdatavalid
  69.    output        DDRAM_RD,       // read
  70.    output [63:0] DDRAM_DIN,       // writedata
  71.    output [7:0]  DDRAM_BE,       // byteenable
  72.    output        DDRAM_WE,       // write
  73.  
  74.    inout [1:0]   cfg_req,
  75.    
  76.    input [31:0]  wr_a,
  77.    input [15:0]  wr_d,
  78.    input [7:0]   wr_d8,
  79.    input [1:0]   wr_be,
  80.    input         wr_req,
  81.    output        wr_ack,
  82.  
  83.    input             bus16,
  84.    output [7:0]  page,
  85.    
  86.    input  [31:0] rd_a,
  87.    output [15:0] rd_d,
  88.    output [7:0]  rd_d8,
  89.    input         rd_req,
  90.    output        rd_ack
  91. );
  92.  
  93. localparam PAGES = 64;   // I had to hardcode this..
  94.  
  95. // Structure
  96. reg PAGE_SWAP [128-1:0];          // 1: Permitted to be swapped out
  97. reg [15:0] PAGE_AGE [128-1:0];      // Page ages
  98. reg PAGE_W [128-1:0];               // Set if a page has been written to
  99. reg [28:0] PAGE_ADDR [128-1:0];      // Page addresses in core - 1K boundaries
  100.  
  101. wire BRAM_CLK;
  102.  
  103. // Inferred BRAM
  104. single_port_ram #(
  105.  .DATA_WIDTH(64),                     // Size of data bus, 64 is right
  106.  .ADDR_WIDTH(7),                     // Size of burst length.  128 for now
  107.  .PAGE_WIDTH(7)                     // 2**x = Number of pages (6=64)
  108. ) bram (
  109.  .data(BIN),
  110.  .addr(BADDR),
  111.  .page(BPAGE),
  112.  .we(BWE),
  113.  .q(BOUT),
  114.  .clk(BRAM_CLK)
  115. );
  116.  
  117. wire [63:0]    BIN, BOUT;
  118. wire [7:0]       BPAGE;
  119. wire [6:0]     BADDR;
  120. wire             BWE;
  121.  
  122. reg [7:0]     ram_burst;
  123. reg [63:0]    ram_data;
  124. reg [28:0]    ram_address;
  125. reg           ram_read = 0;
  126. reg           ram_write = 0;
  127.  
  128. reg rd_acki,wr_acki;
  129. assign DDRAM_ADDR        = MODE ? {1'b0,ram_address[27:10],10'b0} : {ram_address[28:10],10'b0};
  130. assign DDRAM_BE          = 8'b11111111;
  131. assign DDRAM_BURSTCNT    = ram_burst;
  132. assign DDRAM_DIN         = ram_data;
  133. assign DDRAM_RD          = ram_read;
  134. assign DDRAM_WE          = ram_write;
  135. assign rd_ack            = rd_acki;
  136. assign wr_ack            = wr_acki;
  137.  
  138. reg [31:0] rd_addr, wr_addr;
  139. reg [15:0] rd_dat16, wr_dat16;
  140. reg [7:0] rd_dat8, wr_dat8;
  141. reg [1:0] wr_byteen;
  142. reg [7:0] rd_pend;
  143. reg [7:0] wr_pend;
  144. reg [7:0] sw_page; // Page being swapped
  145. reg [1:0] sw_pend;
  146. reg [1:0] phase;
  147.  
  148. assign rd_d = rd_dat16;
  149. assign rd_d8 = rd_dat8;
  150.  
  151. reg [7:0] x8, y8;
  152. reg [15:0] x16, y16;
  153. reg [7:0] signal;
  154. // 00: No errors
  155. // Bit 7: Any other errors
  156. // Bit 0: Page not found
  157. // 7: 1: Write / 0: Read
  158. // 6-5: phase;
  159.  
  160. task age_pages;
  161. reg [7:0] p;
  162. begin
  163.    for (p=0; p<128; p++) PAGE_AGE[p] <= (PAGE_AGE[p] == 16'hFFFF) ? 16'hFFFF : (PAGE_AGE[p] + 16'd1);
  164. end endtask
  165.  
  166. task find_page_old;
  167. // Find the oldest page
  168. reg [7:0] p;
  169. reg [15:0] r;
  170. begin
  171.    r <= 16'd0;
  172.    for (p=127; p[7]; p--) begin
  173.       if ((PAGE_SWAP[p]==1'b1) && (PAGE_AGE[p] > r)) begin
  174.          r <= PAGE_AGE[p];
  175.          page <= p;
  176.       end
  177.    end
  178. end endtask
  179.  
  180. task find_page_a(reg [28:0] addr);
  181. // Find page matching the given address
  182. reg [7:0] p;
  183. begin
  184.    signal[0] <= 1'b1;
  185.    for (p=127; p[7]; p--) begin
  186.       if (PAGE_ADDR[p][28:10]==addr[28:10]) begin
  187.          signal[0]    <= 1'b0;
  188.          page          <= p;
  189.       end
  190.    end
  191. end endtask
  192.  
  193. task get16(reg [28:0] addr);
  194. // Get a 16 bit value if available in cache
  195. begin
  196.    find_page_a(addr);
  197.    if (!signal[0]) begin
  198.       BWE <= 0;
  199.       BPAGE <= page;
  200.       BADDR <= addr[9:3];
  201.       rd_dat16 <= BOUT[(addr[2:1] << 4) +:16];
  202.       PAGE_AGE[page] <= 16'b0;
  203.       rd_pend <= 8'hff;
  204.       BRAM_CLK <= 1'b1;
  205.       phase <= 2'b11;
  206.    end
  207. end endtask
  208.  
  209. task get8(reg [28:0] addr);
  210. // Get a 8 bit value if available in cache
  211. begin
  212.    find_page_a(addr);
  213.    if (!signal[0]) begin
  214.       BWE <= 0;
  215.       BPAGE <= page;
  216.       BADDR <= addr[9:3];
  217.       rd_dat8 <= BOUT[(addr[2:0] << 3) +:8];
  218.       PAGE_AGE[page] <= 16'b0;
  219.       rd_pend <= 8'hff;
  220.       BRAM_CLK <= 1'b1;
  221.       phase <= 2'b11;
  222.    end
  223. end endtask
  224.  
  225. task put16(reg [28:0] addr, reg [15:0] val);
  226. // Put a 16 bit value if its page is cached.
  227. begin
  228.    find_page_a(addr);
  229.    if (!signal[0]) begin
  230.       BPAGE <= page;
  231.       BADDR <= addr[9:3];
  232.       BIN[(addr[2:1] << 4) +:16] <= val;
  233.       BWE <= 1;
  234.       PAGE_AGE[page] <= 16'b0;
  235.       PAGE_W[page] <= 1'b1;
  236.       wr_pend <= 8'hff;
  237.       BRAM_CLK <= 1'b1;
  238.       phase <= 2'b11;
  239.    end else signal[0] <= 1'b1;
  240. end endtask
  241.  
  242. task put8(reg [28:0] addr, reg [7:0] val);
  243. // Put an 8 bit value if its page is cached.
  244. begin
  245.    find_page_a(addr);
  246.    if (!signal[0]) begin
  247.       BPAGE <= page;
  248.       BADDR <= addr[9:3];
  249.       BIN[(addr[2:1] << 3) +:8] <= val;
  250.       BWE <= 1;
  251.       PAGE_W[page] <= 1'b1;
  252.       PAGE_AGE[page] <= 16'b0;
  253.       wr_pend <= 8'hff;
  254.       BRAM_CLK <= 1'b1;
  255.       phase <= 2'b11;
  256.    end else signal[0] <= 1'b1;
  257. end endtask
  258.  
  259. task write_page_s(reg [6:0] p);
  260. // Begin process of sending a cache page to ddr3
  261. begin
  262.    page         <= p;
  263.    BWE         <= 0;
  264.    BPAGE       <= p;
  265.    BADDR       <= 0;
  266.    ram_address <= PAGE_ADDR[page];
  267.    ram_burst   <= 8'd128;
  268.    wr_pend     <= 8'd127;
  269.    BRAM_CLK      <= 1;
  270.    wr_acki       <= 0;
  271.    ram_write   <= 0;
  272. end endtask
  273.  
  274. task write_page_l(reg [6:0] p);
  275. // Continue write burst
  276. begin
  277.    if (!DDRAM_BUSY && !wr_pend[7]) begin
  278.       BADDR       <= ~wr_pend[6:0];
  279.       ram_data    <= BOUT;
  280.       BRAM_CLK      <= 1'b0;
  281.       ram_write   <= 1'b1;
  282.    end
  283. end endtask
  284.  
  285. task write_page_h(reg [6:0] p);
  286. // Continue write burst
  287. begin
  288.    if (!DDRAM_BUSY && !wr_pend[7]) begin
  289.       wr_pend      <= wr_pend - 8'd1;
  290.       BRAM_CLK      <= 1'b1;
  291.       ram_write   <= 1'b0;
  292.    end
  293. end endtask
  294.  
  295. task reset_page(reg [6:0] p, reg [15:0] addr, reg ptype=1'b1);
  296. // Reset the page and set a new address for it.
  297. begin
  298.    page               <= p;
  299.    PAGE_ADDR[page]   <= addr;
  300.    PAGE_AGE[page]      <= 16'b0;
  301.    PAGE_SWAP[page]   <= ptype;
  302.    PAGE_W[page]      <= 1'b0;
  303. end endtask
  304.  
  305. task read_page_s(reg [6:0] p);
  306. // Begin process of getting a cache page from ddr3
  307. begin
  308.    page         <= p;
  309.    BWE         <= 1;
  310.    BPAGE       <= p;
  311.    BADDR       <= 0;
  312.    ram_burst   <= 8'd128;
  313.    rd_pend     <= 8'd127;
  314.    BRAM_CLK      <= 1'b0;
  315.    ram_read      <= 1'b1;
  316.    rd_acki       <= 0;
  317. end endtask
  318.  
  319. task read_page_l(reg [6:0] p);
  320. // Continue read burst
  321. begin
  322.    if (!DDRAM_BUSY && DDRAM_DOUT_READY && !rd_pend[7]) begin
  323.       BADDR       <= ~rd_pend[6:0];
  324.       BIN          <= DDRAM_DOUT;
  325.       BRAM_CLK      <= 1'b1;
  326.       ram_read      <= 1'b0;
  327.    end
  328. end endtask
  329.  
  330. task read_page_h(reg [6:0] p);
  331. // Continue read burst
  332. begin
  333.    if (!DDRAM_BUSY && DDRAM_DOUT_READY && !rd_pend[7]) begin
  334.       rd_pend       <= rd_pend - 8'd1;
  335.       BRAM_CLK      <= 1'b0;
  336.       ram_read      <= 1'b1;
  337.    end
  338. end endtask
  339.  
  340. task page_sw_s;
  341. // Begin process of swapping a page out and bringing a new one in.
  342. // Page swapped out will be the least accessed page.
  343. reg [7:0] p;
  344. begin
  345.    // We only have to write the page if its been updated
  346.    find_page_old;
  347.    sw_pend <= (PAGE_W[page] == 1'b1) ? 2'b01 : 2'b10;
  348.    sw_page <= page;
  349. end endtask
  350.  
  351. // CFG interface:
  352. // Use cfg_req:1 with rd_req:0 and wr_req:0 for the following tasks:
  353. // cfg_req:1 wr_d:16'd0 wr_d8:<page>: Make a page unswappable
  354. // cfg_req:1 wr_d:16'd1 wr_d8:<page>: Make a page swappable
  355. // cfg_req:1 wr_d:16'd2               Look up a page by address (returned in rd_d8)
  356. // cfg_req:1 wr_d:16'd3 wr_d8:<page> wr_a:<addr> Assign an address to a page
  357. // cfg_req:1 wr_d:16'd4 wr_d8:<page> Make a page young (age = 0)
  358. // cfg_req:1 wr_d:16'd5 wr_d8:<page> Make a page old (age = 65535)
  359. // cfg_req:1 wr_d:16'd7 wr_d8:<page> wr_a:<addr> Reset a page (does not commit it!)
  360.    
  361. task cfg(reg [28:0] a, reg [15:0] f, reg [6:0] p);
  362. begin
  363.    debug <= 8'b11100000;
  364.    case (f)
  365.       16'd0: PAGE_SWAP[p] <= 1'b0;
  366.       16'd1: PAGE_SWAP[p] <= 1'b1;
  367.       16'd2: begin
  368.          find_page_a(a);
  369.          rd_dat8 <= page;
  370.          end
  371.       16'd3: PAGE_ADDR[p] <= a;
  372.       16'd4: PAGE_AGE[p] <= 16'h0;
  373.       16'd5: PAGE_AGE[p] <= 16'hFFFF;
  374.       16'd7: reset_page(p, a, 1'b1);
  375.       default: ;
  376.    endcase      
  377. end endtask
  378.  
  379. // Phases:
  380. // 00: Ready for r/w request
  381. // 01: Initialize page swap
  382. // 02: Continue page swap
  383. // 03: Finalize transfer (wait for rd/wr req to go low
  384.  
  385. reg [7:0] pg = 0;
  386. reg init = 0;
  387. always @(posedge DDRAM_CLK) begin
  388.    if (!init) begin
  389.       for (pg=0; pg < 128; pg++) begin // Cheap ass init block
  390.          PAGE_ADDR[pg] <= 28'b0;
  391.          PAGE_AGE[pg] <= 16'b0;
  392.          PAGE_W[pg] <= 1'b0;
  393.          PAGE_SWAP[pg] <= 1'b1;
  394.       end
  395.       rd_pend <= 8'hFF;
  396.       wr_pend <= 8'hFF;
  397.       phase <= 2'b00;
  398.       init <= 1;
  399.    end
  400.    debug[6:5] <= phase;
  401.    age_pages;
  402.    if (phase == 2'b00) begin // Should be in phase 0 whenever we are ready to process requests.
  403.       if (wr_req) begin
  404.          debug[7] <= 1'b1;
  405.          if (bus16)
  406.             case (wr_be)
  407.                2'b00: ;
  408.                2'b01: put8(wr_a,wr_d[7:0]);
  409.                2'b10: put8(wr_a+1,wr_d[15:8]);
  410.                2'b11: put16(wr_a,wr_d);
  411.             endcase
  412.          else
  413.             put8(wr_a, wr_d8);
  414.          if (signal[0]) begin // Page not found
  415.             page_sw_s;
  416.             sw_page <= page;
  417.             debug[4:0] <= {3'b001,sw_pend};
  418.             case (sw_pend)
  419.                2'b01: write_page_s(sw_page);
  420.                2'b10: read_page_s(sw_page);
  421.                default: ;
  422.             endcase        
  423.             phase <= 2'b01;
  424.             debug[4:0] <= {3'b001,sw_pend};
  425.          end else begin
  426.             phase <= 2'b11;
  427.          end;
  428.       end else if (rd_req) begin
  429.          debug[7] <= 1'b0;
  430.          if (bus16)    get16(rd_a);
  431.          else          get8(rd_a);
  432.          if (signal[0]) begin
  433.             page_sw_s;
  434.             sw_page <= page;
  435.             case (sw_pend)
  436.                2'b01: write_page_s(sw_page);
  437.                2'b10: read_page_s(sw_page);
  438.                default: ;
  439.             endcase        
  440.             phase <= 2'b01;
  441.             debug[4:0] <= {3'b001,sw_pend};
  442.          end else phase <= 2'b11;  
  443.       end else if (!wr_req && !rd_req && cfg_req) begin
  444.          debug <= 8'b11100111;
  445.          cfg(wr_a, wr_d, wr_d8);
  446.          cfg_req <= 1'b0;
  447.          phase <= 2'b10;
  448.       end
  449.    end else if (phase == 2'b01) begin // Phase 1: Swap page
  450.       case (sw_pend)
  451.          2'b01: write_page_l(sw_page);
  452.          2'b10: begin // Reset page and set address
  453.             if (rd_req)
  454.                reset_page(sw_page,rd_a);
  455.             else
  456.                reset_page(sw_page,wr_a);            
  457.          end
  458.          2'b11: begin // Read page from DDR3
  459.             read_page_l(sw_page);
  460.          end
  461.          default: ;
  462.       endcase
  463.       phase <= 2'b10;
  464.       debug <= {6'b101001,sw_pend};
  465.    end else if (phase == 2'b10 || (!rd_req && !wr_req)) begin // Continue or end decision
  466.       case (sw_pend)
  467.          2'b01: begin // Commit page to DDR3 (Skipped if no writes to the page)
  468.             write_page_h(sw_page);
  469.             if (wr_pend[7]) sw_pend <= 2'b10;
  470.          end
  471.          2'b10: begin // Reset page and set address
  472.             read_page_s(sw_page);
  473.             sw_pend <= 2'b11;
  474.          end
  475.          2'b11: begin // Read page from DDR3
  476.             read_page_h(sw_page);
  477.             if (rd_pend[7]) sw_pend <= 2'b00;
  478.          end
  479.          default: ;
  480.       endcase
  481.       BRAM_CLK <= 1'b0;
  482.       if (rd_pend != 8'hFF || wr_pend != 8'hFF) begin
  483.          phase <= 2'b01; // DDR3 burst continues
  484.       end else begin  
  485.          phase <= 2'b00; // Retry RW
  486.       end
  487.      
  488.    end else if (phase == 2'b11 || (!rd_req && !wr_req)) begin
  489.       // Wait for the core to be ready
  490.       // We also detect if theres no request being made
  491.       // to allow the phase to be reset to 0.
  492.       signal <= 8'b00000000;
  493.       BWE <= 1'b0;
  494.       BRAM_CLK <= 1'b0;
  495.       if (rd_pend==8'hFF)   rd_acki <= 1;
  496.       if (wr_pend==8'hFF)   wr_acki <= 1;
  497.    end
  498.    if (!wr_req)         wr_acki <= 0;
  499.    if (!rd_req)         rd_acki <= 0;
  500.    if (!wr_req && !rd_req) phase <= 2'b00;
  501. end
  502. endmodule
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement