upsilon/firmware/rtl/waveform/waveform.v

204 lines
4.1 KiB
Coq
Raw Normal View History

/* Write a waveform to a DAC. */
2023-05-10 14:35:57 -04:00
/* TODO: Add "how many values to go" counter. */
module waveform #(
2023-01-22 23:43:51 -05:00
parameter DAC_WID = 24,
parameter DAC_WID_SIZ = 5,
parameter DAC_POLARITY = 0,
parameter DAC_PHASE = 1,
parameter DAC_CYCLE_HALF_WAIT = 10,
parameter DAC_CYCLE_HALF_WAIT_SIZ = 4,
parameter DAC_SS_WAIT = 5,
parameter DAC_SS_WAIT_SIZ = 3,
2023-02-25 16:17:04 -05:00
parameter TIMER_WID = 32,
2023-03-10 17:59:26 -05:00
parameter WORD_WID = 20,
2023-02-25 16:17:04 -05:00
parameter WORD_AMNT_WID = 11,
parameter [WORD_AMNT_WID-1:0] WORD_AMNT = 2047,
parameter RAM_WID = 32,
parameter RAM_WORD_WID = 16,
parameter RAM_WORD_INCR = 2
2022-12-28 14:32:35 -05:00
) (
input clk,
2023-05-10 14:35:57 -04:00
input rst_L,
2022-12-28 14:32:35 -05:00
input arm,
2023-03-15 02:24:28 -04:00
input halt_on_finish,
2023-04-03 00:39:26 -04:00
/* NOTE:
* finished is used when a module wants to wait for a
* waveform with the halt_on_finish flag finishes
* one waveform.
*
* running is used when a module wants to know when
* the waveform module has finished running after
* deasserting arm.
*
* When in doubt, deassert arm and wait for running
* to be deasserted.
*/
2023-03-15 02:24:28 -04:00
output reg finished,
2023-04-02 17:25:19 -04:00
output running,
2023-01-22 23:58:38 -05:00
input [TIMER_WID-1:0] time_to_wait,
2022-12-28 14:32:35 -05:00
2023-02-25 16:17:04 -05:00
/* User interface */
input refresh_start,
input [RAM_WID-1:0] start_addr,
output reg refresh_finished,
/* RAM interface */
output reg [RAM_WID-1:0] ram_dma_addr,
input [RAM_WORD_WID-1:0] ram_word,
output reg ram_read,
input ram_valid,
2022-12-28 14:32:35 -05:00
/* DAC wires. */
output mosi,
2023-03-10 17:59:26 -05:00
output sck,
output ss_L
2022-12-28 14:32:35 -05:00
);
wire [WORD_WID-1:0] word;
2023-05-10 14:35:57 -04:00
reg word_next = 0;
wire word_ok;
wire word_last;
2023-05-10 14:35:57 -04:00
reg word_rst = 1;
2023-02-25 16:17:04 -05:00
bram_interface #(
.WORD_WID(WORD_WID),
.WORD_AMNT_WID(WORD_AMNT_WID),
.WORD_AMNT(WORD_AMNT),
.RAM_WID(RAM_WID),
.RAM_WORD_WID(RAM_WORD_WID),
.RAM_WORD_INCR(RAM_WORD_INCR)
) bram (
.clk(clk),
2023-05-10 14:35:57 -04:00
.rst_L(rst_L),
2023-02-25 16:17:04 -05:00
.word(word),
.word_next(word_next),
.word_last(word_last),
.word_ok(word_ok),
.word_rst(word_rst),
2023-02-25 16:17:04 -05:00
.refresh_start(refresh_start),
.start_addr(start_addr),
.refresh_finished(refresh_finished),
2023-02-25 16:17:04 -05:00
.ram_dma_addr(ram_dma_addr),
.ram_word(ram_word),
.ram_read(ram_read),
.ram_valid(ram_valid)
);
2022-12-28 14:32:35 -05:00
wire dac_finished;
2023-05-10 14:35:57 -04:00
reg dac_arm = 0;
reg [DAC_WID-1:0] dac_out = 0;
wire dac_ready_to_arm_unused;
spi_master_ss_no_read #(
.WID(DAC_WID),
.WID_LEN(DAC_WID_SIZ),
.CYCLE_HALF_WAIT(DAC_CYCLE_HALF_WAIT),
.TIMER_LEN(DAC_CYCLE_HALF_WAIT_SIZ),
.POLARITY(DAC_POLARITY),
.PHASE(DAC_PHASE),
.SS_WAIT(DAC_SS_WAIT),
.SS_WAIT_TIMER_LEN(DAC_SS_WAIT_SIZ)
) dac_master (
.clk(clk),
2023-05-10 14:35:57 -04:00
.rst_L(rst_L),
.ready_to_arm(dac_ready_to_arm_unused),
.mosi(mosi),
.sck_wire(sck),
.ss_L(ss_L),
.finished(dac_finished),
.arm(dac_arm),
.to_slave(dac_out)
);
2022-12-28 14:32:35 -05:00
localparam WAIT_ON_ARM = 0;
2023-01-22 23:58:38 -05:00
localparam DO_WAIT = 1;
localparam RECV_WORD = 2;
localparam WAIT_ON_DAC = 3;
2023-04-02 17:25:19 -04:00
localparam WAIT_ON_DISARM = 4;
reg [2:0] state = WAIT_ON_ARM;
2022-12-28 14:32:35 -05:00
2023-01-22 23:58:38 -05:00
reg [TIMER_WID-1:0] wait_timer = 0;
2023-04-02 17:25:19 -04:00
assign running = state != WAIT_ON_ARM;
2023-05-10 14:35:57 -04:00
always @ (posedge clk) if (!rst_L) begin
state <= WAIT_ON_ARM;
wait_timer <= 0;
finished <= 0;
word_rst <= 1;
word_next <= 0;
dac_out <= 0;
dac_arm <= 0;
end else case (state)
2023-03-15 02:24:28 -04:00
WAIT_ON_ARM: begin
finished <= 0;
if (arm) begin
state <= DO_WAIT;
2023-05-10 14:35:57 -04:00
word_rst <= 0;
2023-03-15 02:24:28 -04:00
wait_timer <= time_to_wait;
end else begin
word_rst <= 1;
end
2022-12-28 14:32:35 -05:00
end
2023-01-22 23:58:38 -05:00
DO_WAIT: if (!arm) begin
state <= WAIT_ON_ARM;
end else if (wait_timer == 0) begin
word_next <= 1;
state <= RECV_WORD;
2023-01-27 17:27:20 -05:00
wait_timer <= time_to_wait;
2023-01-22 23:58:38 -05:00
end else begin
wait_timer <= wait_timer - 1;
end
2023-04-02 17:25:19 -04:00
RECV_WORD: begin
2023-04-03 15:29:20 -04:00
`ifdef VERILATOR_SIMULATION
2023-04-02 17:25:19 -04:00
if (!word_next) begin
$error("RECV_WORD: word_next not asserted means hang");
end
`endif
2023-01-22 23:43:51 -05:00
2023-04-02 17:25:19 -04:00
if (word_ok) begin
dac_out <= {4'b0001, word};
dac_arm <= 1;
word_next <= 0;
state <= WAIT_ON_DAC;
end
2022-12-28 14:32:35 -05:00
end
2023-04-02 17:25:19 -04:00
WAIT_ON_DAC: begin
2023-04-03 15:29:20 -04:00
`ifdef VERILATOR_SIMULATION
2023-04-02 17:25:19 -04:00
if (!dac_arm) begin
$error("WAIT_ON_DAC: dac_arm not asserted means hang");
end
`endif
if (dac_finished) begin
dac_arm <= 0;
/* Was the last word read *the* last word? */
if (word_last && halt_on_finish) begin
state <= WAIT_ON_DISARM;
2023-03-15 02:24:28 -04:00
finished <= 1;
2023-04-02 17:25:19 -04:00
end else begin
state <= DO_WAIT;
wait_timer <= time_to_wait;
2023-03-15 02:24:28 -04:00
end
2022-12-28 14:32:35 -05:00
end
2023-03-10 17:59:26 -05:00
end
2023-04-02 17:25:19 -04:00
WAIT_ON_DISARM: if (!arm) begin
state <= WAIT_ON_ARM;
end
2022-12-28 14:32:35 -05:00
endcase
2023-03-15 02:24:28 -04:00
/* Warning! This will crash verilator with a segmentation fault!
`ifdef VERILATOR
initial begin
$dumpfile("waveform.fst");
$dumpvars();
end
`endif
*/
2022-12-28 14:32:35 -05:00
endmodule
2023-03-15 02:24:28 -04:00
`undefineall