diff --git a/hdl/logic-analyzer/README.md b/hdl/logic-analyzer/README.md new file mode 100644 index 0000000..39c97f4 --- /dev/null +++ b/hdl/logic-analyzer/README.md @@ -0,0 +1,23 @@ +# Logic-analyzer capture memory + +`rtl/la_capture_buffer.v` is a portable Verilog-2001 true dual-port capture +buffer. It deliberately contains no Altera/Intel primitive, board pin, UART, +or trigger logic. Quartus infers Cyclone IV M9K memory from the registered +read and synchronous write ports. + +Parameters: + +| Parameter | Meaning | Default | +|---|---|---:| +| `SAMPLE_WIDTH` | Number of simultaneously captured digital inputs | 16 | +| `ADDR_WIDTH` | Buffer depth as `2**ADDR_WIDTH` | 12 (4096 samples) | + +The write and read clocks may be different. The caller owns clock-domain +crossing for addresses/status and must keep a read address stable until the +registered `rd_data` is valid on the following `rd_clk` edge. + +Example Quartus source assignment: + +```tcl +set_global_assignment -name VERILOG_FILE path/to/templates/hdl/logic-analyzer/rtl/la_capture_buffer.v +``` diff --git a/hdl/logic-analyzer/rtl/la_capture_buffer.v b/hdl/logic-analyzer/rtl/la_capture_buffer.v new file mode 100644 index 0000000..4665139 --- /dev/null +++ b/hdl/logic-analyzer/rtl/la_capture_buffer.v @@ -0,0 +1,29 @@ +// Portable dual-clock capture RAM for FPGA logic analyzers. +// The module intentionally contains no vendor primitives: Quartus infers M9K +// blocks on Cyclone IV, while other tools may infer their native block RAM. +module la_capture_buffer #( + parameter SAMPLE_WIDTH = 16, + parameter ADDR_WIDTH = 12 +) ( + input wire wr_clk, + input wire wr_en, + input wire [ADDR_WIDTH-1:0] wr_addr, + input wire [SAMPLE_WIDTH-1:0] wr_data, + + input wire rd_clk, + input wire [ADDR_WIDTH-1:0] rd_addr, + output reg [SAMPLE_WIDTH-1:0] rd_data +); + localparam DEPTH = (1 << ADDR_WIDTH); + + reg [SAMPLE_WIDTH-1:0] memory [0:DEPTH-1]; + + always @(posedge wr_clk) begin + if (wr_en) + memory[wr_addr] <= wr_data; + end + + // Registered read is supported directly by Cyclone IV M9K blocks. + always @(posedge rd_clk) + rd_data <= memory[rd_addr]; +endmodule