Advertisement
alynna

Untitled

Feb 8th, 2019
835
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // bddram.v
  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