From 5bec0a6c6e4aee1c43a7757ac9818f3b9fdc2b15 Mon Sep 17 00:00:00 2001 From: Julian Blake Kongslie Date: Thu, 17 Feb 2022 08:36:10 -0800 Subject: Reorganize controller state machine and tweak timing slightly. --- hdl/ram_controller.sv | 112 ++++++++++++++++++++++++++++---------------------- 1 file changed, 63 insertions(+), 49 deletions(-) diff --git a/hdl/ram_controller.sv b/hdl/ram_controller.sv index b6e744b..015eef0 100644 --- a/hdl/ram_controller.sv +++ b/hdl/ram_controller.sv @@ -34,27 +34,44 @@ module ram_controller bit slow; enum - { SEND_COMMAND_1 + { CHIP_SELECT + + , 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 + , LAT2_12 + , LAT2_11 + , LAT2_10 + , LAT2_9 + , LAT2_8 + , LAT2_7 + , LAT2_6 + , LAT2_5 + , LAT2_4 + , LAT2_3 + , LAT2_2 + , LAT2_1 + + /* Latency blocks are 6 cycle, but you start counting after the upper + * column address is sent (SEND_COMMAND_4) so we reduce the + * lowest-latency block by one full cycle (two states). + , LAT1_12 + , LAT1_11 + */ + , LAT1_10 + , LAT1_9 + , LAT1_8 + , LAT1_7 + , LAT1_6 + , LAT1_5 + , LAT1_4 + , LAT1_3 + , LAT1_2 + , LAT1_1 , DATA_1 , DATA_2 @@ -104,84 +121,81 @@ module ram_controller ram_csn[1] = 1; ram_clkp = 0; end else begin + automatic bit stall = 0; + ram_clkp = !ram_clkp; case (state) + CHIP_SELECT: begin + ram_clkp = 0; // Overriding clock to guarantee that we're starting the command with the correct clock polarity + ram_csn[address[23]] = 0; + end + 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; + ram_data_out = {!write, 1'b0, 1'b0, 5'b0}; // R/W#, ADDRSPACE, BURST, RESERVED 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; + ram_data_out = {4'b0, address[22:19]}; // RESERVED, ROW 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; + ram_data_out = {address[10:9], address[8:3]}; // ROW, UPPERCOL + // This is the cycle immediately before the latency countdown *really* begins. + // So we capture RWDS now in order to know how many latency blocks are required. + slow = ram_rwds_in; 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; + ram_data_out = {5'b0, address[2:0]}; // RESERVED, LOWERCOL + // If we're not in "slow" mode then skip the LAT2 latency + // block. Note that the state=state.next will still happen + // below, taking us to the first state in the LAT1 block. + if (!slow) state = LAT2_1; 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 + // Nothing happens on any of the LAT_* states except for + // cycling the clock and advancing state. 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 else begin + stall = 1; 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; + if (!stall) begin + state = state.next; + 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 end -- cgit v1.2.3