From 92420e248d4449a2aa61e92f05c0867912d48d56 Mon Sep 17 00:00:00 2001 From: Julian Blake Kongslie Date: Wed, 16 Feb 2022 14:44:01 -0800 Subject: Split into multiple files. --- hdl/command_parser.sv | 102 ++++++++++++ hdl/echo_arbiter.sv | 62 +++++++ hdl/ram_controller.sv | 193 +++++++++++++++++++++ hdl/result_printer.sv | 55 ++++++ hdl/top.sv | 454 +++----------------------------------------------- 5 files changed, 438 insertions(+), 428 deletions(-) create mode 100644 hdl/command_parser.sv create mode 100644 hdl/echo_arbiter.sv create mode 100644 hdl/ram_controller.sv create mode 100644 hdl/result_printer.sv diff --git a/hdl/command_parser.sv b/hdl/command_parser.sv new file mode 100644 index 0000000..d6775ad --- /dev/null +++ b/hdl/command_parser.sv @@ -0,0 +1,102 @@ +module command_parser + ( input bit clock + , input bit resetn + + , output bit uart_ready + , input bit uart_valid + , input bit [7:0] uart_data + + , input bit echo_ready + , output bit echo_valid + , output bit [7:0] echo_data + + , input bit command_ready + , output bit command_valid + , output bit [23:0] command_address + , output bit command_write + , output bit [15:0] command_data + ); + + bit input_byte_valid; + bit [7:0] input_byte; + + enum + { READ_ADDRESS_OR_COMMAND + , READ_DATA_1 + , READ_DATA_2 + , READ_DATA_3 + , READ_DATA_4 + } state; + + always @(posedge clock) begin + if (!resetn) begin + uart_ready = 0; + command_valid = 0; + command_address = 0; + command_write = 0; + command_data = 0; + input_byte_valid = 0; + input_byte = 0; + state = state.first; + end else begin + if (echo_ready) echo_valid = 0; + if (command_ready) command_valid = 0; + if (uart_ready && uart_valid) begin + echo_valid = 1; + echo_data = uart_data; + input_byte_valid = 1; + input_byte = uart_data; + end + + if (!command_valid && input_byte_valid) begin + case (state) + + READ_ADDRESS_OR_COMMAND: begin + if (input_byte >= "0" && input_byte <= "9") begin + command_address = command_address << 4; + command_address[3:0] = input_byte - "0"; + end else if (input_byte >= "a" && input_byte <= "f") begin + command_address = command_address << 4; + command_address[3:0] = input_byte - "a" + 10; + end else if (input_byte >= "A" && input_byte <= "F") begin + command_address = command_address << 4; + command_address[3:0] = input_byte - "A" + 10; + end else if (input_byte == "?") begin + command_valid = 1; + command_write = 0; + command_data = 0; + end else if (input_byte == "=") begin + command_write = 1; + command_data = 0; + state = READ_DATA_1; + end + end + + READ_DATA_1, READ_DATA_2, READ_DATA_3, READ_DATA_4: begin + if (input_byte >= "0" && input_byte <= "9") begin + command_data = command_data << 4; + command_data[3:0] = input_byte - "0"; + state = state.next; + end else if (input_byte >= "a" && input_byte <= "f") begin + command_data = command_data << 4; + command_data[3:0] = input_byte - "a" + 10; + state = state.next; + end else if (input_byte >= "A" && input_byte <= "F") begin + command_data = command_data << 4; + command_data[3:0] = input_byte - "A" + 10; + state = state.next; + end else begin + state = state.first; + end + command_valid = state == state.first; + end + + endcase + input_byte_valid = 0; + end + + uart_ready = !echo_valid && !input_byte_valid; + end + end + +endmodule diff --git a/hdl/echo_arbiter.sv b/hdl/echo_arbiter.sv new file mode 100644 index 0000000..b6892b1 --- /dev/null +++ b/hdl/echo_arbiter.sv @@ -0,0 +1,62 @@ +module echo_arbiter + ( input bit clock + , input bit resetn + + , output bit in0_ready + , input bit in0_valid + , input bit [7:0] in0_data + + , output bit in1_ready + , input bit in1_valid + , input bit [7:0] in1_data + + , input bit out_ready + , output bit out_valid + , output bit [7:0] out_data + ); + + bit in0_hold_valid; + bit [7:0] in0_hold; + + bit in1_hold_valid; + bit [7:0] in1_hold; + + always @(posedge clock) begin + if (!resetn) begin + in0_ready = 0; + in1_ready = 0; + out_valid = 0; + out_data = 0; + in0_hold_valid = 0; + in0_hold = 0; + in1_hold_valid = 0; + in1_hold = 0; + end else begin + if (out_ready) out_valid = 0; + if (in0_ready && in0_valid) begin + in0_hold_valid = 1; + in0_hold = in0_data; + end + if (in1_ready && in1_valid) begin + in1_hold_valid = 1; + in1_hold = in1_data; + end + + if (!out_valid) begin + if (in0_hold_valid) begin + out_valid = 1; + out_data = in0_hold; + in0_hold_valid = 0; + end else if (in1_hold_valid) begin + out_valid = 1; + out_data = in1_hold; + in1_hold_valid = 0; + end + end + + in0_ready = !in0_hold_valid; + in1_ready = !in1_hold_valid; + end + end + +endmodule diff --git a/hdl/ram_controller.sv b/hdl/ram_controller.sv new file mode 100644 index 0000000..b6e744b --- /dev/null +++ b/hdl/ram_controller.sv @@ -0,0 +1,193 @@ +module ram_controller + ( input bit clock + , input bit resetn + + , output bit command_ready + , input bit command_valid + , input bit [23:0] command_address + , input bit command_write + , input bit [15:0] command_data + + , input bit result_ready + , output bit result_valid + , output bit [15:0] result_data + + , output bit ram_resetn + , output bit [1:0] ram_csn + , output bit ram_clkp + , output bit ram_clkn + , output bit ram_rwds_oe + , input bit ram_rwds_in + , output bit ram_rwds_out + , output bit ram_data_oe + , input bit [7:0] ram_data_in + , output bit [7:0] ram_data_out + ); + + assign ram_clkn = !ram_clkp; + + bit valid; + bit [23:0] address; + bit write; + bit [15:0] data; + + bit slow; + + enum + { SEND_COMMAND_1 + , SEND_COMMAND_2 + , SEND_COMMAND_3 + , SEND_COMMAND_4 + , SEND_COMMAND_5 + , SEND_COMMAND_6 + + , LAT2_CYC1 + , LAT2_CYC2 + , LAT2_CYC3 + , LAT2_CYC4 + , LAT2_CYC5 + , LAT2_CYC6 + + , LAT1_CYC1 + , LAT1_CYC2 + , LAT1_CYC3 + , LAT1_CYC4 + // Latency blocks are 6 cycle, but they start in the SEND_COMMAND_5 cycle, so block 1 is only 4 real cycles + //, LAT1_CYC5 + //, LAT1_CYC6 + + , DATA_1 + , DATA_2 + } state; + + int reset_counter; + + always @(posedge clock) begin + if (!resetn || reset_counter != 0) begin + command_ready = 0; + result_valid = 0; + result_data = 0; + ram_resetn = 0; + ram_csn[0] = 1; + ram_csn[1] = 1; + ram_clkp = 0; + ram_rwds_oe = 0; + ram_rwds_out = 0; + ram_data_oe = 0; + ram_data_out = 0; + valid = 0; + address = 0; + write = 0; + data = 0; + slow = 0; + state = state.first; + if (!resetn) + reset_counter = 5; // Spec wants >= 100ns of reset + else + reset_counter = reset_counter - 1; + end else begin + ram_resetn = 1; + ram_rwds_oe = 0; + ram_data_oe = 0; + + if (result_ready) result_valid = 0; + if (command_ready && command_valid) begin + valid = 1; + address = command_address; + write = command_write; + data = command_data; + state = state.first; + end + + if (!valid) begin + ram_csn[0] = 1; + ram_csn[1] = 1; + ram_clkp = 0; + end else begin + case (state) + + SEND_COMMAND_1: begin + ram_clkp = 0; + ram_csn[address[23]] = 0; + ram_data_oe = 1; + ram_data_out = {!write, 1'b0, 1'b0, 5'b0}; // R/W# AS BURST RESERVED + state = state.next; + end + + SEND_COMMAND_2: begin + ram_clkp = 1; + ram_data_oe = 1; + ram_data_out = {4'b0, address[22:19]}; // RESERVED ROW + state = state.next; + end + + SEND_COMMAND_3: begin + ram_clkp = 0; + ram_data_oe = 1; + ram_data_out = {address[18:11]}; // ROW + state = state.next; + end + + SEND_COMMAND_4: begin + ram_clkp = 1; + ram_data_oe = 1; + ram_data_out = {address[10:9], address[8:3]}; // ROW UPPERCOL + slow = ram_rwds_in; // Sort of arbitrarily capturing RWDS in the middle of the command string + state = state.next; + end + + SEND_COMMAND_5: begin + ram_clkp = 0; + ram_data_oe = 1; + ram_data_out = {8'b0}; // RESERVED + state = state.next; + end + + SEND_COMMAND_6: begin + ram_clkp = 1; + ram_data_oe = 1; + ram_data_out = {5'b0, address[2:0]}; // RESERVED LOWERCOL + if (slow) + state = LAT2_CYC1; + else + state = LAT1_CYC1; + end + + LAT2_CYC1, LAT2_CYC2, LAT2_CYC3, LAT2_CYC4, LAT2_CYC5, LAT2_CYC6, + LAT1_CYC1, LAT1_CYC2, LAT1_CYC3, LAT1_CYC4: begin + ram_clkp = !ram_clkp; + state = state.next; + end + + DATA_1, DATA_2: begin + ram_clkp = !ram_clkp; + if (write) begin + ram_rwds_oe = 1; + ram_rwds_out = 1; + ram_data_oe = 1; + ram_data_out = data[7:0]; + data = data >> 8; + state = state.next; + end else if (ram_rwds_in) begin + data = data << 8; + data[7:0] = ram_data_in; + state = state.next; + end + end + + endcase + if (state == state.first) begin + valid = 0; + if (!write) begin + // We know that this is safe because we don't accept commands unless we have result bandwidth + result_valid = 1; + result_data = data; + end + end + end + + command_ready = !valid && !result_valid; + end + end + +endmodule diff --git a/hdl/result_printer.sv b/hdl/result_printer.sv new file mode 100644 index 0000000..7bcaf31 --- /dev/null +++ b/hdl/result_printer.sv @@ -0,0 +1,55 @@ +module result_printer + ( input bit clock + , input bit resetn + + , output bit result_ready + , input bit result_valid + , input bit [15:0] result_data + + , input bit echo_ready + , output bit echo_valid + , output bit [7:0] echo_data + ); + + bit hold_valid; + bit [15:0] hold; + + enum + { DIGIT_1 + , DIGIT_2 + , DIGIT_3 + , DIGIT_4 + } state; + + always @(posedge clock) begin + if (!resetn) begin + result_ready = 0; + echo_valid = 0; + echo_data = 0; + hold_valid = 0; + hold = 0; + state = state.first; + end else begin + if (echo_ready) echo_valid = 0; + if (result_ready && result_valid) begin + hold_valid = 1; + hold = result_data; + end + + if (hold_valid && !echo_valid) begin + echo_valid = 1; + echo_data = hold[15:12]; + hold = hold << 4; + if (echo_data < 10) + echo_data = echo_data + "0"; + else + echo_data = echo_data + "A" - 10; + state = state.next; + if (state == state.first) hold_valid = 0; + end + + result_ready = !hold_valid; + end + end + +endmodule diff --git a/hdl/top.sv b/hdl/top.sv index fee1b68..d765beb 100644 --- a/hdl/top.sv +++ b/hdl/top.sv @@ -1,405 +1,3 @@ -module command_parser - ( input bit clock - , input bit resetn - - , output bit uart_ready - , input bit uart_valid - , input bit [7:0] uart_data - - , input bit echo_ready - , output bit echo_valid - , output bit [7:0] echo_data - - , input bit command_ready - , output bit command_valid - , output bit [23:0] command_address - , output bit command_write - , output bit [15:0] command_data - ); - - bit input_byte_valid; - bit [7:0] input_byte; - - enum - { READ_ADDRESS_OR_COMMAND - , READ_DATA_1 - , READ_DATA_2 - , READ_DATA_3 - , READ_DATA_4 - } state; - - always @(posedge clock) begin - if (!resetn) begin - uart_ready = 0; - command_valid = 0; - command_address = 0; - command_write = 0; - command_data = 0; - input_byte_valid = 0; - input_byte = 0; - state = state.first; - end else begin - if (echo_ready) echo_valid = 0; - if (command_ready) command_valid = 0; - if (uart_ready && uart_valid) begin - echo_valid = 1; - echo_data = uart_data; - input_byte_valid = 1; - input_byte = uart_data; - end - - if (!command_valid && input_byte_valid) begin - case (state) - READ_ADDRESS_OR_COMMAND: begin - if (input_byte >= "0" && input_byte <= "9") begin - command_address = command_address << 4; - command_address[3:0] = input_byte - "0"; - end else if (input_byte >= "a" && input_byte <= "f") begin - command_address = command_address << 4; - command_address[3:0] = input_byte - "a" + 10; - end else if (input_byte >= "A" && input_byte <= "F") begin - command_address = command_address << 4; - command_address[3:0] = input_byte - "A" + 10; - end else if (input_byte == "?") begin - command_valid = 1; - command_write = 0; - command_data = 0; - end else if (input_byte == "=") begin - command_write = 1; - command_data = 0; - state = READ_DATA_1; - end - end - READ_DATA_1, READ_DATA_2, READ_DATA_3, READ_DATA_4: begin - if (input_byte >= "0" && input_byte <= "9") begin - command_data = command_data << 4; - command_data[3:0] = input_byte - "0"; - state = state.next; - end else if (input_byte >= "a" && input_byte <= "f") begin - command_data = command_data << 4; - command_data[3:0] = input_byte - "a" + 10; - state = state.next; - end else if (input_byte >= "A" && input_byte <= "F") begin - command_data = command_data << 4; - command_data[3:0] = input_byte - "A" + 10; - state = state.next; - end else begin - state = state.first; - end - command_valid = state == state.first; - end - endcase - input_byte_valid = 0; - end - - uart_ready = !echo_valid && !input_byte_valid; - end - end - -endmodule - -module echo_arbiter - ( input bit clock - , input bit resetn - - , output bit in0_ready - , input bit in0_valid - , input bit [7:0] in0_data - - , output bit in1_ready - , input bit in1_valid - , input bit [7:0] in1_data - - , input bit out_ready - , output bit out_valid - , output bit [7:0] out_data - ); - - bit in0_hold_valid; - bit [7:0] in0_hold; - - bit in1_hold_valid; - bit [7:0] in1_hold; - - always @(posedge clock) begin - if (!resetn) begin - in0_ready = 0; - in1_ready = 0; - out_valid = 0; - out_data = 0; - in0_hold_valid = 0; - in0_hold = 0; - in1_hold_valid = 0; - in1_hold = 0; - end else begin - if (out_ready) out_valid = 0; - if (in0_ready && in0_valid) begin - in0_hold_valid = 1; - in0_hold = in0_data; - end - if (in1_ready && in1_valid) begin - in1_hold_valid = 1; - in1_hold = in1_data; - end - - if (!out_valid) begin - if (in0_hold_valid) begin - out_valid = 1; - out_data = in0_hold; - in0_hold_valid = 0; - end else if (in1_hold_valid) begin - out_valid = 1; - out_data = in1_hold; - in1_hold_valid = 0; - end - end - - in0_ready = !in0_hold_valid; - in1_ready = !in1_hold_valid; - end - end - -endmodule - -module ram_controller - ( input bit clock - , input bit resetn - - , output bit command_ready - , input bit command_valid - , input bit [23:0] command_address - , input bit command_write - , input bit [15:0] command_data - - , input bit result_ready - , output bit result_valid - , output bit [15:0] result_data - - , output bit ram_resetn - , output bit [1:0] ram_csn - , output bit ram_clkp - , output bit ram_clkn - , output bit ram_rwds_oe - , input bit ram_rwds_in - , output bit ram_rwds_out - , output bit ram_data_oe - , input bit [7:0] ram_data_in - , output bit [7:0] ram_data_out - ); - - assign ram_clkn = !ram_clkp; - - bit valid; - bit [23:0] address; - bit write; - bit [15:0] data; - - int reset_counter; - - bit slow; - - enum - { SEND_COMMAND_1 - , SEND_COMMAND_2 - , SEND_COMMAND_3 - , SEND_COMMAND_4 - , SEND_COMMAND_5 - , SEND_COMMAND_6 - - , LAT2_CYC1 - , LAT2_CYC2 - , LAT2_CYC3 - , LAT2_CYC4 - , LAT2_CYC5 - , LAT2_CYC6 - - , LAT1_CYC1 - , LAT1_CYC2 - , LAT1_CYC3 - , LAT1_CYC4 - // Latency blocks are 6 cycle, but they start in the SEND_COMMAND_5 cycle, so block 1 is only 4 real cycles - //, LAT1_CYC5 - //, LAT1_CYC6 - - , DATA_1 - , DATA_2 - } state; - - always @(posedge clock) begin - if (!resetn || reset_counter != 0) begin - command_ready = 0; - result_valid = 0; - result_data = 0; - ram_resetn = 0; - ram_csn[0] = 1; - ram_csn[1] = 1; - ram_clkp = 0; - ram_rwds_oe = 0; - ram_rwds_out = 0; - ram_data_oe = 0; - ram_data_out = 0; - valid = 0; - address = 0; - write = 0; - data = 0; - if (!resetn) - reset_counter = 5; // Spec wants >= 100ns of reset - else - reset_counter = reset_counter - 1; - slow = 0; - state = state.first; - end else begin - ram_resetn = 1; - ram_rwds_oe = 0; - ram_data_oe = 0; - if (result_ready) result_valid = 0; - if (command_ready && command_valid) begin - valid = 1; - address = command_address; - write = command_write; - data = command_data; - state = state.first; - end - - if (!valid) begin - ram_csn[0] = 1; - ram_csn[1] = 1; - ram_clkp = 0; - end else begin - case (state) - SEND_COMMAND_1: begin - ram_clkp = 0; - ram_csn[address[23]] = 0; - ram_data_oe = 1; - ram_data_out = {!write, 1'b0, 1'b0, 5'b0}; // R/W# AS BURST RESERVED - state = state.next; - end - SEND_COMMAND_2: begin - ram_clkp = 1; - ram_data_oe = 1; - ram_data_out = {4'b0, address[22:19]}; // RESERVED ROW - state = state.next; - end - SEND_COMMAND_3: begin - ram_clkp = 0; - ram_data_oe = 1; - ram_data_out = {address[18:11]}; // ROW - state = state.next; - end - SEND_COMMAND_4: begin - ram_clkp = 1; - ram_data_oe = 1; - ram_data_out = {address[10:9], address[8:3]}; // ROW UPPERCOL - slow = ram_rwds_in; // Sort of arbitrarily capturing RWDS in the middle of the command string - state = state.next; - end - SEND_COMMAND_5: begin - ram_clkp = 0; - ram_data_oe = 1; - ram_data_out = {8'b0}; // RESERVED - state = state.next; - end - SEND_COMMAND_6: begin - ram_clkp = 1; - ram_data_oe = 1; - ram_data_out = {5'b0, address[2:0]}; // RESERVED LOWERCOL - if (slow) - state = LAT2_CYC1; - else - state = LAT1_CYC1; - end - LAT2_CYC1, LAT2_CYC2, LAT2_CYC3, LAT2_CYC4, LAT2_CYC5, LAT2_CYC6, - LAT1_CYC1, LAT1_CYC2, LAT1_CYC3, LAT1_CYC4: begin - ram_clkp = !ram_clkp; - state = state.next; - end - DATA_1, DATA_2: begin - ram_clkp = !ram_clkp; - if (write) begin - ram_rwds_oe = 1; - ram_rwds_out = 1; - ram_data_oe = 1; - ram_data_out = data[7:0]; - data = data >> 8; - state = state.next; - end else if (ram_rwds_in) begin - data = data << 8; - data[7:0] = ram_data_in; - state = state.next; - end - if (state == state.first) begin - valid = 0; - if (!write) begin - result_valid = 1; - result_data = data; - end - end - end - endcase - end - - command_ready = !valid && !result_valid; - end - end - -endmodule - -module result_printer - ( input bit clock - , input bit resetn - - , output bit result_ready - , input bit result_valid - , input bit [15:0] result_data - - , input bit echo_ready - , output bit echo_valid - , output bit [7:0] echo_data - ); - - bit hold_valid; - bit [15:0] hold; - - enum - { DIGIT_1 - , DIGIT_2 - , DIGIT_3 - , DIGIT_4 - } state; - - always @(posedge clock) begin - if (!resetn) begin - result_ready = 0; - echo_valid = 0; - echo_data = 0; - hold_valid = 0; - hold = 0; - state = state.first; - end else begin - if (echo_ready) echo_valid = 0; - if (result_ready && result_valid) begin - hold_valid = 1; - hold = result_data; - end - - if (hold_valid && !echo_valid) begin - echo_valid = 1; - echo_data = hold[15:12]; - hold = hold << 4; - if (echo_data < 10) - echo_data = echo_data + "0"; - else - echo_data = echo_data + "A" - 10; - state = state.next; - if (state == state.first) hold_valid = 0; - end - - result_ready = !hold_valid; - end - end - -endmodule - module top ( input bit clock , input bit resetn @@ -420,6 +18,32 @@ module top bit tx_valid; bit [7:0] tx_data; + bit echo_in0_ready; + bit echo_in0_valid; + bit [7:0] echo_in0_data; + + bit echo_in1_ready; + bit echo_in1_valid; + bit [7:0] echo_in1_data; + + bit command_ready; + bit command_valid; + bit [23:0] command_address; + bit command_write; + bit [15:0] command_data; + + bit result_ready; + bit result_valid; + bit [15:0] result_data; + + bit ram_rwds_oe; + bit ram_rwds_out; + assign ram_rwds = ram_rwds_oe ? ram_rwds_out : 'bZ; + + bit ram_data_oe; + bit [7:0] ram_data_out; + assign ram_data = ram_data_oe ? ram_data_out : 'bZ; + alt_jtag_atlantic #( .INSTANCE_ID(0) , .LOG2_RXFIFO_DEPTH(6) @@ -438,14 +62,6 @@ module top , .t_ena(rx_valid) ); - bit echo_in0_ready; - bit echo_in0_valid; - bit [7:0] echo_in0_data; - - bit echo_in1_ready; - bit echo_in1_valid; - bit [7:0] echo_in1_data; - echo_arbiter arb ( .clock(clock) , .resetn(resetn) @@ -463,12 +79,6 @@ module top , .out_data(tx_data) ); - bit command_ready; - bit command_valid; - bit [23:0] command_address; - bit command_write; - bit [15:0] command_data; - command_parser parser ( .clock(clock) , .resetn(resetn) @@ -488,18 +98,6 @@ module top , .command_data(command_data) ); - bit result_ready; - bit result_valid; - bit [15:0] result_data; - - bit ram_rwds_oe; - bit ram_rwds_out; - assign ram_rwds = ram_rwds_oe ? ram_rwds_out : 'bZ; - - bit ram_data_oe; - bit [7:0] ram_data_out; - assign ram_data = ram_data_oe ? ram_data_out : 'bZ; - ram_controller ram ( .clock(clock) , .resetn(resetn) -- cgit v1.2.3