diff options
author | Sergey Nazaryev <sergey@nazaryev.ru> | 2015-12-25 22:15:47 +0300 |
---|---|---|
committer | Sergey Nazaryev <sergey@nazaryev.ru> | 2015-12-25 22:16:06 +0300 |
commit | eabeba483231b0c6e1fac89c2903169f4e028c9a (patch) | |
tree | ff4f7c6210843bde40b45028675bbe74f04e40bf | |
parent | e4381701562660b0594f09e9ad4d5f5c5ff66fc5 (diff) | |
download | circuit-design-lab234-eabeba483231b0c6e1fac89c2903169f4e028c9a.zip circuit-design-lab234-eabeba483231b0c6e1fac89c2903169f4e028c9a.tar.gz circuit-design-lab234-eabeba483231b0c6e1fac89c2903169f4e028c9a.tar.bz2 |
it now works
-rw-r--r-- | rom_ctrl.v | 225 | ||||
-rw-r--r-- | rom_wb.v | 81 | ||||
-rw-r--r-- | romctrl_testbench.v | 122 | ||||
-rw-r--r-- | romwb_testbench.v | 111 | ||||
-rw-r--r-- | testbench.v | 114 |
5 files changed, 401 insertions, 252 deletions
@@ -8,45 +8,53 @@ module rom_ctrl( input [4:0] adr_i, output reg[31:0] dat_o, - output busy_o + output ack_o ); -wire buf_i_wr, buf_o_wr, buf_i_rd, buf_o_rd; -wire buf_i_empty, buf_o_empty, buf_i_full, buf_o_full; -wire buf_i_rst, buf_o_rst; -wire[31:0] buf_i_data_i, buf_o_data_i, buf_i_data_o, buf_o_data_o; +wire read_buf_wr, write_buf_wr, read_buf_rd, write_buf_rd; +wire read_buf_empty, write_buf_empty, read_buf_full, write_buf_full; +wire read_buf_rst, write_buf_rst; +wire[31:0] read_buf_data_i, write_buf_data_i, read_buf_data_o, write_buf_data_o; -reg[7:0] spi_writer_count; reg spi_writer_wr; -wire spi_writer_tx_need, spi_writer_finish; +wire spi_writer_tx_need; wire[23:0] spi_writer_addr; +wire spi_finish; + //*********************************** // Controller state //*********************************** // Memory for storing state -reg[4:0] state; +reg[4:0] state = IDLE_S; +reg[4:0] next_state; -// Show state of controller for wb -assign busy_o = ( state == IDLE ? 0 : 1 ); +// ACK +assign ack_o = ( state == WAIT_S ? 0 : 1 ); // List of states -localparam IDLE = 4'd0, - WRITING_DATA = 4'd1, - READING_DATA = 4'd2, - WRITING_STATUS = 4'd3, - READING_STATUS = 4'd4, - BULK_ERASE = 4'd5, - ERASING_SECTOR = 4'd6, - QUICK_OPERATION = 4'd7; +localparam IDLE_S = 0, + WAIT_S = 1, + WRITING_DATA_S = 2, + READING_DATA_S = 3, + WRITING_STATUS_S = 4, + READING_STATUS_S = 5, + BULK_ERASING_S = 6, + ERASING_SECTOR_S = 7, + READING_REG_S = 8, + WRITING_REG_S = 9, + POPPING_READ_BUFFER_S = 10, + PUSHING_WRITE_BUFFER_S = 11, + CLEARING_READ_BUFFER_S = 12, + CLEARING_WRITE_BUFFER_S = 13; //*********************************** // Virtual registers //*********************************** // Memory for storing registers -reg[31:0] registers[8:0]; +reg[31:0] registers[31:0]; // List of virtual registers localparam WADDR = 0, @@ -66,29 +74,29 @@ localparam WADDR = 0, //*********************************** // Empty WRITE BUFFER when write to WADDR -assign buf_o_rst = ( wr_i && adr_i == WADDR ); +assign write_buf_rst = ( state == CLEARING_WRITE_BUFFER_S ); // Get data for writing from dat_i -assign buf_o_data_i = dat_i; +assign write_buf_data_i = dat_i; // Write to the WRITE BUFFER when write data to WDATA -assign buf_o_wr = ( wr_i && adr_i == WDATA ); +assign write_buf_wr = ( state == PUSHING_WRITE_BUFFER_S ); // Read data from WRITE BUFFER when write data to SPI controller -assign buf_o_rd = ( state == WRITING_DATA && spi_writer_tx_need ); +assign write_buf_rd = ( state == WRITING_DATA_S && spi_writer_tx_need ); -fifo buf_o( +fifo write_buf( .clk_i(clk_i), - .rst_i(buf_o_rst), + .rst_i(write_buf_rst), - .wr_i(buf_o_wr), - .data_i(buf_o_data_i), + .wr_i(write_buf_wr), + .data_i(write_buf_data_i), - .rd_i(buf_o_rd), - .data_o(buf_o_data_o), + .rd_i(write_buf_rd), + .data_o(write_buf_data_o), - .empty_o(buf_o_empty), - .full_o(buf_o_full) + .empty_o(write_buf_empty), + .full_o(write_buf_full) ); //*********************************** @@ -96,34 +104,29 @@ fifo buf_o( //*********************************** // Empty READ BUFFER when write to RADDR -assign buf_i_rst = ( wr_i && adr_i == RADDR ); +assign read_buf_rst = ( state == CLEARING_READ_BUFFER_S ); // Mark as read top of READ BUFFER when read data from RDATA -assign buf_i_rd = ( rd_i && adr_i == RDATA ); - -// Write to READ BUFFER when read data from SPI controller -//assign buf_i_wr = ( state == READING && spi_writer_tx_need ); -assign buf_i_wr = 1'b0; //FIXME -// Get data for writing from SPI_DATA_I -assign buf_i_data_i = 1'b0; //FIXME +assign read_buf_rd = ( state == POPPING_READ_BUFFER_S ); -fifo buf_i( +fifo read_buf( .clk_i(clk_i), - .rst_i(buf_i_rst), - .rd_i(buf_i_rd), - .wr_i(buf_i_wr), - .empty_o(buf_i_empty), - .full_o(buf_i_full), - .data_i(buf_i_data_i), - .data_o(buf_i_data_o) + .rst_i(read_buf_rst), + .rd_i(read_buf_rd), + .wr_i(read_buf_wr), + .empty_o(read_buf_empty), + .full_o(read_buf_full), + .data_i(read_buf_data_i), + .data_o(read_buf_data_o) ); //*********************************** -// SPI Core +// M25P16 SPI Writer Core //*********************************** -assign spi_writer_tx = buf_o_data_o; +assign spi_writer_tx = write_buf_data_o; assign spi_writer_addr = registers[WADDR][23:0]; + /* spi_writer spi_writer( .clk_i(clk_i), @@ -131,52 +134,114 @@ spi_writer spi_writer( .adr_i(spi_writer_addr), .wr_i(spi_writer_wr), .tx_need(spi_writer_tx_need), - .finish_o(spi_writer_finish) + .finish_o(spi_finish), + + .spi_mosi() + .spi_miso() );*/ -always @(posedge clk_i, posedge rst_i) - if( state == IDLE ) - if( wr_i ) - registers[adr_i] <= dat_i; - else if( rd_i ) - dat_o <= registers[adr_i]; +//*********************************** +// M25P16 SPI Reader Core +//*********************************** + +assign spi_writer_tx = write_buf_data_o; +assign spi_writer_addr = registers[WADDR][23:0]; + +/* +spi_reader spi_reader( + .clk_i(clk_i), + .tx_i(spi_writer_tx), + .adr_i(spi_writer_addr), + .wr_i(spi_writer_wr), + .dat_o(read_buf_wr) + .dat_valid( + .finish_o(spi_finish) + + .spi_mosi() + .spi_miso() +);*/ + +//*********************************** +// Virtual Registers I/O +//*********************************** + +always @( posedge clk_i ) + if( state == READING_REG_S ) + dat_o <= registers[adr_i]; + +always @( posedge clk_i ) + if( state == WRITING_REG_S || + adr_i == RADDR || + adr_i == WADDR ) + registers[adr_i] <= dat_i; -always @(posedge clk_i, posedge rst_i) +//*********************************** +// Rom Controller FSM +//*********************************** + +always @( posedge clk_i, posedge rst_i ) if( rst_i ) - state <= IDLE; + state <= IDLE_S; else state <= next_state; always @* begin next_state = state; - case( state ): - IDLE: + case( state ) + IDLE_S: begin - case(adr_i) - RLEN: - next_state = READING_DATA; - WLEN: - next_state = WRITING_DATA; - SEC_ADDR_ERASE: - next_state = ERASING_SECTOR; - STATUS: - next_state = ( rd_i ? READING_STATUS : WRITING_STATUS ); - default: - next_state = QUICK_OPERATION; - endcase + if( adr_i == RLEN && wr_i ) + next_state = READING_DATA_S; + + else if( adr_i == RADDR && wr_i ) + next_state = CLEARING_READ_BUFFER_S; + + else if( adr_i == RDATA && wr_i ) + next_state = POPPING_READ_BUFFER_S; + + + else if( adr_i == WDATA && wr_i ) + next_state = PUSHING_WRITE_BUFFER_S; + + else if( adr_i == WADDR && wr_i ) + next_state = CLEARING_WRITE_BUFFER_S; + + else if( adr_i == WLEN && wr_i) + next_state = WRITING_DATA_S; + + + else if( wr_i && adr_i == SEC_ADDR_ERASE ) + next_state = ERASING_SECTOR_S; + + else if( wr_i && adr_i == BULK_ERASE ) + next_state = BULK_ERASING_S; + + else if( rd_i && adr_i == STATUS ) + next_state = READING_STATUS_S; + + else if( wr_i && adr_i == STATUS ) + next_state = WRITING_STATUS_S; + + + else if( wr_i ) + next_state = WRITING_REG_S; + + else if( rd_i ) + next_state = READING_REG_S; end - WRITING_DATA: - if( spi_writer_finish ) - next_state = IDLE; + ERASING_SECTOR_S, BULK_ERASING_S, READING_STATUS_S, WRITING_STATUS_S, READING_DATA_S, WRITING_DATA_S: + if( spi_finish ) + next_state = WAIT_S; + + POPPING_READ_BUFFER_S, CLEARING_READ_BUFFER_S, CLEARING_WRITE_BUFFER_S, PUSHING_WRITE_BUFFER_S, READING_REG_S, WRITING_REG_S: + next_state = WAIT_S; - QUICK_OPERATION: - next_state = IDLE; + WAIT_S: + next_state = IDLE_S; - default: - next_state = state; - endcase + endcase end endmodule @@ -3,65 +3,28 @@ module rom_wb ( input wb_clk_i, input wb_rst_i, input [31:0] wb_dat_i, - input [31:0] wb_adr_i, + input [4:0] wb_adr_i, input wb_we_i, input [3:0] wb_sel_i, input wb_cyc_i, input wb_stb_i, - output reg [31:0] wb_dat_o, - output reg wb_ack_o -); - -localparam BUSY = 1, - IDLE = 0; - -reg old_state = 1'b0; -wire new_state; - -wb_conv wb_conv( - .wb_clk_i ( wb_clk_i ), - .wb_rst_i ( wb_rst_i ), - .wb_dat_i ( wb_dat_i ), - .wb_adr_i ( wb_adr_i ), - .wb_we_i ( wb_we_i ), - .wb_sel_i ( wb_sel_i ), - .wb_cyc_i ( wb_cyc_i ), - .wb_stb_i ( wb_stb_i ), - - .wb_dat_o ( wb_dat_o ), - .wb_ack_o ( wb_ack_o ), - - .data_ - .addr_ - .wr_en - .rd_en - .busy - .data_ -); - -spi_conv spi_conv( - .mosi - .miso - .clk - .ss - - .data_ - .addr_ - .wr_en - .rd_en - .busy - .data_ + output [31:0] wb_dat_o, + output wb_ack_o ); +reg ack_d1 = 1'b0; +wire ack_w; +wire[4:0] rom_addr_i; +wire[31:0] rom_dat_i, rom_dat_o; +wire rom_clk_i, rom_read_i, rom_write_i; assign rom_read_i = wb_cyc_i & wb_stb_i & !wb_we_i; assign rom_write_i = wb_cyc_i & wb_stb_i & wb_we_i; assign rom_dat_i = wb_dat_i; -assign rom_dat_o = wb_dat_o; assign rom_addr_i = wb_adr_i; -assign rom_clk_i = wb_adr_i; +assign rom_clk_i = wb_clk_i; rom_ctrl rom_ctrl( .clk_i(rom_clk_i), @@ -75,17 +38,19 @@ rom_ctrl rom_ctrl( .wr_i(rom_write_i), .dat_i(rom_dat_i), - .busy_o(new_state) + .ack_o(ack_w) ); -always @(posedge clk_i) -begin - // если был занят, а стал свободен, значит контроллер завершил операцию и - // нужно дёрнуть один раз ACK_O и положить на следующем такте, чтобы wishbone - // master оповестился о конце операции slave'а - - ack_o <= ( old_state == BUSY && new_state == IDLE ? 1 : 0); - old_state <= new_state; -end - -endmodule +always @(posedge wb_clk_i, posedge wb_rst_i ) + if( wb_rst_i ) + ack_d1 <= 0; + else + ack_d1 <= ack_w; + +// если контроллер был занят, а стал свободен, значит контроллер завершил операцию и +// нужно дёрнуть один раз ACK_O и положить на следующем такте, чтобы wishbone +// master оповестился о конце операции slave'а +assign wb_ack_o = ( ack_d1 ) && ( !ack_w ); +assign wb_dat_o = rom_dat_o; + +endmodule
\ No newline at end of file diff --git a/romctrl_testbench.v b/romctrl_testbench.v new file mode 100644 index 0000000..9c4b1cf --- /dev/null +++ b/romctrl_testbench.v @@ -0,0 +1,122 @@ +`timescale 1ns / 1ps + +//////////////////////////////////////////////////////////////////////////////// +// Company: +// Engineer: +// +// Create Date: 13:56:22 12/25/2015 +// Design Name: rom_ctrl +// Module Name: /home/sn/src/circuit-design-lab234//romctrl-testbench.v +// Project Name: m25p16 +// Target Device: +// Tool versions: +// Description: +// +// Verilog Test Fixture created by ISE for module: rom_ctrl +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: +// +//////////////////////////////////////////////////////////////////////////////// + +module romctrl_testbench; + + // Inputs + reg clk_i; + reg rst_i; + reg rd_i; + reg wr_i; + reg [31:0] dat_i; + reg [4:0] adr_i; + + // Outputs + wire [31:0] dat_o; + wire ack_o; + + // Instantiate the Unit Under Test (UUT) + rom_ctrl uut ( + .clk_i(clk_i), + .rst_i(rst_i), + .rd_i(rd_i), + .wr_i(wr_i), + .dat_i(dat_i), + .adr_i(adr_i), + .dat_o(dat_o), + .ack_o(ack_o) + ); + +initial begin + clk_i = 0; + forever begin + clk_i = !clk_i; + #50; + end +end + +reg [31:0] read_value; +initial begin + rst_i = 0; + + clear(); + + $display("hello world"); + + write( 5'hF, 32'haabbccdd ); + read( 5'hF, read_value ); + + $display("read_value = 0x%h", read_value); + + clear(); + + $finish(); +end + +task write( input [4:0] adr, input [31:0] dat ); +begin + @( posedge clk_i ); + + adr_i <= adr; + dat_i <= dat; + wr_i <= 1; + rd_i <= 0; + + @( posedge clk_i ); + while( ack_o == 1'b1 ) + @( posedge clk_i ); + + wr_i <= 0; + rd_i <= 0; +end +endtask + +task read( input [4:0] adr, output [31:0] dat ); +begin + adr_i <= adr; + wr_i <= 0; + rd_i <= 1; + + @( posedge clk_i ); + while( ack_o == 1'b1 ) + @( posedge clk_i ); + + dat = dat_o; + wr_i <= 0; + rd_i <= 0; +end +endtask + +task clear(); +begin + @( posedge clk_i ); + rd_i <= 0; + wr_i <= 0; + dat_i <= 0; + adr_i <= 0; +end +endtask + +endmodule + diff --git a/romwb_testbench.v b/romwb_testbench.v new file mode 100644 index 0000000..926d449 --- /dev/null +++ b/romwb_testbench.v @@ -0,0 +1,111 @@ +`timescale 1ns / 1ps + +module romwb_testbench; + +reg wb_clk_i; +reg wb_rst_i; +reg [31:0] wb_dat_i; +reg [31:0] wb_adr_i; +reg wb_we_i; +reg [3:0] wb_sel_i; +reg wb_cyc_i; +reg wb_stb_i; + +wire [31:0] wb_dat_o; +wire wb_ack_o; + +rom_wb uut ( + .wb_clk_i(wb_clk_i), + .wb_rst_i(wb_rst_i), + .wb_dat_i(wb_dat_i), + .wb_adr_i(wb_adr_i), + .wb_we_i(wb_we_i), + .wb_sel_i(wb_sel_i), + .wb_cyc_i(wb_cyc_i), + .wb_stb_i(wb_stb_i), + .wb_dat_o(wb_dat_o), + .wb_ack_o(wb_ack_o) +); + +initial begin + wb_clk_i = 0; + forever begin + wb_clk_i = !wb_clk_i; + #50; + end +end + +reg [31:0] read_value; +initial begin + wb_sel_i = 0; + wb_rst_i = 0; + + clear(); + + $display("hello world"); + + write( 5'h4, 32'haabbccdd ); + read( 5'h4, read_value ); + + $display("read_value = 0x%h", read_value); + + clear(); + + $finish(); +end + +task write( input [4:0] adr, input [31:0] dat ); +begin + @( posedge wb_clk_i ); + + wb_adr_i <= adr; // master set ADR to 4 for WRITING to ADR + wb_we_i <= 1; // master set WE_I to 1 for WRITING + wb_stb_i <= 1; // master set STB_O to 1 for indicate of start phase + wb_cyc_i <= 1; // master set CYC_O to 1 for indicate of start cycle + wb_dat_i <= dat; + + @( posedge wb_clk_i ); + while( wb_ack_o == 1'b0 ) + @( posedge wb_clk_i ); + + wb_stb_i <= 1'b0; + wb_cyc_i <= 1'b0; +end +endtask + +task read( input [4:0] adr, output [31:0] dat ); +begin + @( posedge wb_clk_i ); + + wb_adr_i <= adr; // master set ADR to 4 for READING from ADR + wb_we_i <= 0; // master set WE_I to 0 for READING + wb_stb_i <= 1; // master set STB_O to 1 for indicate of start phase + wb_cyc_i <= 1; // master set CYC_O to 1 for indicate of start cycle + + @( posedge wb_clk_i ); + while( wb_ack_o == 1'b0 ) + @( posedge wb_clk_i ); + + dat <= wb_dat_o; + + wb_stb_i <= 1'b0; + wb_cyc_i <= 1'b0; +end +endtask + +task clear(); +begin + @( posedge wb_clk_i ); + + wb_adr_i <= 0; + wb_we_i <= 0; + wb_stb_i <= 0; + wb_cyc_i <= 0; + wb_sel_i = 0; + wb_rst_i = 0; +end +endtask + +endmodule + + diff --git a/testbench.v b/testbench.v deleted file mode 100644 index 5e683a5..0000000 --- a/testbench.v +++ /dev/null @@ -1,114 +0,0 @@ -`timescale 1ns / 1ps - -//////////////////////////////////////////////////////////////////////////////// -// Company: -// Engineer: -// -// Create Date: 03:00:40 12/10/2015 -// Design Name: fifo -// Module Name: C:/Users/M25P16/ff.v -// Project Name: M25P16 -// Target Device: -// Tool versions: -// Description: -// -// Verilog Test Fixture created by ISE for module: fifo -// -// Dependencies: -// -// Revision: -// Revision 0.01 - File Created -// Additional Comments: -// -//////////////////////////////////////////////////////////////////////////////// - -module ff; - - // Inputs - reg clk_i; - reg rst_i; - reg wr_i; - reg [31:0] data_i; - reg rd_i; - - // Outputs - wire full_o; - wire [31:0] data_o; - wire empty_o; - - // Instantiate the Unit Under Test (UUT) - fifo uut ( - .clk_i(clk_i), - .rst_i(rst_i), - .wr_i(wr_i), - .data_i(data_i), - .full_o(full_o), - .rd_i(rd_i), - .data_o(data_o), - .empty_o(empty_o) - ); - - initial - begin - clk_i = 0; - - forever - #5 clk_i = !clk_i; - end - - initial begin - // Initialize Inputs - clk_i = 0; - rst_i = 0; - wr_i = 0; - data_i = 0; - rd_i = 0; - - // Wait 100 ns for global reset to finish - #100; - @(posedge clk_i); - - // Add stimulus here - - wr_i = 1; - data_i = 32'hAABBCCDD; - - @(posedge clk_i); - - wr_i = 1; - data_i = 32'hCCBBCCDD; - - @(posedge clk_i); - - wr_i = 0; - rd_i = 1; - - @(posedge clk_i); - - rd_i = 0; - #100; - - @(posedge clk_i); - rd_i = 1; - - @(posedge clk_i); - rd_i = 0; - @(posedge clk_i); - rd_i = 1; - - @(posedge clk_i); - rd_i = 0; - @(posedge clk_i); - rd_i = 1; - - @(posedge clk_i); - rd_i = 0; - @(posedge clk_i); - rd_i = 1; - - @(posedge clk_i); - rd_i = 0; - end - -endmodule - |