From 811b7c09e290fe3390441dc599b50992623f6ec4 Mon Sep 17 00:00:00 2001 From: Thierry Moreau Date: Sun, 26 Mar 2017 11:56:19 +0200 Subject: [PATCH 1/5] adding tvm_buffer and fifo testbench --- tests/verilog/test_buffer_fifo.py | 52 +++++++++++++ tests/verilog/test_buffer_fifo.v | 87 ++++++++++++++++++++++ verilog/tvm_buffer.v | 118 ++++++++++++++++++++++++++++++ 3 files changed, 257 insertions(+) create mode 100644 tests/verilog/test_buffer_fifo.py create mode 100644 tests/verilog/test_buffer_fifo.v create mode 100644 verilog/tvm_buffer.v diff --git a/tests/verilog/test_buffer_fifo.py b/tests/verilog/test_buffer_fifo.py new file mode 100644 index 000000000000..8db601446b2e --- /dev/null +++ b/tests/verilog/test_buffer_fifo.py @@ -0,0 +1,52 @@ +import tvm +import numpy as np +from tvm.addon import verilog + +def test_buffer_fifo(): + # Test the tvm_buffer.v module as a fifo + + # Find file will search root/verilog and root/tests/verilog + sess = verilog.session([ + verilog.find_file("test_buffer_fifo.v"), + verilog.find_file("tvm_buffer.v") + ]) + + # Get the handles by their names + rst = sess.main.rst + enq = sess.main.enq + valid = sess.main.read_data_valid + dataIn = sess.main.write_data + dataOut = sess.main.read_data + + # Simulation input data + test_data = np.arange(16).astype('int8') + + # Initial state + rst.put_int(1) + enq.put_int(0) + dataIn.put_int(0) + + # De-assert reset + sess.yield_until_posedge() + rst.put_int(0) + + # Main simulation loop + readIdx = 0 + writeIdx = 0 + while readIdx < len(test_data): + # write logic + if (writeIdx < len(test_data)): + enq.put_int(1) + dataIn.put_int(writeIdx) + writeIdx += 1 + else: + enq.put_int(0) + # read logic + if (valid.get_int()): + assert(dataOut.get_int()==test_data[readIdx]) + readIdx += 1 + sess.yield_until_posedge() + + +if __name__ == "__main__": + test_buffer_fifo() diff --git a/tests/verilog/test_buffer_fifo.v b/tests/verilog/test_buffer_fifo.v new file mode 100644 index 000000000000..60b25f954cae --- /dev/null +++ b/tests/verilog/test_buffer_fifo.v @@ -0,0 +1,87 @@ +module main(); + + // Parameters + parameter PER=10; + + // FIFO parameter: + parameter DATA_WIDTH = 8; + parameter DEPTH = 32; + parameter CNTR_WIDTH = 6; + parameter RD_WINDOW = 1; + parameter RD_ADVANCE = 1; + parameter RD_ADDR_WIDTH = 1; + parameter WR_WINDOW = 1; + parameter WR_ADVANCE = 1; + parameter WR_ADDR_WIDTH = 1; + + // Inputs + reg clk; + reg rst; + + // Module inputs + reg [DATA_WIDTH-1:0] write_data; + // FIFO interface abstraction: + // Connect deq to read_advance and read_ready + // Connect enq to write_advance and write_valid + // Set read_addr and write_addr to 0 + reg deq; + reg enq; + // Indicates that the read data is valid + // After it's come out of the FIFO + reg read_data_valid; + + // Module outputs + wire [DATA_WIDTH-1:0] read_data; + wire read_valid; + wire write_ready; + wire [CNTR_WIDTH-1:0] status_counter; + + // Module instantiation + tvm_buffer #( + .DATA_WIDTH(DATA_WIDTH), + .DEPTH(DEPTH), + .CNTR_WIDTH(CNTR_WIDTH), + .RD_WINDOW(RD_WINDOW), + .RD_ADVANCE(RD_ADVANCE), + .RD_ADDR_WIDTH(RD_ADDR_WIDTH), + .WR_WINDOW(WR_WINDOW), + .WR_ADVANCE(WR_ADVANCE), + .WR_ADDR_WIDTH(WR_ADDR_WIDTH) + ) uut ( + .clk(clk), + .rst(rst), + .read_advance(deq), + .read_addr({RD_ADDR_WIDTH{1'b0}}), + .read_ready(deq), + .read_valid(read_valid), + .read_data(read_data), + .write_advance(enq), + .write_addr({WR_ADDR_WIDTH{1'b0}}), + .write_ready(write_ready), + .write_valid(enq), + .write_data(write_data), + .status_counter(status_counter) + ); + + // clock generation + always begin + #(PER/2) clk =~ clk; + end + + // fifo read logic + always @(posedge clk) begin + if (rst) begin + deq <= 0; + read_data_valid <= 0; + end else + // Dequeue logic + deq <= read_valid; + // Read data valid logic + read_data_valid <= deq; + end + + initial begin + // This will allow tvm session to be called every cycle. + $tvm_session(clk); + end +endmodule diff --git a/verilog/tvm_buffer.v b/verilog/tvm_buffer.v new file mode 100644 index 000000000000..402d09b619a7 --- /dev/null +++ b/verilog/tvm_buffer.v @@ -0,0 +1,118 @@ +// Buffer used to add intermediate data buffering in channels +// +// Data within the read/write window is directly accessible via rd_addr/wr_addr. +// The read_advance/write_advance signals update the read/write data pointers by adding RD_WINDOW/WR_WINDOW. +// The status_counter indicate how many items are currently in the buffer (only registered after an advance signal is asserted). +// The ready/valid signals are used to implement a handshake protocol. +// +// Usage: create and pass instance to additional arguments of $tvm_session. + + +module tvm_buffer #( + parameter DATA_WIDTH = 256, + parameter DEPTH = 1024, + parameter CNTR_WIDTH = 10, // log base 2 of BUFF_DEPTH + parameter RD_WINDOW = 8, // set to 1 for FIFO behavior, or DEPTH for SRAM behavior + parameter RD_ADVANCE = 2, // window advance (set to 1 for FIFO behavior) + parameter RD_ADDR_WIDTH = 3, // log base 2 of RD_WINDOW + parameter WR_WINDOW = 8, // set to 1 for FIFO behavior, or DEPTH for SRAM behavior + parameter WR_ADVANCE = 2, // window advance (set to 1 for FIFO behavior) + parameter WR_ADDR_WIDTH = 3 // log base 2 of WR_WINDOW +) ( + input clk, + input rst, + // Read ports + input read_advance, // Window advance (read pointer) + input [RD_ADDR_WIDTH-1:0] read_addr, // Read address offset + input read_ready, // Read ready (dequeue) + output read_valid, // Read valid (not empty) + output [DATA_WIDTH-1:0] read_data, // Read data port + // Write ports + input write_advance, // Window advance (write pointer) + input [WR_ADDR_WIDTH-1:0] write_addr, // Write address offset + output write_ready, // Write ready (not full) + input write_valid, // Write valid (enqueue) + input [DATA_WIDTH-1:0] write_data, // Write data port + // Other outputs + output [CNTR_WIDTH-1:0] status_counter // Number of elements currently in FIFO +); + + // Outputs that need to be latched + reg read_data; + reg status_counter; + + // Internal registers (read pointer, write pointer) + reg[CNTR_WIDTH-1:0] read_ptr; + reg[CNTR_WIDTH-1:0] write_ptr; + + // RAM instance + reg [DATA_WIDTH-1:0] ram[DEPTH-1:0]; + + // Empty and full logic + assign read_valid = (status_counter>=RD_WINDOW) ? 1'b1 : 1'b0; + assign write_ready = (status_counter<(DEPTH-WR_WINDOW)) ? 1'b1 : 1'b0; + + // Counter logic (only affected by enq and deq) + always @(posedge clk) begin + // Case 1: system reset + if (rst==1'b1) begin + status_counter <= 0; + // Case 2: simultaneous write advance and read advance and deq + end else if ((write_advance && write_ready) && (read_advance && read_valid)) begin + status_counter <= status_counter + (WR_ADVANCE - RD_ADVANCE); + // Case 3: write advance + end else if (write_advance && write_ready) begin + status_counter <= status_counter + WR_ADVANCE; + // Case 4: deq + end else if (read_advance && read_valid) begin + status_counter <= status_counter - RD_ADVANCE; + // Default + end else begin + status_counter <= status_counter; + end + end + + // Output logic + always @(posedge clk) begin + if (rst==1'b1) begin + read_data <= 0; + end else begin + if(read_ready) begin + read_data <= ram[(read_ptr+read_addr)%DEPTH]; + end else begin + read_data <= read_data; + end + end + end + + // RAM writing logic + always @(posedge clk) begin + if(write_valid) begin + ram[((write_ptr+write_addr)%DEPTH)] <= write_data; + end + end + + // Read and write pointer logic + always@(posedge clk) begin + if (rst==1'b1) begin + write_ptr <= 0; + read_ptr <= 0; + end else begin + // Increment write pointer by WR_ADVANCE when asserting write_advance + // When performing a write, no need to update the write pointer + if (write_advance && write_ready) begin + write_ptr <= (write_ptr + WR_ADVANCE) % DEPTH; + end else begin + write_ptr <= write_ptr; + end + // Increment read pointer by RD_ADVANCE when asserting read_advance + // When performing a read, no need to update the read pointer + if(read_advance && read_valid) begin + read_ptr <= (read_ptr + RD_ADVANCE) % DEPTH; + end else begin + read_ptr <= read_ptr; + end + end + end + +endmodule // tvm_buffer From cade42b9b66f9623c22c3f37134db17301198cc5 Mon Sep 17 00:00:00 2001 From: Thierry Moreau Date: Sun, 26 Mar 2017 23:25:22 +0200 Subject: [PATCH 2/5] minor edits --- tests/verilog/test_buffer_fifo.py | 5 +++-- tests/verilog/test_buffer_fifo.v | 24 +++++++++++++----------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/tests/verilog/test_buffer_fifo.py b/tests/verilog/test_buffer_fifo.py index 8db601446b2e..18e0a7f124f5 100644 --- a/tests/verilog/test_buffer_fifo.py +++ b/tests/verilog/test_buffer_fifo.py @@ -14,9 +14,9 @@ def test_buffer_fifo(): # Get the handles by their names rst = sess.main.rst enq = sess.main.enq - valid = sess.main.read_data_valid dataIn = sess.main.write_data dataOut = sess.main.read_data + dataOutValid = sess.main.read_data_valid # Simulation input data test_data = np.arange(16).astype('int8') @@ -42,9 +42,10 @@ def test_buffer_fifo(): else: enq.put_int(0) # read logic - if (valid.get_int()): + if (dataOutValid.get_int()): assert(dataOut.get_int()==test_data[readIdx]) readIdx += 1 + # step sess.yield_until_posedge() diff --git a/tests/verilog/test_buffer_fifo.v b/tests/verilog/test_buffer_fifo.v index 60b25f954cae..a20f77d4b042 100644 --- a/tests/verilog/test_buffer_fifo.v +++ b/tests/verilog/test_buffer_fifo.v @@ -3,10 +3,10 @@ module main(); // Parameters parameter PER=10; - // FIFO parameter: + // FIFO parameters parameter DATA_WIDTH = 8; parameter DEPTH = 32; - parameter CNTR_WIDTH = 6; + parameter CNTR_WIDTH = 6; // floor(log(32)) + 1 parameter RD_WINDOW = 1; parameter RD_ADVANCE = 1; parameter RD_ADDR_WIDTH = 1; @@ -14,7 +14,7 @@ module main(); parameter WR_ADVANCE = 1; parameter WR_ADDR_WIDTH = 1; - // Inputs + // Clock & reset reg clk; reg rst; @@ -26,9 +26,6 @@ module main(); // Set read_addr and write_addr to 0 reg deq; reg enq; - // Indicates that the read data is valid - // After it's come out of the FIFO - reg read_data_valid; // Module outputs wire [DATA_WIDTH-1:0] read_data; @@ -70,13 +67,18 @@ module main(); // fifo read logic always @(posedge clk) begin - if (rst) begin + if (rst) deq <= 0; - read_data_valid <= 0; - end else - // Dequeue logic + else deq <= read_valid; - // Read data valid logic + end + + // read_data_valid logic + reg read_data_valid; + always @(posedge clk) begin + if (rst) + read_data_valid <= 0; + else read_data_valid <= deq; end From 063d986727d3cf1289d20d14694550aafc3c86e8 Mon Sep 17 00:00:00 2001 From: Thierry Moreau Date: Sun, 26 Mar 2017 23:26:36 +0200 Subject: [PATCH 3/5] line buffer test bench --- tests/verilog/test_buffer_linebuff.py | 74 ++++++++++++++ tests/verilog/test_buffer_linebuff.v | 139 ++++++++++++++++++++++++++ 2 files changed, 213 insertions(+) create mode 100644 tests/verilog/test_buffer_linebuff.py create mode 100644 tests/verilog/test_buffer_linebuff.v diff --git a/tests/verilog/test_buffer_linebuff.py b/tests/verilog/test_buffer_linebuff.py new file mode 100644 index 000000000000..c86d568824a1 --- /dev/null +++ b/tests/verilog/test_buffer_linebuff.py @@ -0,0 +1,74 @@ +import tvm +import numpy as np +from tvm.addon import verilog + +def test_buffer_linebuff(): + # Test the tvm_buffer.v module as a line buffer + # Window is 8x8, kernel is 3x3 + window_width = 8 + kernel_width = 3 + + # Find file will search root/verilog and root/tests/verilog + sess = verilog.session([ + verilog.find_file("test_buffer_linebuff.v"), + verilog.find_file("tvm_buffer.v") + ]) + + # Get the handles by their names + rst = sess.main.rst + wrAdvance = sess.main.write_advance + wrValid = sess.main.write_valid + wrReady = sess.main.write_ready + wrData = sess.main.write_data + rdData = sess.main.read_data + rdDataValid = sess.main.read_data_valid + + # Simulation input data + test_data = np.arange(window_width*window_width).astype('int8') + + # Initial state + rst.put_int(1) + wrAdvance.put_int(0) + wrValid.put_int(0) + wrData.put_int(0) + + # De-assert reset + sess.yield_until_posedge() + rst.put_int(0) + + # Leave the following signals set to true + sess.yield_until_posedge() + wrValid.put_int(1) + wrAdvance.put_int(1) + + # Main simulation loop + writeIdx = 0 + readIdx = 0 + while readIdx < (window_width-kernel_width+1)*(window_width-kernel_width+1)*kernel_width*kernel_width: + # write logic + if (writeIdx < window_width*window_width): + if (wrReady.get_int()): + wrData.put_int(test_data[writeIdx]) + writeIdx += 1 + else: + wrAdvance.put_int(0) + wrValid.put_int(0) + + # correctness checks + if (rdDataValid.get_int()): + # Derive convolution window indices + baseIdx = readIdx/(kernel_width*kernel_width) + offsetIdx = readIdx%(kernel_width*kernel_width) + yOffset = offsetIdx/kernel_width + xOffset = offsetIdx%kernel_width + pixIndex = baseIdx + yOffset * window_width + xOffset + assert(rdData.get_int()==test_data[pixIndex]) + # print "{} {}".format(rdData.get_int(), test_data[pixIndex]) + readIdx += 1 + + # step + sess.yield_until_posedge() + + +if __name__ == "__main__": + test_buffer_linebuff() diff --git a/tests/verilog/test_buffer_linebuff.v b/tests/verilog/test_buffer_linebuff.v new file mode 100644 index 000000000000..9aa490a86e59 --- /dev/null +++ b/tests/verilog/test_buffer_linebuff.v @@ -0,0 +1,139 @@ +module main(); + + // Parameters + parameter PER=10; + + // In this example we perform a 3x3 convolution of an 8x8 input image + // Therefore the window size here is (3-1)*8+3 = 19 + parameter IMAGE_WIDTH = 8; + parameter KERNEL_WIDTH = 3; + // Line buffer parameters + parameter DATA_WIDTH = 8; + parameter DEPTH = 20; // (3-1)*8+3+1 + parameter CNTR_WIDTH = 5; // floor(log(20)) + 1 + parameter RD_WINDOW = 19; // (3-1)*8+3 + parameter RD_ADVANCE = 1; + parameter RD_ADDR_WIDTH = 5; // floor(log(19)) + 1 + parameter WR_WINDOW = 1; + parameter WR_ADVANCE = 1; + parameter WR_ADDR_WIDTH = 1; + + // Clock & reset + reg clk; + reg rst; + + // Read port inputs + reg read_advance; + reg [RD_ADDR_WIDTH-1:0] read_addr; + reg read_ready; + // Write port outputs + reg write_advance; + reg [DATA_WIDTH-1:0] write_data; + reg [WR_ADDR_WIDTH-1:0] write_addr; + reg write_valid; + + // Outputs + wire [DATA_WIDTH-1:0] read_data; + wire read_valid; + wire write_ready; + wire [CNTR_WIDTH-1:0] status_counter; + + // Module instantiation + tvm_buffer #( + .DATA_WIDTH(DATA_WIDTH), + .DEPTH(DEPTH), + .CNTR_WIDTH(CNTR_WIDTH), + .RD_WINDOW(RD_WINDOW), + .RD_ADVANCE(RD_ADVANCE), + .RD_ADDR_WIDTH(RD_ADDR_WIDTH), + .WR_WINDOW(WR_WINDOW), + .WR_ADVANCE(WR_ADVANCE), + .WR_ADDR_WIDTH(WR_ADDR_WIDTH) + ) uut ( + .clk(clk), + .rst(rst), + .read_advance(read_advance), + .read_data(read_data), + .read_addr(read_addr), + .read_ready(read_ready), + .read_valid(read_valid), + .write_advance(write_advance), + .write_data(write_data), + .write_addr({WR_ADDR_WIDTH{1'b0}}), + .write_ready(write_ready), + .write_valid(write_valid), + .status_counter(status_counter) + ); + + // clock generation + always begin + #(PER/2) clk =~ clk; + end + // write logic + always @(posedge clk) begin + write_addr <= 0; + if (rst) begin + write_advance <= 0; + write_data <= 8'hFF; + write_valid <= 0; + end else begin + write_advance <= 1; + write_valid <= 1; + if (write_ready) begin + write_data <= write_data+1; + end else begin + write_data <= write_data; + end + end + end + + // read logic + localparam KERNEL_SIZE = KERNEL_WIDTH*KERNEL_WIDTH; + reg [3:0] read_counter; + always @(posedge clk) begin + if (rst) begin + read_counter <= KERNEL_SIZE-1; + read_advance <= 0; + read_addr <= -1; + read_ready <= 0; + end else begin + if (read_valid) begin + read_counter <= (read_counter+1)%KERNEL_SIZE; + read_ready <= 1; + // Only advance at the last inner loop iteration + if (read_counter==KERNEL_SIZE-2) begin + read_advance <= 1; + end else begin + read_advance <= 0; + end + // Read address should describe a loop + if (read_counter==KERNEL_SIZE-1) begin + read_addr <= 0; + end else if (read_counter%KERNEL_WIDTH==KERNEL_WIDTH-1) begin + read_addr <= read_addr+IMAGE_WIDTH-KERNEL_WIDTH+1; + end else begin + read_addr <= read_addr+1; + end + end else begin + read_counter <= read_counter; + read_advance <= 0; + read_addr <= read_addr; + read_ready <= 0; + end + end + end + + // read_data_valid logic + reg read_data_valid; + always @(posedge clk) begin + if (rst) + read_data_valid <= 0; + else + read_data_valid <= read_ready; + end + + initial begin + // This will allow tvm session to be called every cycle. + $tvm_session(clk); + end +endmodule From 37109823c48c0a0ea2f81c035d8e87b0f1a9d2a3 Mon Sep 17 00:00:00 2001 From: Thierry Moreau Date: Mon, 27 Mar 2017 00:29:10 +0200 Subject: [PATCH 4/5] adding double buffer tests for the tvm_buffer --- tests/verilog/test_buffer_doublebuff.py | 73 ++++++++++++++++ tests/verilog/test_buffer_doublebuff.v | 107 ++++++++++++++++++++++++ tests/verilog/test_buffer_linebuff.py | 4 +- tests/verilog/test_buffer_linebuff.v | 18 ---- 4 files changed, 182 insertions(+), 20 deletions(-) create mode 100644 tests/verilog/test_buffer_doublebuff.py create mode 100644 tests/verilog/test_buffer_doublebuff.v diff --git a/tests/verilog/test_buffer_doublebuff.py b/tests/verilog/test_buffer_doublebuff.py new file mode 100644 index 000000000000..8cd70a5545a1 --- /dev/null +++ b/tests/verilog/test_buffer_doublebuff.py @@ -0,0 +1,73 @@ +import tvm +import numpy as np +from tvm.addon import verilog + +def test_buffer_doublebuff(): + # Test the tvm_buffer.v module as a double buffer + # Window size is 16, buffer size is 32 + window_width = 16 + set_size = 8 + + # Find file will search root/verilog and root/tests/verilog + sess = verilog.session([ + verilog.find_file("test_buffer_doublebuff.v"), + verilog.find_file("tvm_buffer.v") + ]) + + # Get the handles by their names + rst = sess.main.rst + wrAdvance = sess.main.write_advance + wrAddr = sess.main.write_addr + wrValid = sess.main.write_valid + wrReady = sess.main.write_ready + wrData = sess.main.write_data + rdData = sess.main.read_data + rdDataValid = sess.main.read_data_valid + + # Simulation input data + test_data = np.arange(window_width*set_size).astype('int8') + + # Initial state + rst.put_int(1) + wrAdvance.put_int(0) + wrAddr.put_int(0) + wrValid.put_int(0) + wrData.put_int(0) + + # De-assert reset + sess.yield_until_posedge() + rst.put_int(0) + + # Leave the following signals set to true + sess.yield_until_posedge() + wrValid.put_int(1) + + # Main simulation loop + writeIdx = 0 + readIdx = 0 + while readIdx < len(test_data): + # write logic + if (writeIdx < len(test_data)): + wrAdvance.put_int(0) + if (wrReady.get_int()): + wrData.put_int(test_data[writeIdx]) + wrAddr.put_int(writeIdx%window_width) + if (writeIdx%window_width==window_width-1): + wrAdvance.put_int(1) + writeIdx += 1 + else: + wrAdvance.put_int(0) + wrValid.put_int(0) + + # correctness checks + if (rdDataValid.get_int()): + assert(rdData.get_int()==test_data[readIdx]) + # print "{} {}".format(rdData.get_int(), test_data[readIdx]) + readIdx += 1 + + # step + sess.yield_until_posedge() + + +if __name__ == "__main__": + test_buffer_doublebuff() diff --git a/tests/verilog/test_buffer_doublebuff.v b/tests/verilog/test_buffer_doublebuff.v new file mode 100644 index 000000000000..f9a7a92d5a5c --- /dev/null +++ b/tests/verilog/test_buffer_doublebuff.v @@ -0,0 +1,107 @@ +module main(); + + // Parameters + parameter PER=10; + + // Double buffer parameters + parameter DATA_WIDTH = 8; + parameter DEPTH = 32; + parameter CNTR_WIDTH = 6; // floor(log(32)) + 1 + parameter RD_WINDOW = 16; + parameter RD_ADVANCE = 16; + parameter RD_ADDR_WIDTH = 5; // floor(log(16)) + 1 + parameter WR_WINDOW = 16; + parameter WR_ADVANCE = 16; + parameter WR_ADDR_WIDTH = 5; // floor(log(16)) + 1 + + // Clock & reset + reg clk; + reg rst; + + // Read port inputs + reg read_advance; + reg [RD_ADDR_WIDTH-1:0] read_addr; + reg read_ready; + // Write port outputs + reg write_advance; + reg [DATA_WIDTH-1:0] write_data; + reg [WR_ADDR_WIDTH-1:0] write_addr; + reg write_valid; + + // Outputs + wire [DATA_WIDTH-1:0] read_data; + wire read_valid; + wire write_ready; + wire [CNTR_WIDTH-1:0] status_counter; + + // Module instantiation + tvm_buffer #( + .DATA_WIDTH(DATA_WIDTH), + .DEPTH(DEPTH), + .CNTR_WIDTH(CNTR_WIDTH), + .RD_WINDOW(RD_WINDOW), + .RD_ADVANCE(RD_ADVANCE), + .RD_ADDR_WIDTH(RD_ADDR_WIDTH), + .WR_WINDOW(WR_WINDOW), + .WR_ADVANCE(WR_ADVANCE), + .WR_ADDR_WIDTH(WR_ADDR_WIDTH) + ) uut ( + .clk(clk), + .rst(rst), + .read_advance(read_advance), + .read_data(read_data), + .read_addr(read_addr), + .read_ready(read_ready), + .read_valid(read_valid), + .write_advance(write_advance), + .write_data(write_data), + .write_addr(write_addr), + .write_ready(write_ready), + .write_valid(write_valid), + .status_counter(status_counter) + ); + + // clock generation + always begin + #(PER/2) clk =~ clk; + end + + // read logic + always @(posedge clk) begin + if (rst) begin + read_advance <= 0; + read_addr <= 0; + read_ready <= 0; + end else begin + if (read_valid) begin + read_ready <= 1; + end else begin + read_ready <= 0; + end + if (read_addr%RD_WINDOW==RD_WINDOW-2) begin + read_advance <= 1; + end else begin + read_advance <= 0; + end + if (read_ready) begin + read_addr <= (read_addr+1) % WR_WINDOW; + end else begin + read_addr <= read_addr % WR_WINDOW; + end + end + end + + // read_data_valid logic + reg read_data_valid; + always @(posedge clk) begin + if (rst) + read_data_valid <= 0; + else + read_data_valid <= read_ready; + end + + initial begin + // This will allow tvm session to be called every cycle. + $tvm_session(clk); + end +endmodule diff --git a/tests/verilog/test_buffer_linebuff.py b/tests/verilog/test_buffer_linebuff.py index c86d568824a1..20a2b6ed0926 100644 --- a/tests/verilog/test_buffer_linebuff.py +++ b/tests/verilog/test_buffer_linebuff.py @@ -38,15 +38,15 @@ def test_buffer_linebuff(): # Leave the following signals set to true sess.yield_until_posedge() - wrValid.put_int(1) wrAdvance.put_int(1) + wrValid.put_int(1) # Main simulation loop writeIdx = 0 readIdx = 0 while readIdx < (window_width-kernel_width+1)*(window_width-kernel_width+1)*kernel_width*kernel_width: # write logic - if (writeIdx < window_width*window_width): + if (writeIdx < len(test_data)): if (wrReady.get_int()): wrData.put_int(test_data[writeIdx]) writeIdx += 1 diff --git a/tests/verilog/test_buffer_linebuff.v b/tests/verilog/test_buffer_linebuff.v index 9aa490a86e59..641947a5ed24 100644 --- a/tests/verilog/test_buffer_linebuff.v +++ b/tests/verilog/test_buffer_linebuff.v @@ -29,7 +29,6 @@ module main(); // Write port outputs reg write_advance; reg [DATA_WIDTH-1:0] write_data; - reg [WR_ADDR_WIDTH-1:0] write_addr; reg write_valid; // Outputs @@ -69,23 +68,6 @@ module main(); always begin #(PER/2) clk =~ clk; end - // write logic - always @(posedge clk) begin - write_addr <= 0; - if (rst) begin - write_advance <= 0; - write_data <= 8'hFF; - write_valid <= 0; - end else begin - write_advance <= 1; - write_valid <= 1; - if (write_ready) begin - write_data <= write_data+1; - end else begin - write_data <= write_data; - end - end - end // read logic localparam KERNEL_SIZE = KERNEL_WIDTH*KERNEL_WIDTH; From 831d7a6771fb80fa4a15bcd26e39e8db251cf8dc Mon Sep 17 00:00:00 2001 From: Thierry Moreau Date: Mon, 27 Mar 2017 00:42:20 +0200 Subject: [PATCH 5/5] making variable consistent with python style --- tests/verilog/test_buffer_doublebuff.py | 58 ++++++++++++------------- tests/verilog/test_buffer_fifo.py | 26 +++++------ tests/verilog/test_buffer_linebuff.py | 52 +++++++++++----------- 3 files changed, 68 insertions(+), 68 deletions(-) diff --git a/tests/verilog/test_buffer_doublebuff.py b/tests/verilog/test_buffer_doublebuff.py index 8cd70a5545a1..e0439d9c984c 100644 --- a/tests/verilog/test_buffer_doublebuff.py +++ b/tests/verilog/test_buffer_doublebuff.py @@ -16,23 +16,23 @@ def test_buffer_doublebuff(): # Get the handles by their names rst = sess.main.rst - wrAdvance = sess.main.write_advance - wrAddr = sess.main.write_addr - wrValid = sess.main.write_valid - wrReady = sess.main.write_ready - wrData = sess.main.write_data - rdData = sess.main.read_data - rdDataValid = sess.main.read_data_valid + write_advance = sess.main.write_advance + write_addr = sess.main.write_addr + write_valid = sess.main.write_valid + write_ready = sess.main.write_ready + write_data = sess.main.write_data + read_data = sess.main.read_data + read_data_valid = sess.main.read_data_valid # Simulation input data test_data = np.arange(window_width*set_size).astype('int8') # Initial state rst.put_int(1) - wrAdvance.put_int(0) - wrAddr.put_int(0) - wrValid.put_int(0) - wrData.put_int(0) + write_advance.put_int(0) + write_addr.put_int(0) + write_valid.put_int(0) + write_data.put_int(0) # De-assert reset sess.yield_until_posedge() @@ -40,30 +40,30 @@ def test_buffer_doublebuff(): # Leave the following signals set to true sess.yield_until_posedge() - wrValid.put_int(1) + write_valid.put_int(1) # Main simulation loop - writeIdx = 0 - readIdx = 0 - while readIdx < len(test_data): + write_idx = 0 + read_idx = 0 + while read_idx < len(test_data): # write logic - if (writeIdx < len(test_data)): - wrAdvance.put_int(0) - if (wrReady.get_int()): - wrData.put_int(test_data[writeIdx]) - wrAddr.put_int(writeIdx%window_width) - if (writeIdx%window_width==window_width-1): - wrAdvance.put_int(1) - writeIdx += 1 + if (write_idx < len(test_data)): + write_advance.put_int(0) + if (write_ready.get_int()): + write_data.put_int(test_data[write_idx]) + write_addr.put_int(write_idx%window_width) + if (write_idx%window_width==window_width-1): + write_advance.put_int(1) + write_idx += 1 else: - wrAdvance.put_int(0) - wrValid.put_int(0) + write_advance.put_int(0) + write_valid.put_int(0) # correctness checks - if (rdDataValid.get_int()): - assert(rdData.get_int()==test_data[readIdx]) - # print "{} {}".format(rdData.get_int(), test_data[readIdx]) - readIdx += 1 + if (read_data_valid.get_int()): + assert(read_data.get_int()==test_data[read_idx]) + # print "{} {}".format(read_data.get_int(), test_data[read_idx]) + read_idx += 1 # step sess.yield_until_posedge() diff --git a/tests/verilog/test_buffer_fifo.py b/tests/verilog/test_buffer_fifo.py index 18e0a7f124f5..3255ceafb0de 100644 --- a/tests/verilog/test_buffer_fifo.py +++ b/tests/verilog/test_buffer_fifo.py @@ -14,9 +14,9 @@ def test_buffer_fifo(): # Get the handles by their names rst = sess.main.rst enq = sess.main.enq - dataIn = sess.main.write_data - dataOut = sess.main.read_data - dataOutValid = sess.main.read_data_valid + write_data = sess.main.write_data + read_data = sess.main.read_data + read_data_valid = sess.main.read_data_valid # Simulation input data test_data = np.arange(16).astype('int8') @@ -24,27 +24,27 @@ def test_buffer_fifo(): # Initial state rst.put_int(1) enq.put_int(0) - dataIn.put_int(0) + write_data.put_int(0) # De-assert reset sess.yield_until_posedge() rst.put_int(0) # Main simulation loop - readIdx = 0 - writeIdx = 0 - while readIdx < len(test_data): + read_idx = 0 + write_idx = 0 + while read_idx < len(test_data): # write logic - if (writeIdx < len(test_data)): + if (write_idx < len(test_data)): enq.put_int(1) - dataIn.put_int(writeIdx) - writeIdx += 1 + write_data.put_int(write_idx) + write_idx += 1 else: enq.put_int(0) # read logic - if (dataOutValid.get_int()): - assert(dataOut.get_int()==test_data[readIdx]) - readIdx += 1 + if (read_data_valid.get_int()): + assert(read_data.get_int()==test_data[read_idx]) + read_idx += 1 # step sess.yield_until_posedge() diff --git a/tests/verilog/test_buffer_linebuff.py b/tests/verilog/test_buffer_linebuff.py index 20a2b6ed0926..da01f3fc0cc1 100644 --- a/tests/verilog/test_buffer_linebuff.py +++ b/tests/verilog/test_buffer_linebuff.py @@ -16,21 +16,21 @@ def test_buffer_linebuff(): # Get the handles by their names rst = sess.main.rst - wrAdvance = sess.main.write_advance - wrValid = sess.main.write_valid - wrReady = sess.main.write_ready - wrData = sess.main.write_data - rdData = sess.main.read_data - rdDataValid = sess.main.read_data_valid + write_advance = sess.main.write_advance + write_valid = sess.main.write_valid + write_ready = sess.main.write_ready + write_data = sess.main.write_data + read_data = sess.main.read_data + read_data_valid = sess.main.read_data_valid # Simulation input data test_data = np.arange(window_width*window_width).astype('int8') # Initial state rst.put_int(1) - wrAdvance.put_int(0) - wrValid.put_int(0) - wrData.put_int(0) + write_advance.put_int(0) + write_valid.put_int(0) + write_data.put_int(0) # De-assert reset sess.yield_until_posedge() @@ -38,33 +38,33 @@ def test_buffer_linebuff(): # Leave the following signals set to true sess.yield_until_posedge() - wrAdvance.put_int(1) - wrValid.put_int(1) + write_advance.put_int(1) + write_valid.put_int(1) # Main simulation loop - writeIdx = 0 - readIdx = 0 - while readIdx < (window_width-kernel_width+1)*(window_width-kernel_width+1)*kernel_width*kernel_width: + write_idx = 0 + read_idx = 0 + while read_idx < (window_width-kernel_width+1)*(window_width-kernel_width+1)*kernel_width*kernel_width: # write logic - if (writeIdx < len(test_data)): - if (wrReady.get_int()): - wrData.put_int(test_data[writeIdx]) - writeIdx += 1 + if (write_idx < len(test_data)): + if (write_ready.get_int()): + write_data.put_int(test_data[write_idx]) + write_idx += 1 else: - wrAdvance.put_int(0) - wrValid.put_int(0) + write_advance.put_int(0) + write_valid.put_int(0) # correctness checks - if (rdDataValid.get_int()): + if (read_data_valid.get_int()): # Derive convolution window indices - baseIdx = readIdx/(kernel_width*kernel_width) - offsetIdx = readIdx%(kernel_width*kernel_width) + baseIdx = read_idx/(kernel_width*kernel_width) + offsetIdx = read_idx%(kernel_width*kernel_width) yOffset = offsetIdx/kernel_width xOffset = offsetIdx%kernel_width pixIndex = baseIdx + yOffset * window_width + xOffset - assert(rdData.get_int()==test_data[pixIndex]) - # print "{} {}".format(rdData.get_int(), test_data[pixIndex]) - readIdx += 1 + assert(read_data.get_int()==test_data[pixIndex]) + # print "{} {}".format(read_data.get_int(), test_data[pixIndex]) + read_idx += 1 # step sess.yield_until_posedge()