Fixed minor issues in ALU.v

Rewrote RAM.v
  RAM should now support read and write
  RAM CKE will be pulled low when no queries to it are being made
  Added bank-independent read/write systems
  Added parameterized per-bank clock-hogging
This commit is contained in:
Gabriel Tofvesson 2018-10-17 02:34:03 +02:00
parent 7ebac10ffc
commit a3f7a48276
4 changed files with 199 additions and 96 deletions

34
ALU.v
View File

@ -31,9 +31,9 @@ reg shift_rotate;
wire [BITS:0] add_out;
wire [BITS-1:0] lshift [0:LOG2_BITS];
wire [LOG2_BITS:0] lshift_overflow;
wire [LOG2_BITS-1:0] lshift_overflow;
wire [BITS-1:0] rshift [0:LOG2_BITS];
wire [LOG2_BITS:0] rshift_underflow;
wire [LOG2_BITS-1:0] rshift_underflow;
assign z = i_z[7:0];
assign o_flags = i_flg;
@ -42,33 +42,13 @@ FastAdder8 fa8(.cin(), .a(a), .b(b), .out(add_out[BITS-1:0]), .cout(add_out[BITS
genvar i;
generate
for(i = 1; i<LOG2_BITS; i = i + 1) begin : shifters
LeftBitShifter #(.bits(BITS), .shiftby(2**(i-1))) lsh(i==1 ? a : lshift[i-1], b[i], shift_rotate, lshift[i], lshift_overflow[i]);
RightBitShifter #(.bits(BITS), .shiftby(2**(i-1))) rsh(i==1 ? a : rshift[i-1], b[i], shift_rotate, rshift[i], rshift_underflow[i]);
for(i = 0; i<LOG2_BITS; i = i + 1) begin : shifters
LeftBitShifter #(.bits(BITS), .shiftby(2**i)) lsh(i==0 ? a : lshift[i-1], b[i], shift_rotate, lshift[i], lshift_overflow[i]);
RightBitShifter #(.bits(BITS), .shiftby(2**i)) rsh(i==0 ? a : rshift[i-1], b[i], shift_rotate, rshift[i], rshift_underflow[i]);
end
endgenerate
integer j;
// Left shift decoder
//LeftBitShifter #(.bits(BITS), .shiftby(1)) (a, b[0], shift_rotate, lshift[0], lshift_overflow[0]);
//LeftBitShifter #(.bits(BITS), .shiftby(2)) (lshift[0], b[1], shift_rotate, lshift[1], lshift_overflow[1]);
//LeftBitShifter #(.bits(BITS), .shiftby(4)) (lshift[1], b[2], shift_rotate, lshift[2], lshift_overflow[2]);
//LeftBitShifter #(.bits(8), .shiftby(8)) (lshift[2], b[3], lshift[3], lshift_overflow[3]);
//LeftBitShifter #(.bits(8), .shiftby(16)) (lshift[3], b[4], lshift[4], lshift_overflow[4]);
//LeftBitShifter #(.bits(8), .shiftby(32)) (lshift[4], b[5], lshift[5], lshift_overflow[5]);
//LeftBitShifter #(.bits(8), .shiftby(64)) (lshift[5], b[6], lshift[6], lshift_overflow[6]);
//LeftBitShifter #(.bits(8), .shiftby(128)) (lshift[6], b[7], lshift[7], lshift_overflow[7]);
// Right shift decoder
//RightBitShifter #(.bits(BITS), .shiftby(1)) (a, b[0], shift_rotate, rshift[0], rshift_underflow[0]);
//RightBitShifter #(.bits(BITS), .shiftby(2)) (rshift[0], b[1], shift_rotate, rshift[1], rshift_underflow[1]);
//RightBitShifter #(.bits(BITS), .shiftby(4)) (rshift[1], b[2], shift_rotate, rshift[2], rshift_underflow[2]);
//RightBitShifter #(.bits(8), .shiftby(8)) (rshift[2], b[3], rshift[3], rshift_underflow[3]);
//RightBitShifter #(.bits(8), .shiftby(16)) (rshift[3], b[4], rshift[4], rshift_underflow[4]);
//RightBitShifter #(.bits(8), .shiftby(32)) (rshift[4], b[5], rshift[5], rshift_underflow[5]);
//RightBitShifter #(.bits(8), .shiftby(64)) (rshift[5], b[6], rshift[6], rshift_underflow[6]);
//RightBitShifter #(.bits(8), .shiftby(128)) (rshift[6], b[7], rshift[7], rshift_underflow[7]);
integer j, k;
always @* begin
case(op & 8'b00011111) // 5-bit instructions: 3 flag bits
@ -163,7 +143,7 @@ always @* begin
i_z <= ~(a ^ b);
i_flg <= 8'b0;
end
// CL_MUL
/*
12: begin

View File

@ -8,9 +8,9 @@ module Callback(
parameter ISIZE;
reg [ISIZE-1:0] counter;
reg [2:0] ctr_trigger = 2'b10;
reg [2:0] ctr_trigger = 2'b00;
assign callback = !counter & ctr_trigger;
assign callback = !counter && ctr_trigger ? 1'b1 : 1'b0;
always @(posedge clk or posedge reset) begin
if(reset) begin

227
RAM.v
View File

@ -1,69 +1,188 @@
/*
* DEVICE INFORMATION:
* HY57V641620FTP-7:
* RAS latency: 2 or 3 cycles
* RCD latency: 2 or 3 cycles
* full address_select available for row selection
* address_select[7:0] available for col selection
*/
module RAM(
input wire clk,
output wire [10:0] RAM_addr, // RAM address buffer
output wire RAM_A10, // RAM address/auto-precharge
output wire [1:0] RAM_bank_sel, // RAM bank selection
inout wire [15:0] RAM_data, // RAM data bus
output wire RAM_clk, // RAM clock signal
output wire RAM_clk_enable, // RAM enable clock
output wire RAM_enable, // RAM chip enable
output wire RAM_strobe_row, // RAM row strobe
output wire RAM_strobe_col, // RAM column strobe
output wire RAM_write_enable, // RAM data bus write enable
input wire read_rq, // Read request (Internal)
input wire write_rq, // Write request (Internal)
input wire [1:0] access_bank, // Which bank to access
output reg [15:0] RAM_state, // State information (Internal)
output wire [3:0] op_trigger // Event trigger wire (per bank)
input wire clk, // Clock signal
output reg [10:0] RAM_addr, // RAM address buffer
output reg RAM_A10, // RAM address/auto-precharge
output reg [1:0] RAM_bank_sel, // RAM bank selection
inout wire [15:0] RAM_data, // RAM data bus
output wire RAM_clk, // RAM clock signal
output wire RAM_clk_enable, // RAM enable clock
output reg RAM_enable, // RAM chip enable
output reg RAM_strobe_row, // RAM row strobe
output reg RAM_strobe_col, // RAM column strobe
output reg RAM_write_enable, // RAM data bus write enable
input wire read_rq, // Read request (Internal)
input wire write_rq, // Write request (Internal)
input wire [1:0] access_bank, // Which bank to access
output wire op_trigger, // Event trigger wire
input wire [11:0] address_select, // Address selection when accessing RAM,
input wire stop_access, // Close a row
output reg [1:0] op_bank // Bank being accessed when op_trigger is pulled high
);
reg [2:0] read_init[0:3]; // Whether or not a read operation has been initiated
reg trigger_low; // If trigger should be pulled low on next clock cycle
parameter CPB = 4; // Specifies in bit length how many cycles a bank burst can allocate for itself before other banks are checked
parameter tRCD = 3 + 1; // Assume RCD latency of 3 cycles
parameter tRAS = 3 + 1; // Assume CAS latency of 3 cycles
genvar k;
reg [CPB-1:0] acc_cycles; // Cycles used on current bank
reg [1:0] acc_bank; // Which bank is allocating read cycles
reg [1:0] acc_close[0:3]; // Requests a close of the current row
reg [3:0] acc_type; // The current access type of the bank (0: READ, 1: WRITE)
reg [3:0] acc_state [0:3]; // Current access state for each bank (0: READY, 1: OPENING, 2: tRCD, 3: READ, 4: STOPPING)
reg [3:0] acc_init_callback; // Pull this high to initiate a callback
reg [1:0] event_trigger; // Event triggers drive op_trigger
wire [3:0] acc_event; // Event update callback wire
wire [2:0] callback_timeout[0:3]; // Callback clock cycle definition
Callback #(.ISIZE(3)) cb0(clk, callback_timeout[0], acc_init_callback[0], acc_event[0]);
Callback #(.ISIZE(3)) cb1(clk, callback_timeout[1], acc_init_callback[1], acc_event[1]);
Callback #(.ISIZE(3)) cb2(clk, callback_timeout[2], acc_init_callback[2], acc_event[2]);
Callback #(.ISIZE(3)) cb3(clk, callback_timeout[3], acc_init_callback[3], acc_event[3]);
// Initialize the ram in an inactive state
initial RAM_enable = 1'b1;
initial RAM_strobe_row = 1'b1;
initial RAM_strobe_col = 1'b1;
initial RAM_write_enable = 1'b1;
initial acc_bank = 1'b1;
assign op_trigger = event_trigger[0] ^ event_trigger[1];
assign RAM_clk = clk;
assign RAM_clk_enable = (acc_state[0] | acc_state[1] | acc_state[2] | acc_state[3]) ? 1'b1 : 1'b0;
genvar n;
generate
for(k = 0; k<4; k = k + 1) begin : trigger_gen
assign op_trigger[k] = read_init[k] == 3'b011;
end
for(n = 0; n < 4; n = n + 1) begin : gen_callback_timing
assign callback_timeout[n] = acc_state[n][1] ? tRAS : tRCD;
end
endgenerate
assign RAM_enable = read_init[0] == 3'b000 && read_init[1] == 3'b000 && read_init[2] == 3'b000 && read_init[3] == 3'b000;
assign RAM_clk_enable = read_init[0] != 3'b000 && read_init[1] != 3'b000 && read_init[2] != 3'b000 && read_init[3] != 3'b000;
assign RAM_clk = clk; // RAM clock tracks processor input clock
integer i;
always @(posedge clk or posedge read_rq) begin
if(read_rq) begin
if(!read_init[access_bank] && !write_rq) begin
read_init[access_bank] <= 3'b001;
end
always @(posedge read_rq or posedge write_rq or posedge acc_event or posedge stop_access or posedge clk) begin
if(read_rq || write_rq) begin
if(acc_state[access_bank] == 4'b0000) begin
RAM_enable <= 1'b0;
RAM_strobe_row <= 1'b0;
RAM_strobe_col <= 1'b1;
RAM_write_enable <= 1'b1;
RAM_bank_sel <= access_bank;
RAM_addr <= {address_select[11], address_select[9:0]};
RAM_A10 <= address_select[10];
acc_type[access_bank] <= read_rq ? 1'b0 : 1'b1;
acc_state[access_bank] <= 4'b0001;
acc_init_callback[access_bank] <= 1'b1;
acc_close[access_bank] <= 1'b0;
end
end
else begin
if(read_init[0]) begin
read_init[0] <= read_init[0] + 3'b001; // Increment read
RAM_state[3:0] <= 4'b0001; // STATE: read
end
if(read_init[1]) begin
read_init[1] <= read_init[1] + 3'b001; // Increment read
RAM_state[7:4] <= 4'b0001; // STATE: read
end
if(read_init[2]) begin
read_init[2] <= read_init[2] + 3'b001; // Increment read
RAM_state[11:8] <= 4'b0001; // STATE: read
end
if(read_init[3]) begin
read_init[3] <= read_init[3] + 3'b001; // Increment read
RAM_state[15:12] <= 4'b0001; // STATE: read
end
else if(stop_access) begin
if(acc_state[access_bank])
acc_close[access_bank] <= 1'b1;
end
else if(clk) begin
for(i = 0; i < 4; i = i + 1)
if(acc_state[i] == 4'b0010)
acc_init_callback[i] <= 1'b1;
if(~(acc_state[0] | acc_state[1] | acc_state[2] | acc_state[3]))
RAM_enable <= 1'b1;
// Bank access management
acc_cycles[acc_bank] <= acc_cycles[acc_bank] + 1'b1;
if(acc_cycles[acc_bank] == {CPB{1'b1}}) begin
// Close banks as needed
if(acc_close[0]) begin
acc_close[0] <= 1'b0;
RAM_bank_sel <= 2'b00;
acc_state[0] <= 4'b0000;
end
else if(acc_close[1]) begin
acc_close[1] <= 1'b0;
RAM_bank_sel <= 2'b01;
acc_state[1] <= 4'b0000;
end
else if(acc_close[2]) begin
acc_close[2] <= 1'b0;
RAM_bank_sel <= 2'b10;
acc_state[2] <= 4'b0000;
end
else if(acc_close[3]) begin
acc_close[3] <= 1'b0;
RAM_bank_sel <= 2'b11;
acc_state[3] <= 4'b0000;
end
// Increment bank tracker
if(~(acc_close[0] | acc_close[1] | acc_close[2] | acc_close[3])) begin
acc_bank <= acc_bank + 1;
acc_cycles <= {CPB{1'b0}};
end
else begin
// Trigger RAM row-close event
RAM_enable <= 1'b0;
RAM_strobe_row <= 1'b1;
RAM_strobe_col <= 1'b1;
RAM_write_enable <= 1'b0;
end
end
else begin
// Access bank
for(i = 0; i < 4; i = i + 1) begin
// Bank_{i} active and not closing and...
// Enough cycles left or when no other bank is active or...
// Bank_{i+1} at cycle limit and next banks inactive or bank is closing or...
// Bank_{i+2} at cycle limit and next bank inactive or bank is closing or...
// Bank_{i+3} at cycle limit or closing
if(!acc_close[i] && acc_state[i] == 4'b0100 && (
(acc_bank == i && (acc_cycles != {CPB{1'b1}} || (acc_state[(i+1)%4] != 4'b0100 && acc_state[(i+2)%4] != 4'b0100 && acc_state[(i+3)%4] != 4'b0100))) ||
(acc_bank == (i+1)%4 && ((acc_close[(i+1)%4] || acc_cycles == {CPB{1'b1}}) && acc_state[(i+2)%4] != 4'b0100 && acc_state[(i+3)%4] != 4'b0100)) ||
(acc_bank == (i+2)%4 && ((acc_close[(i+2)%4] || acc_cycles == {CPB{1'b1}}) && acc_state[(i+3)%4] != 4'b0100)) ||
(acc_bank == (i+3)%4 && (acc_close[(i+3)%4] || acc_cycles == {CPB{1'b1}}))
)) begin
RAM_bank_sel <= i;
RAM_addr <= {2'b0, RAM_addr[7:0]};
RAM_A10 <= 1'b1;
RAM_strobe_row <= 1'b1;
RAM_strobe_col <= 1'b0;
RAM_write_enable <= ~acc_type[i];
op_bank <= i;
event_trigger[0] <= event_trigger[1] ? 1'b0 : 1'b1;
end
end
end
end
else if(acc_event) begin
for(i = 0; i < 4; i = i + 1) begin
if(acc_state[i] == 4'b0001) begin
RAM_bank_sel <= i;
RAM_strobe_row <= 1'b1;
RAM_strobe_col <= 1'b0;
RAM_write_enable <= ~acc_type[i];
RAM_A10 <= 1;
acc_state[i] <= 4'b0010;
acc_init_callback[i] <= 1'b0;
end
else if(acc_state[i] == 4'b0010) begin
acc_init_callback[i] <= 1'b0;
acc_state[i] <= 4'b0100;
end
end
end
end
always @(posedge write_rq) begin
if(!read_init[access_bank] && !read_rq) begin
//TODO: Implement read
end
end
// Reset op_trigger by tracking posedge-driven event_trigger
always @(negedge clk) event_trigger[1] <= event_trigger[0] ? 1'b1 : 1'b0;
endmodule

View File

@ -28,15 +28,17 @@ localparam PLL_SELECT = 1; // 0: 100MHz, 1: 200MHz, 2: 300MHz, 3: 400MHz,
localparam RAM_PLL = 0; // Must be either 0 or 1. DO NOT SET TO ANY OTHER VALUE AS IT MIGHT FRY THE ONBOARD RAM!!!
// ---- REGISTERS ---- //
reg debounce; // Input debouncer
reg db_trap; // Debounce buffer
reg [3:0] seg_buf_numbers [0:3]; // 7-segment binary-number-representation buffer
reg [1:0] stage; // Computational stage
reg [7:0] alu_a; // ALU (core0) input a
reg [7:0] alu_b; // ALU (core0) input b
reg [7:0] alu_op; // ALU (core0) opcode
reg [2:0] gfx_rgb; // VGA color channels
reg [1:0] ram_bank_sel; // Which ram bank to access
reg debounce; // Input debouncer
reg db_trap; // Debounce buffer
reg [3:0] seg_buf_numbers [0:3];// 7-segment binary-number-representation buffer
reg [1:0] stage; // Computational stage
reg [7:0] alu_a; // ALU (core0) input a
reg [7:0] alu_b; // ALU (core0) input b
reg [7:0] alu_op; // ALU (core0) opcode
reg [2:0] gfx_rgb; // VGA color channels
reg [1:0] ram_bank_sel; // Which ram bank to access
reg [11:0] ram_addr; // RAM address selection
reg ram_close; // RAM close-row trigger
// ---- WIRES ---- //
wire [7:0] seg_buf[0:3]; // Encoded segment buffer (8-bit expanded 4-bit number buffer)
@ -48,8 +50,8 @@ wire cb; // Callback/timeout
wire [9:0] vga_coords[0:1]; // Current screen coordinates being drawn to
wire ram_request_read; // Trigger a read operation from main memory
wire ram_request_write; // Trigger a write operation from main memory
wire [3:0] ram_event; // Event trigger from ram when an operation is completed (ex. a read op is ready)
wire [15:0] ram_state; // Main memory event information (0:3; bank0, 4:7; bank1, 8:11; bank2, 12:15; bank3)
wire ram_event; // Event trigger from ram when a r/w operation is ready
wire [1:0] ram_event_bank; // Which bank an event is happening on
// ---- WIRE ASSIGNS ---- //
assign pll[4] = clk;
@ -104,8 +106,10 @@ RAM main_memory(
ram_request_read,
ram_request_write,
ram_bank_sel,
ram_state,
ram_event
ram_event,
ram_addr,
ram_close,
ram_event_bank
);
always @(posedge cb or negedge value) select_out <= cb ? 4'b0000 : 4'b1111;