blob: 57553d27a8447b8115aaf588d5157d47ad7a99ce [file] [log] [blame]
`default_nettype none
`timescale 1ns/10ps
module rom_stream_loader#(
parameter DATA_WIDTH=16,
parameter ADDRESS_WIDTH = 16
)(
input clk,
input reset,
// Loader nets
input load,
input [DATA_WIDTH-1:0] input_data,
input sck,
output reg ack,
// ROM nets
input rom_busy,
input rom_initialized,
output reg rom_request,
output reg [DATA_WIDTH-1:0] output_data,
output [ADDRESS_WIDTH-1:0] output_address
);
reg writing;
reg [ADDRESS_WIDTH-1:0] current_address;
wire rom_receive_ready;
wire request_written;
reg wait_fall_clk;
reg was_loading;
assign output_address = current_address;
assign rom_receive_ready = !rom_busy && rom_initialized;
assign request_written = was_loading & writing & ~rom_busy;
always @(posedge clk) begin
if(reset) begin
was_loading <= 1'b0;
end else if(load) begin
was_loading <= 1'b1;
end else begin
was_loading <= 1'b0;
end
end
always @(posedge clk) begin
if(reset) begin
wait_fall_clk <= 1'b0;
end else if((wait_fall_clk && !sck) || !load) begin
wait_fall_clk <= 1'b0;
end else if(rom_request) begin
wait_fall_clk <= 1'b1;
end
end
always @(posedge clk) begin
ack <= 1'b0;
if(load && !was_loading) begin
// Reset address on new load
current_address <= {ADDRESS_WIDTH{1'b0}};
end else if(request_written) begin
// Advance ROM address
current_address <= current_address + 1'b1;
ack <= 1'b1;
end
end
always @(posedge clk) begin
output_data <= input_data;
end
always @(posedge clk) begin
if(reset) begin
rom_request <= 1'b0;
writing <= 1'b0;
end else begin
// Wait for the rom_busy signal to know that the write started
if(rom_request & rom_busy) begin
rom_request <= 1'b0;
writing <= 1'b1;
end else if(request_written) begin
// Finished writing to ROM
writing <= 1'b0;
end else if(load && !writing && rom_receive_ready && !wait_fall_clk && sck) begin
rom_request <= 1'b1;
end
end
end
`ifdef FORMAL
// register for knowing if we have just started
reg f_past_valid = 0;
// start in reset
initial assume(reset);
initial assume(current_address==0);
initial assume(was_loading==0);
always @(posedge clk) begin
f_past_valid <= 1;
if(f_past_valid) begin
COVER_WRITING: cover(writing);
COVER_REQUEST: cover(rom_request);
COVER_ACK: cover(ack);
COVER_FEW_WRITES: cover(current_address == 'h7);
//COVER_RESTART_ADDRESS: cover($past(current_address)!=0 && $rose(reset) && rom_busy);
COVER_RESTART_ADDRESS: cover($past(current_address)!=0 && current_address==0);
if($past(rom_initialized))
assume(rom_initialized);
if(!$past(rom_receive_ready)) begin
ASSERT_ROM_REQUEST_WHEN_READY: assert(!rom_request);
end
if($past(ack) && !ack) begin
assume($changed(input_data));//!=$past(input_data));
end
if(rom_request) begin
assume(rom_request && rom_busy);
end
//if(!rom_busy && $past(rom_busy)) begin
if($fell(rom_busy)) begin
assume($past(rom_busy,2) && $past(rom_busy,3) && $past(rom_busy,4) && $past(rom_busy,5));
end
if(!$past(reset) && !reset && (load && !was_loading) && ($past(current_address)!='hffff) && $changed(current_address)) begin
ASSERT_ADDRESS_INCREMENT: assert(current_address == ($past(current_address)+1));
end
if($rose(rom_request)) begin
ASSERT_REQUEST_WHEN_BUSY: assert($past(!rom_busy));
end
if(!rom_initialized) begin
ASSERT_ROM_NOT_INITIALIZED: assert(!writing && !rom_request);
end
if(!reset && (writing || rom_request)) begin
ASSERT_ROM_INITIALIZED: assert(rom_initialized);
end
if(ack) begin
ASSERT_ACK: assert($fell(writing));
end
if(writing) begin
ASSERT_REQUEST_WHILE_WRITING: assert(!rom_request);
end
end
end
`endif
endmodule