alynna

Untitled

Feb 8th, 2019
635
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
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×