// LLRF history buffers // Larry Doolittle, LBNL, January 2003 // Mostly an instantiation of a bunch of dual port RAMs, but also // includes address generation and data multiplexing on the ADC end, // and a little bit of data multiplexing for host read of the data. // Can be compiled in two modes: if you //`define TEST_BUFFERS // then the 6kBytes of RAM is used up as a single large (4096 long) buffer for // all 12 bits of a single ADC channel. This can be useful for // Otherwise, the RAM is split up into multiple pieces for simultaneous // recording of forward, reflected, and cavity (these three have their // decimation controlled), and one more of reflected only (actually // configurable) at the beginning of the pulse. // Consider having this module latch its configuration information // (trace_sel, wide_trace_config, and rising_edge_decay) from the // host data bus, rather than having the top level module handle that. `timescale 1ns / 1ns module history( clk40, rstn, dals, dbls, dcls, ddls, // input data and their clock outm, // option to monitor output channel trace_enable, address_at_pulse_end, history_config, test_buffers_config, clk_host, host_dout, host_addr, we); // host interface input clk40, rstn; input [11:0] dals, dbls, dcls, ddls, outm; input clk_host, we; output [15:0] host_dout; input [13:0] host_addr; input trace_enable; // valid in the 40 MHz clock domain output [15:0] address_at_pulse_end; input [15:0] history_config; // not necessarily all bits are used output test_buffers_config; wire [5:0] wide_trace_config = history_config[5:0]; wire [1:0] trace_sel = history_config[9:8]; wire rising_edge_decay = history_config[12]; wire [(10 - 1):0] wide_address; reg [11:0] trace_data; reg decay_write_squelch; wire [11:0] decay_trace_dout; reg [15:0] trace_address, address_at_pulse_end; wire decay_write_enable = trace_enable & ~decay_write_squelch; wire [9:0] decay_address = trace_address[9:0]; wire test_buffers_config = 0; ramdp1024x12 decay_trace( .ADDRA(decay_address), .RSTA(1'b0), .ENA(1'b1), .WEA(decay_write_enable), .CLKA(clk40), .DIA(trace_data), //.DOA(void), // read from host .ADDRB(host_addr[(10 - 1):0]), .RSTB(1'b0), .ENB(1'b1), .WEB(1'b0), // host write not allowed .CLKB(clk_host), .DIB(12'b0000000000), // not used .DOB(decay_trace_dout)); wire [31:0] wide_trace_din = {dals[11:1], dbls[11:1], dcls[11:2]}; wire [31:0] wide_trace_dout; wire [31:0] unused_32; ramdp1024x32 wide_trace( .ADDRA(wide_address), .RSTA(1'b0), .ENA(1'b1), .WEA(trace_enable), .CLKA(clk40), .DIA(wide_trace_din), .DOA(unused_32), // read from host .ADDRB(host_addr[9:0] ), .RSTB(1'b0), .ENB(1'b1), .WEB(1'b0), // host write not allowed .CLKB(clk_host), .DIB({32{1'b0}}), // not used .DOB(wide_trace_dout)); always @(posedge clk40 or negedge rstn) if (~rstn) begin decay_write_squelch <= 1'b0; trace_data <= 0; trace_address <= 0; address_at_pulse_end <= 0; end else begin if((~trace_enable) | (rising_edge_decay & trace_address[10])) decay_write_squelch <= trace_enable; // Ordinary multiplexer; a bank of SRL16E's could be used instead // to reduce the cell footprint, at the expense of more more arcane // Verilog and more awkward host software. trace_data <= trace_sel[1] ? ( trace_sel[0] ? ddls : dcls ) : ( trace_sel[0] ? dbls : dals ); trace_address <= trace_enable ? (trace_address + 1'b1) : {16{1'b0}}; if(trace_enable) address_at_pulse_end <= trace_address; end assign wide_address = {trace_address[9:8], ~wide_trace_config[5] ? trace_address[7] : trace_address[15], ~wide_trace_config[4] ? trace_address[6] : trace_address[14], ~wide_trace_config[3] ? trace_address[5] : trace_address[13], ~wide_trace_config[2] ? trace_address[4] : trace_address[12], ~wide_trace_config[1] ? trace_address[3] : trace_address[11], ~wide_trace_config[0] ? trace_address[2] : trace_address[10], trace_address[1:0]}; assign host_dout = ~host_addr[13] ? {4'b0000, decay_trace_dout } // 0x4000 through 0x7ffc : ( ~host_addr[12] ? ( ~host_addr[11] ? {4'b0000, wide_trace_dout[31:21], 1'b0 } // 0x8000 through 0x9ffc : {4'b0000, wide_trace_dout[20:10], 1'b0 } // 0xa000 through 0xbffc ) : {4'b0000, wide_trace_dout[ 9: 0], 2'b00} // 0xc000 through 0xffff ) ; endmodule