diff --git a/Makefile b/Makefile index 7cc7a0a..6e03e1a 100644 --- a/Makefile +++ b/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 diff --git a/bericht/rt_folgen.txt b/bericht/rt_folgen.txt index ea1f14b..99f327a 100644 --- a/bericht/rt_folgen.txt +++ b/bericht/rt_folgen.txt @@ -1,4 +1,4 @@ -# +# #Busse # #- BUS_A (Ad) @@ -45,14 +45,14 @@ | | LD_N_2 | |-----------------------+--------------| -|-------------------+------------------| -| DIN -> BUS_A -> I | NA | -| | N/A - N/A | -| | BC: | -| | -> Z = 0: LD_S_1 | -| | -> Z = 1: IDLE | -| | I_GT_ZERO | -|-------------------+------------------| +|-----------------------+------------------| +| 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 | -| OLD_X -> BUS_B -> ALU_B | OLD_X_LTE_X_2 | -| | OLD_X_LTE_X_1 | -|-------------------------+---------------| +|---------------------------+---------------| +| 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 | diff --git a/verilog/heron_ctrl.v b/verilog/heron_ctrl.v index b4570b8..f5cbe87 100644 --- a/verilog/heron_ctrl.v +++ b/verilog/heron_ctrl.v @@ -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 diff --git a/verilog/heron_ctrl_tb.v b/verilog/heron_ctrl_tb.v new file mode 100644 index 0000000..bb91cf0 --- /dev/null +++ b/verilog/heron_ctrl_tb.v @@ -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 diff --git a/verilog/heron_fsm.v b/verilog/heron_fsm.v index 0347886..96093cb 100644 --- a/verilog/heron_fsm.v +++ b/verilog/heron_fsm.v @@ -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 diff --git a/verilog/heron_fsm_tb.v b/verilog/heron_fsm_tb.v index 9a9a23c..69326ef 100644 --- a/verilog/heron_fsm_tb.v +++ b/verilog/heron_fsm_tb.v @@ -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 diff --git a/verilog/heron_states.v b/verilog/heron_states.v new file mode 100644 index 0000000..98cedfd --- /dev/null +++ b/verilog/heron_states.v @@ -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