`timescale 1ns / 1ps //////////////////////////////////////////////////////////////////////////////// // // The External SRAM is not fast enough for a 50MHz sample clock or the 33MHz PCI //clock, so the sample rate is limited to 25MHz and the bus access must be buffered //with dual-port RAM. //////////////////////////////////////////////////////////////////////////////// module dacdriver(data_out, clock_out, sram_data, sram_addr, sram_oe, sram_rd, sram_ce, dac_clock_in, bus_clock_in, ib_data, ib_addr, ib_read, ib_write, reset); output [15:0] data_out; output clock_out; inout [15:0] sram_data; output [18:0] sram_addr; output sram_oe; output sram_rd; output sram_ce; input dac_clock_in; input bus_clock_in; inout [15:0] ib_data; input [10:0] ib_addr; input ib_read; input ib_write; input reset; reg DAC_enable; reg [31:0] prescaler; reg prescaler_out; reg [18:0] end_address; reg [15:0] sram_data_buff; reg [18:0] counter; reg [31:0] ps_counter; reg [15:0] test_value; wire counter_clock; wire data_latch_clock; reg ima_start; reg ima_clear_start; wire ima_clear_start_or_rst; reg ima_write; reg ima_active; reg [18:0] ima_base_addr; reg [9:0] ima_length; reg [18:0] ima_addr; wire [15:0] ima_data; wire [9:0] ima_block_addr; reg ima_ce; reg ima_wr; reg ima_oe; reg [0:2] ima_prescale; reg [2:0] ima_state; reg pci_active; reg usb_active; reg [15:0] data_out_latch; reg [10:0] ib_addr_latch; assign sram_ce = DAC_enable ? 1'b1 : (ima_active ? ima_ce : 1'b0); assign sram_rd = DAC_enable ? 1'b1 : (ima_active ? ~ima_wr : 1'b1); assign sram_oe = DAC_enable ? 1'b1 : (ima_active ? ima_oe : 1'b0); assign sram_addr = DAC_enable ? counter : ima_addr; assign sram_data = DAC_enable ? 16'bz : (ima_write ? ima_data : 16'bz); always @ (posedge reset or posedge dac_clock_in) if(reset) ima_prescale <= 0; else ima_prescale <= ima_prescale + 1; always @ (posedge reset or posedge ima_prescale[0]) if(reset) begin ima_state <= 0; ima_clear_start <= 0; ima_active <= 0; ima_addr <= 0; ima_ce <= 0; ima_wr <= 0; ima_oe <= 0; end else begin case(ima_state) 0: begin ima_clear_start <= 0; ima_active <= 0; ima_addr <= 0; ima_ce <= 0; ima_wr <= 0; ima_oe <= 0; if(ima_start) ima_state <= ima_state + 1; end 1: begin ima_clear_start <= 1; ima_addr <= ima_base_addr; ima_active <= 1; ima_state <= ima_state + 1; end 2: begin ima_clear_start <= 0; ima_ce <= 1; if(ima_write) begin ima_state <= 3; end else begin ima_oe <= 1; ima_state <= 5; end end 3: begin ima_wr <= 1; ima_state <= ima_state + 1; end 4: if(ima_length != ima_block_addr) begin ima_wr <= 0; ima_state <= ima_state - 1; ima_addr <= ima_addr + 1; end else begin ima_wr <= 0; ima_state <= 0; end 5: if(ima_length != ima_block_addr) begin ima_ce <= 1; ima_oe <= 1; ima_addr <= ima_addr + 1; end else begin ima_ce <= 0; ima_oe <= 0; ima_state <= 0; end default: ima_state <= 0; endcase end assign data_out = DAC_enable ? sram_data_buff : 16'h8000; assign clock_out = counter_clock ^ test_value[0]; //polarity doesn't seem to matter assign counter_clock = (|prescaler) ? prescaler_out : dac_clock_in; assign data_latch_clock = ~counter_clock ^ test_value[1]; //invert polarity always @(posedge dac_clock_in or posedge reset) if (reset) begin ps_counter <= 0; prescaler_out <= 0; end else begin prescaler_out <= ~(|ps_counter); if(ps_counter >= prescaler) ps_counter <= 0; else ps_counter <= ps_counter + 1; end always @(posedge counter_clock or posedge reset) if (reset) counter <= 0; else if((counter >= end_address) || !DAC_enable) counter <= 0; else counter <= counter + 1; always @(posedge data_latch_clock or posedge reset) if(reset) sram_data_buff <= 0; else sram_data_buff <= sram_data; assign ima_clear_start_or_rst = reset | ima_clear_start; always @(posedge bus_clock_in or posedge ima_clear_start_or_rst) if (ima_clear_start_or_rst) ima_start <= 0; else if(ib_write & (ib_addr == 11'ha)) ima_start <= ib_data[2]; always @(posedge bus_clock_in or posedge reset) if (reset) begin pci_active <= 0; usb_active <= 0; DAC_enable <= 0; test_value <= 0; prescaler <= 0; end_address <= 0; test_value <= 0; ima_base_addr <= 0; ima_length <= 0; ima_write <= 0; end else begin if(ib_write) case(ib_addr) 11'h0: begin pci_active <= ib_data[0]; usb_active <= ib_data[1]; end 11'h1: DAC_enable <= ib_data[0]; 11'h2: test_value <= ib_data; 11'h3: prescaler[15:0] <= ib_data[15:0]; 11'h4: prescaler[31:16] <= ib_data[15:0]; 11'h5: end_address[15:0] <= ib_data[15:0]; 11'h6: end_address[18:16] <= ib_data[2:0]; 11'h7: ima_base_addr[15:0] <= ib_data; 11'h8: ima_base_addr[18:16] <= ib_data[2:0]; 11'h9: ima_length <= ib_data[9:0]; 11'ha: ima_write <= ib_data[1]; default:; endcase end assign ib_data = (ib_read & (ib_addr_latch <= 11'ha)) ? data_out_latch : 16'bz; always @(posedge bus_clock_in or posedge reset) if (reset) begin data_out_latch <= 0; ib_addr_latch <= 11'h7ff; end else begin case(ib_addr) 'h0: data_out_latch <= {14'b0,usb_active,pci_active}; 'h1: data_out_latch <= {15'b0,DAC_enable}; 'h2: data_out_latch <= test_value; 'h3: data_out_latch <= prescaler[15:0]; 'h4: data_out_latch <= prescaler[31:16]; 'h5: data_out_latch <= end_address[15:0]; 'h6: data_out_latch <= {13'b0,end_address[18:16]}; 'h7: data_out_latch <= ima_base_addr[15:0]; 'h8: data_out_latch <= {13'b0,ima_base_addr[18:16]}; 'h9: data_out_latch <= {6'b0,ima_length}; 'ha: data_out_latch <= {13'b0,ima_start,ima_write,ima_active}; default:; endcase ib_addr_latch <= ib_addr; end wire [15:0] ram_data; assign ima_block_addr = (ima_addr[9:0] - ima_base_addr[9:0]); /* a small (256 word) buffer RAMB4_S16_S16 block0( .CLKA(bus_clock_in),.RSTA(reset), .ENA(1'b1),.WEA(ib_write & (ib_addr[19:10] == 10'h001)), .ADDRA(ib_addr[7:0]),.DIA(ib_data),.DOA(ram_data), .CLKB(ima_prescale[0]),.RSTB(reset), .ENB(1'b1),.WEB(ima_oe), .ADDRB(ima_block_addr[7:0]),.DIB(sram_data),.DOB(ima_data) ); */ //A larger (1024 Word) buffer. This could be expanded to 2048 words RAMB4_S4_S4 block0( .CLKA(bus_clock_in),.RSTA(reset), .ENA(1'b1),.WEA(ib_write & ib_addr[10]), .ADDRA(ib_addr[9:0]),.DIA(ib_data[3:0]),.DOA(ram_data[3:0]), .CLKB(ima_prescale[0]),.RSTB(reset), .ENB(1'b1),.WEB(ima_oe), .ADDRB(ima_block_addr),.DIB(sram_data[3:0]),.DOB(ima_data[3:0]) ); RAMB4_S4_S4 block1( .CLKA(bus_clock_in),.RSTA(reset), .ENA(1'b1),.WEA(ib_write & ib_addr[10]), .ADDRA(ib_addr[9:0]),.DIA(ib_data[7:4]),.DOA(ram_data[7:4]), .CLKB(ima_prescale[0]),.RSTB(reset), .ENB(1'b1),.WEB(ima_oe), .ADDRB(ima_block_addr),.DIB(sram_data[7:4]),.DOB(ima_data[7:4]) ); RAMB4_S4_S4 block2( .CLKA(bus_clock_in),.RSTA(reset), .ENA(1'b1),.WEA(ib_write & ib_addr[10]), .ADDRA(ib_addr[9:0]),.DIA(ib_data[11:8]),.DOA(ram_data[11:8]), .CLKB(ima_prescale[0]),.RSTB(reset), .ENB(1'b1),.WEB(ima_oe), .ADDRB(ima_block_addr),.DIB(sram_data[11:8]),.DOB(ima_data[11:8]) ); RAMB4_S4_S4 block3( .CLKA(bus_clock_in),.RSTA(reset), .ENA(1'b1),.WEA(ib_write & ib_addr[10]), .ADDRA(ib_addr[9:0]),.DIA(ib_data[15:12]),.DOA(ram_data[15:12]), .CLKB(ima_prescale[0]),.RSTB(reset), .ENB(1'b1),.WEB(ima_oe), .ADDRB(ima_block_addr),.DIB(sram_data[15:12]),.DOB(ima_data[15:12]) ); assign ib_data = (ib_read & ib_addr_latch[10]) ? ram_data : 16'bz; endmodule