add control unit
This commit is contained in:
parent
1d70a432c9
commit
a6e02f8e2f
10
Makefile
10
Makefile
@ -14,13 +14,17 @@ bericht/graph.pdf: bericht/graph.dot
|
||||
bericht: bericht/graph.pdf
|
||||
latexmk -pdf bericht/bericht.tex;
|
||||
|
||||
fsm: verilog/fsm.vcd
|
||||
gtkwave verilog/fsm.vcd
|
||||
fsm: verilog/heron_fsm.vcd
|
||||
gtkwave verilog/heron_fsm.vcd
|
||||
|
||||
ctrl: verilog/heron_ctrl.vcd
|
||||
gtkwave verilog/heron_ctrl.vcd
|
||||
|
||||
fsm_tb: verilog/heron_fsm.vcd
|
||||
ctrl_tb: verilog/heron_ctrl.vcd
|
||||
|
||||
%.vcd : %.vvp
|
||||
vvp $<
|
||||
|
||||
%.vvp: %_tb.v %.v
|
||||
iverilog -o $@ $^
|
||||
iverilog -o $@ -Iverilog verilog/heron_{fsm,ctrl}.v
|
||||
|
@ -45,14 +45,14 @@
|
||||
| | LD_N_2 |
|
||||
|-----------------------+--------------|
|
||||
|
||||
|-------------------+------------------|
|
||||
| DIN -> BUS_A -> I | NA |
|
||||
|-----------------------+------------------|
|
||||
| ALU_RES -> BUS_A -> I | NA |
|
||||
| | N/A - N/A |
|
||||
| | BC: |
|
||||
| | -> Z = 0: LD_S_1 |
|
||||
| | -> Z = 1: IDLE |
|
||||
| | I_GT_ZERO |
|
||||
|-------------------+------------------|
|
||||
|-----------------------+------------------|
|
||||
|
||||
|-------------------+-----------|
|
||||
| I -> BUS_A -> ADR | DR |
|
||||
@ -113,12 +113,12 @@
|
||||
| | DIV_4 |
|
||||
|---------------------------------+---------------|
|
||||
|
||||
|-------------------------+---------------|
|
||||
| ALU -> BUS_A -> X | N/A |
|
||||
| ALU -> BUS_A -> ALU_A | SUB - C: SET |
|
||||
|---------------------------+---------------|
|
||||
| ALU_RES -> BUS_A -> X | N/A |
|
||||
| ALU_RES -> BUS_A -> ALU_A | SUB - C: SET |
|
||||
| OLD_X -> BUS_B -> ALU_B | OLD_X_LTE_X_2 |
|
||||
| | OLD_X_LTE_X_1 |
|
||||
|-------------------------+---------------|
|
||||
|---------------------------+---------------|
|
||||
|
||||
|---------------------+-----------------|
|
||||
| X -> BUS_A -> OLD_X | N/A |
|
||||
|
@ -1,39 +1,197 @@
|
||||
`include "heron_states.v"
|
||||
|
||||
module heron_ctrl(
|
||||
state,
|
||||
ready,
|
||||
ram_wr_en,
|
||||
ram_rd_en,
|
||||
alu_mode,
|
||||
alu_set_z,
|
||||
alu_set_c,
|
||||
alu_set_s,
|
||||
k0_to_b,
|
||||
k1_to_b,
|
||||
alu_to_b,
|
||||
state, // ?
|
||||
ready, // ?
|
||||
ram_wr_en, // ?
|
||||
ram_rd_en, // ?
|
||||
alu_mode, //
|
||||
alu_set_z, //
|
||||
alu_set_c, //
|
||||
alu_set_s, //
|
||||
k0_to_b, //
|
||||
k1_to_b, //
|
||||
alu_res_to_a, //
|
||||
a_to_adr,
|
||||
a_to_i,
|
||||
a_to_old_x,
|
||||
a_to_s,
|
||||
a_to_x,
|
||||
b_to_adr,
|
||||
din_to_a,
|
||||
div_to_b_shift_1,
|
||||
i_to_a,
|
||||
old_x_to_b,
|
||||
s_to_b,
|
||||
s_to_b_shift_1,
|
||||
x_to_a,
|
||||
x_to_b_shifted);
|
||||
a_to_i, //
|
||||
a_to_old_x, //
|
||||
a_to_s, //
|
||||
a_to_x, //
|
||||
b_to_adr, // ?
|
||||
din_to_a, // ?
|
||||
edb_to_din, // ?
|
||||
a_to_do, // ?
|
||||
div_to_b_shift_1, // ?
|
||||
i_to_a, //
|
||||
old_x_to_b, //
|
||||
s_to_b, //
|
||||
s_to_a_shift_1, //
|
||||
x_to_a, //
|
||||
x_to_b_shifted); // ?
|
||||
|
||||
// readability
|
||||
parameter ON = 1'b1;
|
||||
parameter OFF = 1'b0;
|
||||
parameter MINUS = 1'b1;
|
||||
parameter PLUS = 1'b0;
|
||||
|
||||
input [3:0] state;
|
||||
|
||||
output ready;
|
||||
output ram_wr_en;
|
||||
output ram_rd_en;
|
||||
output rom_rd_en;
|
||||
output alu_mode;
|
||||
output alu_set_z;
|
||||
output alu_set_c;
|
||||
output alu_set_s;
|
||||
output k0_to_b;
|
||||
output k1_to_b;
|
||||
output alu_res_to_a;
|
||||
output a_to_adr;
|
||||
output a_to_i;
|
||||
output a_to_old_x;
|
||||
output a_to_s;
|
||||
output a_to_x;
|
||||
output b_to_adr;
|
||||
output din_to_a;
|
||||
output edb_to_din;
|
||||
output a_to_do;
|
||||
output div_to_b_shift_1;
|
||||
output i_to_a;
|
||||
output old_x_to_b;
|
||||
output s_to_b;
|
||||
output s_to_a_shift_1;
|
||||
output x_to_a;
|
||||
output x_to_b_shifted;
|
||||
|
||||
reg ready;
|
||||
reg ram_wr_en;
|
||||
reg ram_rd_en;
|
||||
reg rom_rd_en;
|
||||
reg alu_mode;
|
||||
reg alu_set_z;
|
||||
reg alu_set_c;
|
||||
reg alu_set_s;
|
||||
reg k0_to_b;
|
||||
reg k1_to_b;
|
||||
reg alu_res_to_a;
|
||||
reg a_to_adr;
|
||||
reg a_to_i;
|
||||
reg a_to_old_x;
|
||||
reg a_to_s;
|
||||
reg a_to_x;
|
||||
reg b_to_adr;
|
||||
reg din_to_a;
|
||||
reg edb_to_din;
|
||||
reg a_to_do;
|
||||
reg div_to_b_shift_1;
|
||||
reg i_to_a;
|
||||
reg old_x_to_b;
|
||||
reg s_to_b;
|
||||
reg s_to_a_shift_1;
|
||||
reg x_to_a;
|
||||
reg x_to_b_shifted;
|
||||
|
||||
always @(state) begin
|
||||
end
|
||||
ready = OFF;
|
||||
ram_wr_en = OFF;
|
||||
ram_rd_en = OFF;
|
||||
alu_mode = PLUS;
|
||||
alu_set_z = OFF;
|
||||
alu_set_c = OFF;
|
||||
alu_set_s = OFF;
|
||||
k0_to_b = OFF;
|
||||
k1_to_b = OFF;
|
||||
alu_res_to_a = OFF;
|
||||
a_to_adr = OFF;
|
||||
a_to_i = OFF;
|
||||
a_to_old_x = OFF;
|
||||
a_to_s = OFF;
|
||||
a_to_x = OFF;
|
||||
b_to_adr = OFF;
|
||||
din_to_a = OFF;
|
||||
edb_to_din = OFF;
|
||||
div_to_b_shift_1 = OFF;
|
||||
i_to_a = OFF;
|
||||
old_x_to_b = OFF;
|
||||
s_to_b = OFF;
|
||||
s_to_a_shift_1 = OFF;
|
||||
x_to_a = OFF;
|
||||
x_to_b_shifted = OFF;
|
||||
|
||||
case (state)
|
||||
`IDLE: begin
|
||||
ready = ON;
|
||||
end
|
||||
`LD_N_1: begin
|
||||
k0_to_b = ON;
|
||||
b_to_adr = ON;
|
||||
edb_to_din = ON;
|
||||
ram_rd_en = ON;
|
||||
end
|
||||
`LD_N_2: begin
|
||||
din_to_a = ON;
|
||||
k0_to_b = ON;
|
||||
alu_mode = MINUS;
|
||||
alu_set_z = ON;
|
||||
end
|
||||
`I_GT_ZERO: begin
|
||||
alu_res_to_a = ON;
|
||||
a_to_i = ON;
|
||||
end
|
||||
`LD_S_1: begin
|
||||
i_to_a = ON;
|
||||
edb_to_din = ON;
|
||||
a_to_adr = ON;
|
||||
ram_rd_en = ON;
|
||||
end
|
||||
`LD_S_2: begin
|
||||
din_to_a = ON;
|
||||
a_to_s = ON;
|
||||
k1_to_b = ON;
|
||||
alu_mode = MINUS;
|
||||
alu_set_s = ON;
|
||||
alu_set_z = ON;
|
||||
end
|
||||
`S_GT_ONE:; // noop
|
||||
`X_1: begin
|
||||
s_to_a_shift_1 = ON;
|
||||
s_to_b = ON;
|
||||
|
||||
a_to_old_x = ON;
|
||||
a_to_x = ON;
|
||||
end
|
||||
`DIV_1: begin
|
||||
x_to_a = ON;
|
||||
s_to_b = ON;
|
||||
end
|
||||
`DIV_2:; // noop
|
||||
`DIV_3:; // noop
|
||||
`DIV_4: begin
|
||||
x_to_a = ON;
|
||||
div_to_b_shift_1 = ON;
|
||||
end
|
||||
`OLD_X_LTE_X_1: begin
|
||||
alu_res_to_a = ON;
|
||||
a_to_x = ON;
|
||||
old_x_to_b = ON;
|
||||
alu_set_c = ON;
|
||||
end
|
||||
`OLD_X_LTE_X_2: begin
|
||||
x_to_a = ON;
|
||||
a_to_old_x = ON;
|
||||
end
|
||||
`STORE_X: begin
|
||||
x_to_b_shifted = ON;
|
||||
a_to_do = ON;
|
||||
ram_wr_en = ON;
|
||||
end
|
||||
`DEC_I: begin
|
||||
i_to_a = ON;
|
||||
k1_to_b = ON;
|
||||
alu_mode = MINUS;
|
||||
alu_set_z = ON;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
endmodule
|
||||
|
25
verilog/heron_ctrl_tb.v
Normal file
25
verilog/heron_ctrl_tb.v
Normal file
@ -0,0 +1,25 @@
|
||||
module heron_fsm_tb;
|
||||
task assert;
|
||||
input condition;
|
||||
input [(20*8 - 1):0] message;
|
||||
begin
|
||||
if (condition !== 1'b1)
|
||||
begin
|
||||
$display("Assertion Failed: %s", message);
|
||||
$finish(2);
|
||||
end
|
||||
end
|
||||
endtask
|
||||
|
||||
reg[3:0] state;
|
||||
|
||||
initial begin
|
||||
$dumpfile("ctrl.vcd");
|
||||
$dumpvars;
|
||||
end
|
||||
|
||||
initial begin
|
||||
$display("Control logic tests passed!");
|
||||
$finish;
|
||||
end
|
||||
end
|
@ -1,22 +1,6 @@
|
||||
module heron_fsm(clk, load, reset, flag_z, flag_c, flag_s, state);
|
||||
// (C) 1953, Frank Gray
|
||||
parameter IDLE = 4'b0000;
|
||||
parameter LD_N_1 = 4'b0001;
|
||||
parameter LD_N_2 = 4'b0011;
|
||||
parameter I_GT_ZERO = 4'b0010;
|
||||
parameter LD_S_1 = 4'b0110;
|
||||
parameter LD_S_2 = 4'b0111;
|
||||
parameter S_GT_ONE = 4'b0101;
|
||||
parameter X_1 = 4'b0100;
|
||||
parameter DIV_1 = 4'b1100;
|
||||
parameter DIV_2 = 4'b1101;
|
||||
parameter DIV_3 = 4'b1111;
|
||||
parameter DIV_4 = 4'b1110;
|
||||
parameter OLD_X_LTE_X_1 = 4'b1010;
|
||||
parameter OLD_X_LTE_X_2 = 4'b1011;
|
||||
parameter STORE_X = 4'b1001;
|
||||
parameter DEC_I = 4'b1000;
|
||||
`include "heron_states.v"
|
||||
|
||||
module heron_fsm(clk, load, reset, flag_z, flag_c, flag_s, state);
|
||||
input clk;
|
||||
input load;
|
||||
input reset;
|
||||
@ -32,49 +16,52 @@ module heron_fsm(clk, load, reset, flag_z, flag_c, flag_s, state);
|
||||
|
||||
always @(posedge clk or posedge reset)
|
||||
if(reset) begin
|
||||
state <= IDLE;
|
||||
state <= `IDLE;
|
||||
end else begin
|
||||
state <= next_state;
|
||||
end
|
||||
|
||||
always @(state or flag_z or load)
|
||||
case(state)
|
||||
IDLE:
|
||||
`IDLE: begin
|
||||
if(load) begin
|
||||
next_state = LD_N_1;
|
||||
next_state = `LD_N_1;
|
||||
end else begin
|
||||
next_state = IDLE;
|
||||
next_state = `IDLE;
|
||||
end
|
||||
LD_N_1: next_state = LD_N_2;
|
||||
LD_N_2: next_state = I_GT_ZERO;
|
||||
I_GT_ZERO:
|
||||
end
|
||||
`LD_N_1: next_state = `LD_N_2;
|
||||
`LD_N_2: next_state = `I_GT_ZERO;
|
||||
`I_GT_ZERO: begin
|
||||
if (flag_z) begin
|
||||
next_state = LD_S_1;
|
||||
next_state = `LD_S_1;
|
||||
end else begin
|
||||
next_state = IDLE;
|
||||
next_state = `IDLE;
|
||||
end
|
||||
LD_S_1: next_state = LD_S_2;
|
||||
LD_S_2: next_state = S_GT_ONE;
|
||||
S_GT_ONE:
|
||||
end
|
||||
`LD_S_1: next_state = `LD_S_2;
|
||||
`LD_S_2: next_state = `S_GT_ONE;
|
||||
`S_GT_ONE: begin
|
||||
if (flag_s || flag_z) begin
|
||||
next_state = STORE_X;
|
||||
next_state = `STORE_X;
|
||||
end else begin
|
||||
next_state = X_1;
|
||||
next_state = `X_1;
|
||||
end
|
||||
X_1: next_state = DIV_2;
|
||||
DIV_1: next_state = DIV_2;
|
||||
DIV_2: next_state = DIV_3;
|
||||
DIV_3: next_state = DIV_4;
|
||||
DIV_4: next_state = OLD_X_LTE_X_1;
|
||||
OLD_X_LTE_X_1: next_state = OLD_X_LTE_X_2;
|
||||
OLD_X_LTE_X_2:
|
||||
end
|
||||
`X_1: next_state = `DIV_2;
|
||||
`DIV_1: next_state = `DIV_2;
|
||||
`DIV_2: next_state = `DIV_3;
|
||||
`DIV_3: next_state = `DIV_4;
|
||||
`DIV_4: next_state = `OLD_X_LTE_X_1;
|
||||
`OLD_X_LTE_X_1: next_state = `OLD_X_LTE_X_2;
|
||||
`OLD_X_LTE_X_2: begin
|
||||
if (flag_c) begin
|
||||
next_state = DIV_1;
|
||||
next_state = `DIV_1;
|
||||
end else begin
|
||||
next_state = STORE_X;
|
||||
next_state = `STORE_X;
|
||||
end
|
||||
STORE_X: next_state = DEC_I;
|
||||
DEC_I: next_state = I_GT_ZERO;
|
||||
end
|
||||
`STORE_X: next_state = `DEC_I;
|
||||
`DEC_I: next_state = `I_GT_ZERO;
|
||||
endcase
|
||||
end
|
||||
endmodule
|
||||
|
@ -1,3 +1,5 @@
|
||||
`include "heron_states.v"
|
||||
|
||||
module heron_fsm_tb;
|
||||
task assert;
|
||||
input condition;
|
||||
@ -50,13 +52,15 @@ module heron_fsm_tb;
|
||||
#(CYCLE)
|
||||
load = 0;
|
||||
|
||||
assert(state == fsm.LD_N_1, "IDLE -> LD_N_1");
|
||||
assert(state == `LD_N_1, "IDLE -> LD_N_1");
|
||||
#(CYCLE)
|
||||
assert(state == fsm.LD_N_2, "LD_N_1 -> LD_N_2");
|
||||
assert(state == `LD_N_2, "LD_N_1 -> LD_N_2");
|
||||
#(CYCLE)
|
||||
assert(state == fsm.I_GT_ZERO, "LD_N_2 -> I_GT_ZERO");
|
||||
assert(state == `I_GT_ZERO, "LD_N_2 -> I_GT_ZERO");
|
||||
#(CYCLE)
|
||||
assert(state == `I_GT_ZERO, "LD_N_2 -> I_GT_ZERO");
|
||||
|
||||
$display("All tests passed!");
|
||||
$display("FSM tests passed!");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
|
17
verilog/heron_states.v
Normal file
17
verilog/heron_states.v
Normal file
@ -0,0 +1,17 @@
|
||||
// (C) 1953, Frank Gray
|
||||
`define IDLE 4'b0000
|
||||
`define LD_N_1 4'b0001
|
||||
`define LD_N_2 4'b0011
|
||||
`define I_GT_ZERO 4'b0010
|
||||
`define LD_S_1 4'b0110
|
||||
`define LD_S_2 4'b0111
|
||||
`define S_GT_ONE 4'b0101
|
||||
`define X_1 4'b0100
|
||||
`define DIV_1 4'b1100
|
||||
`define DIV_2 4'b1101
|
||||
`define DIV_3 4'b1111
|
||||
`define DIV_4 4'b1110
|
||||
`define OLD_X_LTE_X_1 4'b1010
|
||||
`define OLD_X_LTE_X_2 4'b1011
|
||||
`define STORE_X 4'b1001
|
||||
`define DEC_I 4'b1000
|
Loading…
Reference in New Issue
Block a user