aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/example.v488
1 files changed, 432 insertions, 56 deletions
diff --git a/src/example.v b/src/example.v
index 63ad7ed..c588dba 100644
--- a/src/example.v
+++ b/src/example.v
@@ -660,50 +660,365 @@ module on_button_write(input wire clock_50mhz,
end // always @ (posedge clock_50mhz)
endmodule
-module dumb_write(input wire clock_50mhz,
- input wire reset,
-
- input wire can_write,
- output wire [15:0] write_data,
+module winbond_spi(input wire clock_50mhz,
+ input wire reset,
+
+ input wire operate,
+ input wire [31:0] send_data,
+ input wire [2:0] bytes_to_send,
+ input wire [14:0] bytes_to_receive,
+
+ output reg byte_ready,
+ output reg [7:0] received_data,
+ output reg operation_finished,
+
+ output reg sdo,
+ input wire sdi,
+ output wire sck,
+ output reg ss_n
+ );
+ reg working;
+ reg operating;
- output wire want_to_write,
- output wire [17:0] write_addr,
+ reg [31:0] sdo_data;
+ reg [5:0] bits_to_output;
- input wire [17:0] written_memory_base,
- input wire start_operating
- );
- reg [9:0] write_idx;
- /* To each word we'll be writing its offset from written_memory_base */
- assign write_data = write_idx;
- assign write_addr = written_memory_base + write_idx;
+ parameter sending = 0;
+ parameter receiving = 1;
+ reg state;
- parameter max_idx = 599;
- reg operating;
- assign want_to_write = operating;
+ reg [6:0] sdi_data;
+ reg [17:0] bits_to_receive;
+ reg [3:0] bits_received;
+ reg send_only_operation;
- reg [1:0] write_state;
+ assign sck = clock_50mhz;
always @ (posedge clock_50mhz) begin
- if (reset) begin
- write_idx <= 10'bxxxxxxxxxx;
+ if (reset || !operate) begin
operating <= 0;
+ byte_ready <= 0;
+ operation_finished <= 0;
+
+ bits_to_receive <= 18'hXXXXX;
+ bits_to_output <= 6'hXX;
+ sdi_data <= 7'hXX;
+ sdo_data <= 32'hXXXXXXXX;
+ received_data <= 8'hXX;
+ send_only_operation <= 1'bx;
+ state <= 1'bx;
end
else begin
- if (start_operating && !operating) begin
- operating <= 1;
- write_state <= 0;
- write_idx <= 0;
+ operating <= 1;
+
+ if (!operating && operate) begin
+ bits_to_receive <= bytes_to_receive * 8;
+ bits_to_output <= bytes_to_send * 8;
+ sdo_data <= send_data;
+ send_only_operation <= bytes_to_receive == 0;
+ state <= sending;
+ byte_ready <= 0;
+ operation_finished <= 0;
+
+ sdi_data <= 7'hXX;
+ received_data <= 8'hXX;
end
- else if (operating) begin
- if (can_write) begin
- write_idx <= write_idx + 1;
- if (write_idx == max_idx)
- operating <= 0;
+ else begin
+ if (operation_finished) begin
+ byte_ready <= 0;
+
+ bits_to_receive <= 18'hXXXXX;
+ bits_to_output <= 6'hXX;
+ sdi_data <= 7'hXX;
+ sdo_data <= 32'hXXXXXXXX;
+ received_data <= 8'hXX;
+ send_only_operation <= 1'bx;
+ state <= 1'bx;
end
+ else begin
+ if (state == sending) begin
+ byte_ready <= 0;
+ bits_to_output <= bits_to_output - 1;
+ sdo_data <= {sdo_data[30:0], 1'bx};
+
+ if (bits_to_output - 1 == 0) begin
+ state <= receiving;
+ if (send_only_operation)
+ operation_finished <= 1;
+ end
+
+ sdi_data <= 7'hXX;
+ received_data <= 8'hXX;
+ end // if (state == sending)
+
+ if (state == receiving) begin
+
+ bits_to_receive <= bits_to_receive - 1;
+ sdi_data <= {sdi_data[5:0], sdi};
+
+ if (bits_to_receive % 8 - 1 == 0) begin
+ byte_ready <= 1;
+ received_data <= {sdi_data[6:0], sdi};
+ end
+ else begin
+ byte_ready <= 0;
+ received_data <= 8'hXX;
+ end
+
+ if (bits_to_receive - 1 == 0)
+ operation_finished <= 1;
+
+ bits_to_output <= 6'hXX;
+ sdo_data <= 32'hXXXXXXXX;
+ end // if (state == receiving)
+ end // else: !if(operation_finished)
+ end // else: !if(!operating && operate)
+ end // else: !if(reset || !operate)
+ end // always @ (posedge clock_50mhz)
+
+ always @ (negedge clock_50mhz) begin
+ sdo <= sdo_data[31];
+
+ if (!operating) begin
+ ss_n <= 1;
+ end
+ else begin
+ if (operation_finished)
+ ss_n <= 1;
+ else
+ ss_n <= 0;
+ end
+ end // always @ (negedge clock_50mhz)
+endmodule // winbond_spi
+
+module spi_chip_powerup(input wire clock_50mhz,
+ input wire reset,
+
+ output reg want_spi_operation,
+ output wire [31:0] spi_send_data,
+ output wire [2:0] spi_bytes_to_send,
+ output wire [14:0] spi_bytes_to_receive,
+
+ input wire spi_operation_finished,
+
+ input wire operate,
+ output reg finished_operating
+ );
+ parameter power_up_instruction = 8'hAB;
+
+ assign spi_send_data = {power_up_instruction, 24'hXXXXXX};
+ assign spi_bytes_to_send = 1;
+ assign spi_bytes_to_receive = 0;
+
+ parameter sending_power_up = 0;
+ parameter waiting = 1;
+ reg state;
+
+ parameter freq = 50; /* Mhz */
+ parameter powerup_wait_time = 3000; /* ns */
+ parameter powerup_wait_ticks = powerup_wait_time * freq / 1000;
+ reg [7:0] powerup_wait_counter;
+
+ reg operating;
+
+ always @ (posedge clock_50mhz) begin
+ if (reset || !operate) begin
+ want_spi_operation <= 0;
+ finished_operating <= 0;
+ operating <= 0;
+
+ state <= 1'bx;
+ powerup_wait_counter <= 8'hXX;
+ end
+ else begin
+ operating <= 1;
+
+ if (!operating && operate) begin
+ want_spi_operation <= 1;
+ finished_operating <= 0;
+ state <= sending_power_up;
+
+ powerup_wait_counter <= 8'hXX;
end
- end // else: !if(reset)
+ else begin
+ if (state == sending_power_up) begin
+ finished_operating <= 0;
+
+ if (spi_operation_finished) begin
+ powerup_wait_counter <= powerup_wait_ticks;
+ state <= waiting;
+ want_spi_operation <= 0;
+ end
+ else begin
+ want_spi_operation <= 1;
+
+ powerup_wait_counter <= 8'hXX;
+ end
+ end // if (state == sending_power_up)
+
+ if (state == waiting) begin
+ want_spi_operation <= 0;
+
+ if (powerup_wait_counter == 0) begin
+ finished_operating <= 1;
+ end
+ else begin
+ finished_operating <= 0;
+ powerup_wait_counter <= powerup_wait_counter - 1;
+ end
+ end // if (state == waiting)
+ end // else: !if(!operating && operate)
+ end // else: !if(reset || !operate)
+ end // always @ (posedge clock_50mhz)
+endmodule // spi_chip_powerup
+
+module spi_sram_copy(input wire clock_50mhz,
+ input wire reset,
+
+ input wire can_write,
+ output reg [15:0] write_data,
+
+ output wire want_to_write, /* sram memory */
+ output wire [17:0] write_addr,
+
+ input wire [17:0] written_memory_base,
+
+ output reg want_spi_operation,
+ output wire [31:0] spi_send_data,
+ output wire [2:0] spi_bytes_to_send,
+ output wire [14:0] spi_bytes_to_receive,
+
+ input wire spi_byte_ready,
+ input wire [7:0] received_byte,
+
+ input wire [23:0] flash_memory_base,
+
+ input wire operate,
+ output reg finished_operating
+ );
+ parameter fast_read_instruction = 8'h0B;
+
+ parameter words_to_copy = 600;
+
+ assign spi_bytes_to_send = 5;
+
+ reg [9:0] words_left_to_receive;
+ assign spi_bytes_to_receive = words_left_to_receive * 2;
+
+ reg [9:0] word_idx;
+
+ assign write_addr = written_memory_base + word_idx;
+
+ wire [23:0] read_addr;
+ assign read_addr = flash_memory_base + 16 * word_idx;
+ assign spi_send_data = {fast_read_instruction, read_addr};
+
+ reg write_word_ready;
+ assign want_to_write = write_word_ready;
+
+ wire write_happens;
+ assign write_happens = want_to_write && can_write;
+
+ reg [7:0] high_byte;
+ reg high_byte_received;
+
+ wire word_received;
+ assign word_received = high_byte_received && spi_byte_ready;
+
+ /* true if next spi data word came b4 we handled the previous one :c */
+ wire data_discarded;
+ assign data_discarded = word_received && write_word_ready && !write_happens;
+
+ reg reading_finished;
+
+ reg operating;
+
+ always @ (posedge clock_50mhz) begin
+ if (reset || !operate) begin
+ operating <= 0;
+ want_spi_operation <= 0;
+ finished_operating <= 0;
+ write_word_ready <= 0;
+
+ words_left_to_receive <= 10'hXXX;
+ word_idx <= 10'hXXX;
+ high_byte <= 8'hXX;
+ high_byte_received <= 1'bx;
+ reading_finished <= 1'bx;
+ end // if (reset || !operate)
+ else begin
+ operating <= 1;
+
+ if (operate && !operating) begin
+ want_spi_operation <= 1;
+ finished_operating <= 0;
+ write_word_ready <= 0;
+ words_left_to_receive <= words_to_copy;
+ word_idx <= 0;
+ reading_finished <= 0;
+ high_byte_received <= 0;
+
+ high_byte <= 8'hXX;
+ end // if (operate && !operating)
+ else if (finished_operating) begin
+ want_spi_operation <= 0;
+ write_word_ready <= 0;
+ words_left_to_receive <= 10'hXX;
+ word_idx <= 10'hXX;
+ reading_finished <= 1'bx;
+ high_byte_received <= 1'bx;
+ high_byte <= 8'hXX;
+ end
+ else begin
+ /*
+ * if spi data comes too fast, we discard it and start reading
+ * anew once we write current data
+ */
+ if (reading_finished)
+ want_spi_operation <= 0;
+ else if (data_discarded)
+ want_spi_operation <= 0;
+ else if (write_happens)
+ want_spi_operation <= 1;
+
+ if (spi_byte_ready) begin
+ if (high_byte_received) begin
+ high_byte_received <= 0;
+
+ high_byte <= 8'hXX;
+ end
+ else begin
+ high_byte <= received_byte;
+ high_byte_received <= 1;
+ end
+ end // if (spi_byte_ready)
+
+ if (word_received && !data_discarded) begin
+ words_left_to_receive <= words_left_to_receive - 1;
+ write_word_ready <= 1;
+ write_data <= {high_byte, received_byte};
+
+ if (words_left_to_receive - 1 == 0)
+ reading_finished <= 1;
+ end
+ else if (write_happens) begin
+ write_word_ready <= 0;
+ write_data <= 16'hXXXX;
+ end
+ else if (!write_word_ready) begin
+ write_data <= 16'hXXXX;
+ end
+
+ if (write_happens) begin
+ word_idx <= word_idx + 1;
+
+ if (reading_finished)
+ finished_operating <= 1;
+ end
+ end // else: !if(finished_operating)
+ end // else: !if(reset || !operate)
end // always @ (posedge clock_50mhz)
-endmodule // dumb_write
+endmodule // spi_sram_copy
module top(input wire clock_100mhz,
input wire but1,
@@ -732,20 +1047,25 @@ module top(input wire clock_100mhz,
* timing problems
*/
reg reset;
- /*
- * `initial` usually isn't synthesizable, but in case
- * it is on some particular FPGA - we try to make use of it
- */
- initial
- reset <= 1;
reg err_disabled;
reg clock_50mhz;
+ /*
+ * `initial` usually isn't synthesizable, but it helps run the code
+ * in test-benches
+ */
+ initial begin
+ reset <= 1;
+ clock_50mhz <= 0;
+ err_disabled <= 0;
+ end
+
always @ (posedge clock_100mhz)
clock_50mhz <= clock_50mhz + 1;
parameter memory_base = 18'b010101010101010101;
+ parameter flash_base = 24'h000000;
wire vga_io_available;
assign vga_io_available = 1;
@@ -760,19 +1080,80 @@ module top(input wire clock_100mhz,
always @ (posedge clock_50mhz)
last_reset <= reset;
- wire dumbwrite_io_available;
- assign dumbwrite_io_available = vga_io_available && !vga_wants_io;
-
- wire dumbwrite_wants_io;
- wire [17:0] dumbwrite_io_addr;
- wire [15:0] dumbwrite_write_data;
-
- dumb_write dumbwrite(clock_50mhz, reset, dumbwrite_io_available, dumbwrite_write_data,
- dumbwrite_wants_io, dumbwrite_io_addr, memory_base,
- !reset && last_reset);
+ wire spi_operation_wanted;
+ wire [31:0] spi_send_data;
+ wire [2:0] spi_bytes_to_send;
+ wire [14:0] spi_bytes_to_receive;
+ wire spi_byte_ready;
+ wire [7:0] spi_received_data;
+ wire spi_operation_finished;
+
+ winbond_spi spi(clock_50mhz, reset, spi_operation_wanted,
+ spi_send_data, spi_bytes_to_send,
+ spi_bytes_to_receive, spi_byte_ready,
+ spi_received_data, spi_operation_finished,
+ sdo, sdi, sck, ss_n);
+
+ wire chip_powerup_wants_operation;
+ wire [31:0] chip_powerup_send_data;
+ wire [2:0] chip_powerup_bytes_to_send;
+ wire [14:0] chip_powerup_bytes_to_receive;
+ wire chip_powerup_finished_operating;
+
+ spi_chip_powerup chip_powerup(clock_50mhz, reset,
+ chip_powerup_wants_operation,
+ chip_powerup_send_data,
+ chip_powerup_bytes_to_send,
+ chip_powerup_bytes_to_receive,
+ spi_operation_finished, !reset,
+ chip_powerup_finished_operating);
+
+ wire data_copy_sram_io_available;
+ assign data_copy_sram_io_available = vga_io_available && !vga_wants_io;
+ wire [15:0] data_copy_write_data;
+ wire data_copy_wants_sram_io;
+ wire [17:0] data_copy_sram_io_addr;
+ wire data_copy_wants_spi_operation;
+ wire [31:0] data_copy_spi_send_data;
+ wire [2:0] data_copy_spi_bytes_to_send;
+ wire [14:0] data_copy_spi_bytes_to_receive;
+ wire data_copy_finished_operating;
+
+ spi_sram_copy data_copy(clock_50mhz, reset, data_copy_sram_io_available,
+ data_copy_write_data, data_copy_wants_sram_io,
+ data_copy_sram_io_addr, memory_base,
+ data_copy_wants_spi_operation,
+ data_copy_spi_send_data, data_copy_spi_bytes_to_send,
+ data_copy_spi_bytes_to_receive, spi_byte_ready,
+ spi_received_data, flash_base,
+ chip_powerup_finished_operating,
+ data_copy_finished_operating);
+
+ assign {
+ spi_operation_wanted,
+ spi_send_data,
+ spi_bytes_to_send,
+ spi_bytes_to_receive
+ }
+ = !chip_powerup_finished_operating ?
+ {
+ chip_powerup_wants_operation,
+ chip_powerup_send_data,
+ chip_powerup_bytes_to_send,
+ chip_powerup_bytes_to_receive
+ } :
+ !data_copy_finished_operating ?
+ {
+ data_copy_wants_spi_operation,
+ data_copy_spi_send_data,
+ data_copy_spi_bytes_to_send,
+ data_copy_spi_bytes_to_receive
+ } :
+ {1'b0, 32'hXXXXXXXX, 3'hX, 15'hXXXX};
wire butwrite_io_available;
- assign butwrite_io_available = dumbwrite_io_available && !dumbwrite_wants_io;
+ assign butwrite_io_available = data_copy_sram_io_available
+ && !data_copy_wants_sram_io;
wire butwrite_wants_io;
wire [17:0] butwrite_io_addr;
@@ -805,12 +1186,12 @@ module top(input wire clock_100mhz,
sram_cs_n <= 1'b0;
sram_addr <= vga_io_addr;
end
- else if (dumbwrite_wants_io) begin
+ else if (data_copy_wants_sram_io) begin
write_in_progress <= 1;
sram_oe_n <= 1'b1;
sram_cs_n <= 1'b0;
- sram_addr <= dumbwrite_io_addr;
- write_data <= dumbwrite_write_data;
+ sram_addr <= data_copy_sram_io_addr;
+ write_data <= data_copy_write_data;
end
else if (butwrite_wants_io) begin
write_in_progress <= 1;
@@ -842,9 +1223,4 @@ module top(input wire clock_100mhz,
end
assign sram_io = sram_we_n ? 16'bzzzzzzzzzzzzzzzz : write_data;
-
- assign sdo = sdi;
- assign sck = 1;
- assign ss_n = 1;
-
endmodule // top