/ 9_Firmware / 9_2_FPGA / chirp_memory_loader_param.v
chirp_memory_loader_param.v
  1  `timescale 1ns / 1ps
  2  module chirp_memory_loader_param #(
  3      parameter LONG_I_FILE_SEG0 = "long_chirp_seg0_i.mem",
  4      parameter LONG_Q_FILE_SEG0 = "long_chirp_seg0_q.mem",
  5      parameter LONG_I_FILE_SEG1 = "long_chirp_seg1_i.mem",
  6      parameter LONG_Q_FILE_SEG1 = "long_chirp_seg1_q.mem",
  7      parameter LONG_I_FILE_SEG2 = "long_chirp_seg2_i.mem",
  8      parameter LONG_Q_FILE_SEG2 = "long_chirp_seg2_q.mem",
  9      parameter LONG_I_FILE_SEG3 = "long_chirp_seg3_i.mem",
 10      parameter LONG_Q_FILE_SEG3 = "long_chirp_seg3_q.mem",
 11      parameter SHORT_I_FILE = "short_chirp_i.mem",
 12      parameter SHORT_Q_FILE = "short_chirp_q.mem",
 13      parameter DEBUG = 1
 14  )(
 15      input wire clk,
 16      input wire reset_n,
 17      input wire [1:0] segment_select,
 18      input wire mem_request,
 19      input wire use_long_chirp,
 20      input wire [9:0] sample_addr,
 21      output reg [15:0] ref_i,
 22      output reg [15:0] ref_q,
 23      output reg mem_ready
 24  );
 25  
 26  // Memory declarations - now 4096 samples for 4 segments
 27  (* ram_style = "block" *) reg [15:0] long_chirp_i [0:4095];
 28  (* ram_style = "block" *) reg [15:0] long_chirp_q [0:4095];
 29  (* ram_style = "block" *) reg [15:0] short_chirp_i [0:1023];
 30  (* ram_style = "block" *) reg [15:0] short_chirp_q [0:1023];
 31  
 32  // Initialize memory
 33  integer i;
 34  
 35  initial begin
 36      `ifdef SIMULATION
 37      if (DEBUG) begin
 38          $display("[MEM] Starting memory initialization for 4 long chirp segments");
 39      end
 40      `endif
 41      
 42      // === LOAD LONG CHIRP - 4 SEGMENTS ===
 43      // Segment 0 (addresses 0-1023)
 44      $readmemh(LONG_I_FILE_SEG0, long_chirp_i, 0, 1023);
 45      $readmemh(LONG_Q_FILE_SEG0, long_chirp_q, 0, 1023);
 46      `ifdef SIMULATION
 47      if (DEBUG) $display("[MEM] Loaded long chirp segment 0 (0-1023)");
 48      `endif
 49      
 50      // Segment 1 (addresses 1024-2047)
 51      $readmemh(LONG_I_FILE_SEG1, long_chirp_i, 1024, 2047);
 52      $readmemh(LONG_Q_FILE_SEG1, long_chirp_q, 1024, 2047);
 53      `ifdef SIMULATION
 54      if (DEBUG) $display("[MEM] Loaded long chirp segment 1 (1024-2047)");
 55      `endif
 56      
 57      // Segment 2 (addresses 2048-3071)
 58      $readmemh(LONG_I_FILE_SEG2, long_chirp_i, 2048, 3071);
 59      $readmemh(LONG_Q_FILE_SEG2, long_chirp_q, 2048, 3071);
 60      `ifdef SIMULATION
 61      if (DEBUG) $display("[MEM] Loaded long chirp segment 2 (2048-3071)");
 62      `endif
 63      
 64      // Segment 3 (addresses 3072-4095)
 65      $readmemh(LONG_I_FILE_SEG3, long_chirp_i, 3072, 4095);
 66      $readmemh(LONG_Q_FILE_SEG3, long_chirp_q, 3072, 4095);
 67      `ifdef SIMULATION
 68      if (DEBUG) $display("[MEM] Loaded long chirp segment 3 (3072-4095)");
 69      `endif
 70      
 71      // === LOAD SHORT CHIRP ===
 72      // Load first 50 samples (0-49). Explicit range prevents iverilog warning
 73      // about insufficient words for the full [0:1023] array.
 74      $readmemh(SHORT_I_FILE, short_chirp_i, 0, 49);
 75      $readmemh(SHORT_Q_FILE, short_chirp_q, 0, 49);
 76      `ifdef SIMULATION
 77      if (DEBUG) $display("[MEM] Loaded short chirp (0-49)");
 78      `endif
 79      
 80      // Zero pad remaining 974 samples (50-1023)
 81      for (i = 50; i < 1024; i = i + 1) begin
 82          short_chirp_i[i] = 16'h0000;
 83          short_chirp_q[i] = 16'h0000;
 84      end
 85      `ifdef SIMULATION
 86      if (DEBUG) $display("[MEM] Zero-padded short chirp from 50-1023");
 87      
 88      // === VERIFICATION ===
 89      if (DEBUG) begin
 90          $display("[MEM] Memory loading complete. Verification samples:");
 91          $display("  Long[0]:     I=%h Q=%h", long_chirp_i[0], long_chirp_q[0]);
 92          $display("  Long[1023]:  I=%h Q=%h", long_chirp_i[1023], long_chirp_q[1023]);
 93          $display("  Long[1024]:  I=%h Q=%h", long_chirp_i[1024], long_chirp_q[1024]);
 94          $display("  Long[2047]:  I=%h Q=%h", long_chirp_i[2047], long_chirp_q[2047]);
 95          $display("  Long[2048]:  I=%h Q=%h", long_chirp_i[2048], long_chirp_q[2048]);
 96          $display("  Long[3071]:  I=%h Q=%h", long_chirp_i[3071], long_chirp_q[3071]);
 97          $display("  Long[3072]:  I=%h Q=%h", long_chirp_i[3072], long_chirp_q[3072]);
 98          $display("  Long[4095]:  I=%h Q=%h", long_chirp_i[4095], long_chirp_q[4095]);
 99          $display("  Short[0]:    I=%h Q=%h", short_chirp_i[0], short_chirp_q[0]);
