From 7ebfec600044d050477b650abc775a81f5d037d8 Mon Sep 17 00:00:00 2001 From: Julian Blake Kongslie Date: Wed, 16 Feb 2022 14:25:06 -0800 Subject: Complete rewrite to break out the separate state machines and fix timing --- hdl/top.sv | 687 ++++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 518 insertions(+), 169 deletions(-) (limited to 'hdl/top.sv') diff --git a/hdl/top.sv b/hdl/top.sv index babdc95..fee1b68 100644 --- a/hdl/top.sv +++ b/hdl/top.sv @@ -1,193 +1,542 @@ -module top +module command_parser ( input bit clock , input bit resetn - , output bit ramresetn - , output bit [1:0] ramcsn - , output bit ramclkp - , output bit ramclkn - , input bit ramrwds - , inout bit [7:0] ramdata - ); + , output bit uart_ready + , input bit uart_valid + , input bit [7:0] uart_data -assign ramresetn = resetn; -assign ramclkn = !ramclkp; - -bit ram_data_oe; -bit [7:0] ram_send_data; - -assign ramdata = ram_data_oe ? ram_send_data : 8'bZ; - -bit rx_ready; -bit rx_valid; -bit [7:0] rx_data; - -bit tx_ready; -bit tx_valid; -bit [7:0] tx_data; - -alt_jtag_atlantic - #( .INSTANCE_ID(0) - , .LOG2_RXFIFO_DEPTH(6) - , .LOG2_TXFIFO_DEPTH(6) - , .SLD_AUTO_INSTANCE_INDEX("NO") - ) jtag - ( .clk(clock) - , .rst_n(resetn) - , .r_dat(tx_data) - , .r_val(tx_valid) - , .r_ena(tx_ready) - , .t_dat(rx_data) - , .t_dav(rx_ready) - , .t_ena(rx_valid) + , 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; - -bit [22:0] address; -bit [7:0] data; -bit write; - -bit [47:0] command; - -enum - { UART_READ_ADDRESS_OR_COMMAND - , UART_READ_DATA_1 - , UART_READ_DATA_0 - , RAM_WAIT_READY - , RAM_SEND_COMMAND_5 - , RAM_SEND_COMMAND_4 - , RAM_SEND_COMMAND_3 - , RAM_SEND_COMMAND_2 - , RAM_SEND_COMMAND_1 - , RAM_SEND_COMMAND_0 - , RAM_INIT_WAIT_DATA - , RAM_WAIT_DATA - , RAM_SENDRECV_DATA - , UART_WRITE_DATA_1 - , UART_WRITE_DATA_0 - } state; - -always @(posedge clock) begin - if (!resetn) begin - ramcsn[0] = 1; - ramcsn[1] = 1; - ramclkp = 0; - ram_data_oe = 0; - rx_ready = 0; - tx_valid = 0; - input_byte_valid = 0; - address = 0; - state = state.first; - end else begin - if (tx_ready) tx_valid = 0; - if (rx_valid && !input_byte_valid && !tx_valid) begin - tx_valid = 1; - tx_data = rx_data; - input_byte_valid = 1; - input_byte = rx_data; - end - case (state) - UART_READ_ADDRESS_OR_COMMAND: - if (input_byte_valid) begin - if (input_byte >= "0" && input_byte <= "9") begin - address = address << 4; - address[3:0] = input_byte - "0"; - end else if (input_byte >= "a" && input_byte <= "f") begin - address = address << 4; - address[3:0] = input_byte - "a" + 10; - end else if (input_byte >= "A" && input_byte <= "F") begin - address = address << 4; - address[3:0] = input_byte - "A" + 10; - end else if (input_byte == "?") begin - write = 0; - command = {12'b100000000000, address[22:3], 13'b0, address[2:0]}; - address = 0; - data = 0; - state = RAM_SEND_COMMAND_5; - end else if (input_byte == "=") begin - write = 1; - command = {12'b000000000000, address[22:3], 13'b0, address[2:0]}; - address = 0; - data = 0; - state = UART_READ_DATA_1; - end - input_byte_valid = 0; + 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 - UART_READ_DATA_1, UART_READ_DATA_0: - if (input_byte_valid) begin - if (input_byte >= "0" && input_byte <= "9") begin - data = data << 4; - data[3:0] = input_byte - "0"; - state = state.next; - end else if (input_byte >= "a" && input_byte <= "f") begin - data = data << 4; - data[3:0] = input_byte - "a" + 10; - state = state.next; - end else if (input_byte >= "A" && input_byte <= "F") begin - data = data << 4; - data[3:0] = input_byte - "A" + 10; - state = state.next; + + 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 - RAM_WAIT_READY: - begin - ramcsn[0] = 0; - if (ramrwds) state = state.next; + + 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 - RAM_SEND_COMMAND_5, RAM_SEND_COMMAND_4, RAM_SEND_COMMAND_3, RAM_SEND_COMMAND_2, RAM_SEND_COMMAND_1, RAM_SEND_COMMAND_0: - begin - ramclkp = ~ramclkp; - ram_data_oe = 1; - ram_send_data = command[47:40]; - command = command << 8; - state = state.next; + if (in1_ready && in1_valid) begin + in1_hold_valid = 1; + in1_hold = in1_data; end - RAM_INIT_WAIT_DATA: - begin - ramclkp = ~ramclkp; - ram_data_oe = 0; - state = state.next; + + 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 - RAM_WAIT_DATA: - begin - ramclkp = ~ramclkp; - if (ramrwds) begin + + 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_send_data = data; + 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 - state = state.next; end + endcase end - RAM_SENDRECV_DATA: - begin - ramclkp = ~ramclkp; - ramcsn[0] = 1; - ram_data_oe = 0; - if (write) begin - state = state.first; - end else begin - data = ramdata; - state = UART_WRITE_DATA_1; - 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 - UART_WRITE_DATA_1, UART_WRITE_DATA_0: - if (!tx_valid) begin - tx_valid = 1; - if (data[7:4] < 10) begin - tx_data = data[7:4] + "0"; - end else begin - tx_data = data[7:4] + "A" - 10; - end - data = data << 4; + + 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 - endcase - rx_ready = !input_byte_valid && !tx_valid; + + result_ready = !hold_valid; + end end -end + +endmodule + +module top + ( input bit clock + , input bit resetn + + , output bit ram_resetn + , output bit [1:0] ram_csn + , output bit ram_clkp + , output bit ram_clkn + , inout bit ram_rwds + , inout bit [7:0] ram_data + ); + + bit rx_ready; + bit rx_valid; + bit [7:0] rx_data; + + bit tx_ready; + bit tx_valid; + bit [7:0] tx_data; + + alt_jtag_atlantic + #( .INSTANCE_ID(0) + , .LOG2_RXFIFO_DEPTH(6) + , .LOG2_TXFIFO_DEPTH(6) + , .SLD_AUTO_INSTANCE_INDEX("NO") + ) jtag + ( .clk(clock) + , .rst_n(resetn) + + , .r_dat(tx_data) + , .r_val(tx_valid) + , .r_ena(tx_ready) + + , .t_dat(rx_data) + , .t_dav(rx_ready) + , .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) + + , .in0_ready(echo_in0_ready) + , .in0_valid(echo_in0_valid) + , .in0_data(echo_in0_data) + + , .in1_ready(echo_in1_ready) + , .in1_valid(echo_in1_valid) + , .in1_data(echo_in1_data) + + , .out_ready(tx_ready) + , .out_valid(tx_valid) + , .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) + + , .uart_ready(rx_ready) + , .uart_valid(rx_valid) + , .uart_data(rx_data) + + , .echo_ready(echo_in0_ready) + , .echo_valid(echo_in0_valid) + , .echo_data(echo_in0_data) + + , .command_ready(command_ready) + , .command_valid(command_valid) + , .command_address(command_address) + , .command_write(command_write) + , .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) + + , .command_ready(command_ready) + , .command_valid(command_valid) + , .command_address(command_address) + , .command_write(command_write) + , .command_data(command_data) + + , .result_ready(result_ready) + , .result_valid(result_valid) + , .result_data(result_data) + + , .ram_resetn(ram_resetn) + , .ram_csn(ram_csn) + , .ram_clkp(ram_clkp) + , .ram_clkn(ram_clkn) + , .ram_rwds_oe(ram_rwds_oe) + , .ram_rwds_in(ram_rwds) + , .ram_rwds_out(ram_rwds_out) + , .ram_data_oe(ram_data_oe) + , .ram_data_in(ram_data) + , .ram_data_out(ram_data_out) + ); + + result_printer print + ( .clock(clock) + , .resetn(resetn) + + , .result_ready(result_ready) + , .result_valid(result_valid) + , .result_data(result_data) + + , .echo_ready(echo_in1_ready) + , .echo_valid(echo_in1_valid) + , .echo_data(echo_in1_data) + ); endmodule -- cgit v1.2.3