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/ram_controller.sv | 193 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 hdl/ram_controller.sv (limited to 'hdl/ram_controller.sv') 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 -- cgit v1.2.3