100          $display("  Short[49]:   I=%h Q=%h", short_chirp_i[49], short_chirp_q[49]);
101          $display("  Short[50]:   I=%h Q=%h (zero-padded)", short_chirp_i[50], short_chirp_q[50]);
102      end
103      `endif
104  end
105  
106  // Memory access logic
107  // long_addr is combinational — segment_select[1:0] concatenated with sample_addr[9:0]
108  wire [11:0] long_addr = {segment_select, sample_addr};
109  
110  // ---- BRAM read block (sync-only, sync reset) ----
111  // REQP-1839/1840 fix: BRAM output registers cannot have async resets.
112  // We use a synchronous reset instead, which Vivado maps to the BRAM
113  // RSTREGB port (supported by 7-series BRAM primitives).
114  always @(posedge clk) begin
115      if (!reset_n) begin
116          ref_i <= 16'd0;
117          ref_q <= 16'd0;
118      end else if (mem_request) begin
119          if (use_long_chirp) begin
120              ref_i <= long_chirp_i[long_addr];
121              ref_q <= long_chirp_q[long_addr];
122              
123              `ifdef SIMULATION
124              if (DEBUG && $time < 100) begin
125                  $display("[MEM @%0t] Long chirp: seg=%b, addr=%d, I=%h, Q=%h",
126                          $time, segment_select, long_addr,
127                          long_chirp_i[long_addr], long_chirp_q[long_addr]);
128              end
129              `endif
130          end else begin
131              // Short chirp (0-1023)
132              ref_i <= short_chirp_i[sample_addr];
133              ref_q <= short_chirp_q[sample_addr];
134              
135              `ifdef SIMULATION
136              if (DEBUG && $time < 100) begin
137                  $display("[MEM @%0t] Short chirp: addr=%d, I=%h, Q=%h",
138                          $time, sample_addr, short_chirp_i[sample_addr], short_chirp_q[sample_addr]);
139              end
140              `endif
141          end
142      end
143  end
144  
145  // ---- Control block (async reset for mem_ready only) ----
146  always @(posedge clk or negedge reset_n) begin
147      if (!reset_n) begin
148          mem_ready <= 1'b0;
149      end else begin
150          mem_ready <= mem_request;
151      end
152  end
153  
154  endmodule