Skip to content

Instantly share code, notes, and snippets.

@hlian
Created April 28, 2010 19:35
Show Gist options
  • Save hlian/382594 to your computer and use it in GitHub Desktop.
Save hlian/382594 to your computer and use it in GitHub Desktop.
// ------------------------------------------------------------------------
// ELE 206: top_module for PUnC Project
// Author: Dana Hoffman and Hao Lian (based on Arnab Sinha's code)
// Description: A computer!
// ------------------------------------------------------------------------
`timescale 1ns / 1ps
module top_module(reset, sysclk, uclk, ss, en, led);
parameter I_bus_width = 8;
parameter D_bus_width = 8;
parameter PC_width = 8;
parameter RESET=0, FETCH=1, DECODE=2,
CMP=3, OUT1=4, OUT2=5, JMP1=6, JMP2=7,
SHR=8, SHL=9, ADDM1=10, ADDM2=11, ADDM3=12,
NANDM1=13, NANDM2=14, NANDM3=15,
STORE1=16, STORE2=17,
LDI1=18, LDI2=19,
LDM1=20, LDM2=21, LDM3=22,
JNZ1=23, JNZ2=24;
// System stuff, dclk = delayed(uclk).
input sysclk, uclk, reset;
wire dclk;
// Seven-segment digits. Register SS_display taps into
// SS_display_wire.
output [6:0] ss;
output [3:0] en;
output [5:0] led;
reg [I_bus_width-1:0] SS_display;
// Buses.
wire [I_bus_width-1:0] I_bus;
wire [D_bus_width-1:0] D_bus;
// Control wires: instruction box.
wire PC_inc_ctrl, PC_ld_ctrl,
I_mem_ld, I_mem_to_I_bus_ctrl;
wire [I_bus_width-1:0] PC_value; // Taps the value of PC in IBox
// Control wires: execution box.
wire A_ld_ctrl, A_shL_ctrl, A_shR_ctrl,
D_mem_ld_ctrl,
D_mem_to_D_bus_ctrl, A_to_D_bus_ctrl, A_to_I_bus_ctrl,
ALU_mode_ctrl, A_neq_0;
wire [1:0] A_mode_ctrl;
ss_display SD1 (.clock(sysclk), .ssOut(ss), .nIn({PC_value, SS_display}), .enable(en));
delayCounter dc(.sysclk(sysclk), .uclk(uclk), .dclk(dclk));
e_box e(.clk(dclk), .reset(reset),
.I_bus(I_bus), .D_bus(D_bus),
.A_ld_ctrl(A_ld_ctrl), .A_shL_ctrl(A_shL_ctrl), .A_shR_ctrl(A_shR_ctrl),
.D_mem_ld_ctrl(D_mem_ld_ctrl),
.D_mem_to_D_bus_ctrl(D_mem_to_D_bus_ctrl),
.A_to_D_bus_ctrl(A_to_D_bus_ctrl),
.A_to_I_bus_ctrl(A_to_I_bus_ctrl),
.ALU_mode_ctrl(ALU_mode_ctrl), .A_mode_ctrl(A_mode_ctrl), .PC_value(PC_value),
.A_neq_0(A_neq_0));
i_box i(.clk(dclk), .reset(reset),
.PC_inc_ctrl(PC_inc_ctrl), .PC_ld_ctrl(PC_ld_ctrl),
.I_mem_to_I_bus_ctrl(I_mem_to_I_bus_ctrl),
.I_bus(I_bus), .PC_value(PC_value));
reg [4:0] state;
always @(posedge dclk) begin
if (reset) state <= FETCH;
else begin
case (state)
FETCH: state <= DECODE;
DECODE: begin
if (I_bus[7:6] == 2'b10) state <= CMP;
else if (I_bus == 8'h10) state <= OUT1;
else if (I_bus == 8'h20) state <= JMP1;
else if (I_bus == 8'h40) state <= SHR;
else if (I_bus == 8'h50) state <= SHL;
else if (I_bus == 8'hD0) state <= ADDM1;
else if (I_bus == 8'hC0) state <= NANDM1;
else if (I_bus == 8'h00) state <= STORE1;
else if (I_bus == 8'hE0) state <= LDI1;
else if (I_bus == 8'hF0) state <= LDM1;
else if (I_bus == 8'h30) state <= JNZ1;
end
CMP: state <= FETCH;
OUT1: state <= OUT2;
OUT2: state <= FETCH;
JMP1: state <= JMP2;
JMP2: state <= FETCH;
SHR: state <= FETCH;
SHL: state <= FETCH;
ADDM1: state <= ADDM2;
ADDM2: state <= ADDM3;
ADDM3: state <= FETCH;
NANDM1: state <= NANDM2;
NANDM2: state <= NANDM3;
NANDM3: state <= FETCH;
STORE1: state <= STORE2;
STORE2: state <= FETCH;
LDI1: state <= LDI2;
LDI2: state <= FETCH;
LDM1: state <= LDM2;
LDM2: state <= LDM3;
LDM3: state <= FETCH;
JNZ1: state <= JNZ2;
JNZ2: state <= FETCH;
endcase
end
end
assign PC_inc_ctrl = (state == DECODE) ||
(state == CMP) || (state == OUT2) || (state == SHR) || (state == SHL) ||
(state == ADDM3) || (state == NANDM3) || (state == STORE2) || (state == LDI2) ||
(state == LDM3);
assign I_mem_to_I_bus_ctrl = (state == FETCH) || (state == DECODE) ||
(state == ADDM1) || (state == ADDM2) || (state == ADDM3) ||
(state == NANDM1) || (state == NANDM2) || (state == NANDM3) ||
(state == STORE1) || (state == STORE2) ||
(state == LDI1) || (state == LDI2) ||
(state == LDM1) || (state == LDM2) || (state == LDM3) ||
(state == JNZ1) || (state == JNZ2);
assign D_mem_ld_ctrl = (state == STORE1) || (state == STORE2);
assign D_mem_to_D_bus_ctrl =
(state == ADDM1) || (state == ADDM2) || (state == ADDM3) ||
(state == NANDM1) || (state == NANDM2) || (state == NANDM3) ||
(state == LDM1) || (state == LDM2) || (state == LDM3);
assign A_ld_ctrl = (state == CMP)
|| (state == SHR) || (state == SHL) || (state == ADDM3)
|| (state == NANDM3) || (state == LDI2) || (state == LDM3);
assign A_mode_ctrl =
(state == CMP) ? 2'b11:
(state == ADDM3) ? 2'b00:
(state == NANDM3) ? 2'b00:
(state == LDI2) ? 2'b10:
(state == LDM3) ? 2'b01:
0;
assign ALU_mode_ctrl =
(state == ADDM3) ? 0 :
(state == NANDM3) ? 1 : 0;
assign A_to_I_bus_ctrl =
(state == OUT1) || (state == OUT2) ||
(state == JMP1) || (state == JMP2);
assign PC_ld_ctrl = (state == JMP2) ||
(state == JNZ2 && A_neq_0);
assign A_shL_ctrl = (state == SHL);
assign A_shR_ctrl = (state == SHR);
assign D_mem_to_D_bus_ctrl =
(state == ADDM1) || (state == ADDM2) || (state == ADDM3) ||
(state == NANDM1) || (state == NANDM2) || (state == NANDM3) ||
(state == LDM1) || (state == LDM2) || (state == LDM3);
assign A_to_D_bus_ctrl = (state == STORE1) || (state == STORE2);
assign led = state;
always @(posedge dclk) begin
//SS_display <= I_bus;
//SS_display <= D_bus;
// We put SS_display here for easier testing and tapping.
if (state == OUT2) SS_display <= I_bus;
//SS_display <= A_neq_0;
end
endmodule
module e_box(clk, reset,
I_bus, D_bus,
A_ld_ctrl, A_shL_ctrl, A_shR_ctrl,
D_mem_ld_ctrl, D_mem_to_D_bus_ctrl, A_to_D_bus_ctrl, A_to_I_bus_ctrl,
ALU_mode_ctrl, A_mode_ctrl, PC_value,
A_neq_0);
parameter I_bus_width = 8;
parameter D_bus_width = 8;
// System stuff.
input clk, reset;
// Buses.
inout [I_bus_width-1:0] I_bus;
inout [D_bus_width-1:0] D_bus;
output A_neq_0;
// PC tap.
input [I_bus_width-1:0] PC_value;
// Control wires.
input A_ld_ctrl, A_shL_ctrl, A_shR_ctrl;
input D_mem_ld_ctrl;
input D_mem_to_D_bus_ctrl, A_to_D_bus_ctrl, A_to_I_bus_ctrl;
input ALU_mode_ctrl;
input [1:0] A_mode_ctrl;
// Local storage: data memory and accumulator.
reg [D_bus_width-1:0] D_mem[1:0];
reg signed [D_bus_width-1:0] A;
always @(posedge clk) begin
if (reset) begin
D_mem[I_bus] <= 0;
A <= 0;
end
else begin
D_mem[I_bus] <= D_mem_ld_ctrl ? D_bus : D_mem[I_bus];
A <=
A_shL_ctrl ? A << 1 :
A_shR_ctrl ? A >>> 1 :
A_ld_ctrl && (A_mode_ctrl == 2'b00) ?
(ALU_mode_ctrl == 0 ? A + D_bus : ~(A & D_bus)) :
A_ld_ctrl && (A_mode_ctrl == 2'b10) ? I_bus :
A_ld_ctrl && (A_mode_ctrl == 2'b01) ? D_bus :
A_ld_ctrl && (A_mode_ctrl == 2'b11) ? (A[7] == 1) : A;
end
end
// Tri-state buffers.
assign D_bus = D_mem_to_D_bus_ctrl ? D_mem[I_bus] :
A_to_D_bus_ctrl ? A : 8'bz;
assign I_bus = A_to_I_bus_ctrl ? A : 8'bz;
assign A_neq_0 = (A != 0);
endmodule
module i_box(clk, reset, PC_inc_ctrl, PC_ld_ctrl,
I_mem_to_I_bus_ctrl, I_bus, PC_value);
parameter I_bus_width = 8;
parameter PC_width = 8;
// System stuff.
input clk, reset;
// Control wires.
input PC_inc_ctrl, PC_ld_ctrl,
I_mem_to_I_bus_ctrl;
inout [I_bus_width-1:0] I_bus;
output [PC_width-1:0] PC_value;
// Local storage: instruction memory and program counter.
reg [I_bus_width-1:0] I_mem[255:0];
reg [PC_width-1:0] PC;
integer i;
always @(posedge clk) begin
if (reset) begin
PC <= 0;
i = 0; I_mem[i] <= 8'he0; // ldi 32
i = i + 1; I_mem[i] <= 8'h20;
i = i + 1; I_mem[i] <= 8'h00; // store (00)
i = i + 1; I_mem[i] <= 8'h00;
i = i + 1; I_mem[i] <= 8'he0; // ldi 18
i = i + 1; I_mem[i] <= 8'h12;
i = i + 1; I_mem[i] <= 8'h00; // store (01)
i = i + 1; I_mem[i] <= 8'h01;
i = i + 1; I_mem[i] <= 8'h10; // out
i = i + 1; I_mem[i] <= 8'h00;
i = i + 1; I_mem[i] <= 8'hf0; // ldm (00)
i = i + 1; I_mem[i] <= 8'h00;
i = i + 1; I_mem[i] <= 8'h10; // out
i = i + 1; I_mem[i] <= 8'h00;
i = i + 1; I_mem[i] <= 8'he0; // ldi CMP_C_D
i = i + 1; I_mem[i] <= 8'h58;
i = i + 1; I_mem[i] <= 8'h20; // jmp
i = i + 1; I_mem[i] <= 8'h00;
i = 8'h12; I_mem[i] <= 8'hf0; // ldm (01)
i = i + 1; I_mem[i] <= 8'h01;
i = i + 1; I_mem[i] <= 8'hc0; // nandm (01)
i = i + 1; I_mem[i] <= 8'h01;
i = i + 1; I_mem[i] <= 8'h00; // store (08)
i = i + 1; I_mem[i] <= 8'h08;
i = i + 1; I_mem[i] <= 8'he0; // ldi 01
i = i + 1; I_mem[i] <= 8'h01;
i = i + 1; I_mem[i] <= 8'hd0; // addm (08)
i = i + 1; I_mem[i] <= 8'h08;
i = i + 1; I_mem[i] <= 8'hd0; // addm (00)
i = i + 1; I_mem[i] <= 8'h00;
i = i + 1; I_mem[i] <= 8'h00; // store (00)
i = i + 1; I_mem[i] <= 8'h00;
i = i + 1; I_mem[i] <= 8'h10; // out
i = i + 1; I_mem[i] <= 8'h00;
i = i + 1; I_mem[i] <= 8'hf0; // ldm (01)
i = i + 1; I_mem[i] <= 8'h01;
i = i + 1; I_mem[i] <= 8'h10; // out
i = i + 1; I_mem[i] <= 8'h00;
i = i + 1; I_mem[i] <= 8'he0; // ldi cmp_c_d
i = i + 1; I_mem[i] <= 8'h58;
i = i + 1; I_mem[i] <= 8'h20; // jmp
i = i + 1; I_mem[i] <= 8'h00;
i = 8'h30; I_mem[i] <= 8'hf0; // ldm (00)
i = i + 1; I_mem[i] <= 8'h00;
i = i + 1; I_mem[i] <= 8'hc0; // nandm (00)
i = i + 1; I_mem[i] <= 8'h00;
i = i + 1; I_mem[i] <= 8'h00; // store (08)
i = i + 1; I_mem[i] <= 8'h08;
i = i + 1; I_mem[i] <= 8'he0; // ldi 01
i = i + 1; I_mem[i] <= 8'h01;
i = i + 1; I_mem[i] <= 8'hd0; // addm (08)
i = i + 1; I_mem[i] <= 8'h08;
i = i + 1; I_mem[i] <= 8'hd0; // addm (01)
i = i + 1; I_mem[i] <= 8'h01;
i = i + 1; I_mem[i] <= 8'h00; // store (01)
i = i + 1; I_mem[i] <= 8'h01;
i = i + 1; I_mem[i] <= 8'h10; // out
i = i + 1; I_mem[i] <= 8'h00;
i = i + 1; I_mem[i] <= 8'hf0; // ldm (00)
i = i + 1; I_mem[i] <= 8'h00;
i = i + 1; I_mem[i] <= 8'h10; // out
i = i + 1; I_mem[i] <= 8'h00;
i = i + 1; I_mem[i] <= 8'he0; // ldi cmp_c_d
i = i + 1; I_mem[i] <= 8'h58;
i = i + 1; I_mem[i] <= 8'h20; // jmp
i = i + 1; I_mem[i] <= 8'h00;
i = 8'h50; I_mem[i] <= 8'h80; // cmp
i = i + 1; I_mem[i] <= 8'h00;
i = i + 1; I_mem[i] <= 8'h30; // jnz D_minus_C
i = i + 1; I_mem[i] <= 8'h30;
i = i + 1; I_mem[i] <= 8'he0; // ldi C_minus_D
i = i + 1; I_mem[i] <= 8'h12;
i = i + 1; I_mem[i] <= 8'h20; // jmp
i = i + 1; I_mem[i] <= 8'h00;
i = 8'h58; I_mem[i] <= 8'hf0; // ldm (01)
i = i + 1; I_mem[i] <= 8'h01;
i = i + 1; I_mem[i] <= 8'hC0; // nandm (01)
i = i + 1; I_mem[i] <= 8'h01;
i = i + 1; I_mem[i] <= 8'h00; // store (08)
i = i + 1; I_mem[i] <= 8'h08;
i = i + 1; I_mem[i] <= 8'he0; // ldi (01)
i = i + 1; I_mem[i] <= 8'h01;
i = i + 1; I_mem[i] <= 8'hd0; // addm (08)
i = i + 1; I_mem[i] <= 8'h08;
i = i + 1; I_mem[i] <= 8'hd0; // addm (00)
i = i + 1; I_mem[i] <= 8'h00;
i = i + 1; I_mem[i] <= 8'h30; // jnz GCD_NOT_DONE
i = i + 1; I_mem[i] <= 8'h50;
i = i + 1; I_mem[i] <= 8'hf0; // ldm (00)
i = i + 1; I_mem[i] <= 8'h00;
i = i + 1; I_mem[i] <= 8'h10; // out
i = i + 1; I_mem[i] <= 8'h00;
end
else begin
PC <= PC_inc_ctrl ? PC + 1 :
PC_ld_ctrl ? I_bus :
PC;
end
end
// Tap PC.
assign PC_value = PC;
// Tri-state buffer.
assign I_bus = I_mem_to_I_bus_ctrl ? I_mem[PC] : 8'bz;
endmodule
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment