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