cpu32

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit 0f8a33c12038f8491d6d3b4875c6422740111767
parent 071a08bb2b8bfdd304142613b37e5d6664df99b3
Author: Brian Swetland <swetland@frotz.net>
Date:   Thu,  9 Feb 2012 20:43:44 -0800

cpu/control: start tidying up

Diffstat:
Mverilog/control.v | 97++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
Mverilog/cpu32.v | 31++++++++++++++++---------------
2 files changed, 93 insertions(+), 35 deletions(-)

diff --git a/verilog/control.v b/verilog/control.v @@ -1,3 +1,15 @@ +// Copyright 2012, Brian Swetland. Use at your own risk. + +`define PC_SRC_NEXT 2'b00 // normal +`define PC_SRC_B_IMM 2'b01 // on immediate branches +`define PC_SRC_B_REG 2'b10 // on indirect branches +`define PC_SRC_X 2'b11 // unspecified + +`define W_SRC_ALU 2'b00 // normal +`define W_SRC_RAM 2'b01 // on ram read ops +`define W_SRC_PC_NEXT 2'b10 // on branch link ops +`define W_SRC_X 2'b11 // unspecified + module control ( input [3:0] opcode, input [3:0] opfunc, @@ -6,35 +18,80 @@ module control ( output ctl_ram_we, output ctl_ram_rd, output ctl_d_or_b, - output ctl_branch, - output ctl_branch_ind, output ctl_imm16, + output reg [1:0] ctl_pc_src, + output reg [1:0] ctl_wdata_src, output [3:0] ctl_alu_func ); +reg ctl_branch; + +wire ctl_branch_op; +wire ctl_branch_ind; wire ctl_ram_op; +wire ctl_regs_we_; + +reg [7:0] control; + +always @ (*) + case (opcode) + 4'b0000: control = 8'b01000000; // ALU Rd, Ra, Rb + 4'b0001: control = 8'b01001100; // ALU Rd, Ra, #I + 4'b0010: control = 8'b01101100; // LW Rd, [Ra, #] + 4'b0011: control = 8'b00010100; // SW Rd, [Ra, #] + 4'b0100: control = 8'b10001100; // B* rel16 + 4'b0101: control = 8'b10000100; // B* Rb + 4'b0110: control = 8'b00000000; + 4'b0111: control = 8'b00000000; + 4'b1000: control = 8'b00000000; + 4'b1001: control = 8'b00000000; + 4'b1010: control = 8'b00000000; + 4'b1011: control = 8'b00000000; + 4'b1100: control = 8'b00000000; + 4'b1101: control = 8'b00000000; + 4'b1110: control = 8'b00000000; + 4'b1111: control = 8'b00000000; + endcase + +assign { ctl_branch_op, ctl_regs_we_, ctl_ram_rd, ctl_ram_we, ctl_d_or_b, ctl_imm16 } = control[7:2]; + +wire ctl_cond_z; +wire ctl_cond_nz; wire ctl_link_bit; -// cheesy decoder -- TODO: write for real -assign ctl_regs_we = - (opcode[3:1] == 3'h0) || - (opcode == 4'h2) || - (ctl_branch && ctl_link_bit) || - (ctl_branch_ind && ctl_link_bit); -assign ctl_d_or_b = ((opcode == 4'h1) || (opcode == 4'h2) || (opcode == 4'h4)); -assign ctl_ram_rd = (opcode == 4'h2); -assign ctl_ram_we = (opcode == 4'h3); -assign ctl_ram_op = ((opcode == 4'h2) || (opcode == 4'h3)); -assign ctl_alu_func = ctl_ram_op ? 4'b0010 : opfunc; -assign ctl_imm16 = (opcode != 4'h0); +assign ctl_cond_z = opfunc[0]; +assign ctl_cond_nz = opfunc[1]; assign ctl_link_bit = opfunc[3]; +assign ctl_branch_ind = opcode[0]; + +always @ (*) + case ( { ctl_branch_op, ctl_cond_z, ctl_cond_nz, ctl_adata_zero } ) + 4'b1110: ctl_branch = 1'b1; + 4'b1111: ctl_branch = 1'b1; + 4'b1101: ctl_branch = 1'b1; + 4'b1010: ctl_branch = 1'b1; + default: ctl_branch = 1'b0; + endcase + +always @ (*) + case ( { ctl_branch, ctl_branch_ind } ) + 2'b00: ctl_pc_src = `PC_SRC_NEXT; + 2'b01: ctl_pc_src = `PC_SRC_NEXT; + 2'b10: ctl_pc_src = `PC_SRC_B_IMM; + 2'b11: ctl_pc_src = `PC_SRC_B_REG; + endcase + +always @ (*) + case ( { ctl_branch, ctl_ram_rd } ) + 2'b00: ctl_wdata_src = `W_SRC_ALU; + 2'b01: ctl_wdata_src = `W_SRC_RAM; + 2'b10: ctl_wdata_src = `W_SRC_PC_NEXT; + 2'b11: ctl_wdata_src = `W_SRC_PC_NEXT; + endcase + +assign ctl_alu_func = (ctl_ram_rd | ctl_ram_we) ? 4'b0010 : opfunc; -// branch if it is a branch opcode and the condition is met -// unconditional branches set both condition bits -assign ctl_branch = (opcode == 4'h4) & - ((opfunc[0] & ctl_adata_zero) || (opfunc[1] & (!ctl_adata_zero))); -assign ctl_branch_ind = (opcode == 4'h5) & - ((opfunc[0] & ctl_adata_zero) || (opfunc[1] & (!ctl_adata_zero))); +assign ctl_regs_we = ctl_regs_we_ | (ctl_branch & ctl_link_bit); endmodule diff --git a/verilog/cpu32.v b/verilog/cpu32.v @@ -32,21 +32,22 @@ assign opimm16 = ir[15:0]; wire ctl_regs_we; // 1 = write back to register file wire ctl_d_or_b; // 0 = write to R[opseld], 1 = R[opselb] -wire ctl_branch; // 1 = direct branch -wire ctl_branch_ind; // 1 = indirect branch wire ctl_imm16; // 0 = bdata, 1 = imm16 -> alu right wire [3:0] ctl_alu_func; wire ctl_ram_we; wire ctl_ram_rd; +wire [1:0] ctl_wdata_src; +wire [1:0] ctl_pc_src; + control control( .opcode(opcode), .opfunc(opfunc), .ctl_adata_zero(ctl_adata_zero), .ctl_regs_we(ctl_regs_we), .ctl_d_or_b(ctl_d_or_b), - .ctl_branch(ctl_branch), - .ctl_branch_ind(ctl_branch_ind), + .ctl_pc_src(ctl_pc_src), + .ctl_wdata_src(ctl_wdata_src), .ctl_imm16(ctl_imm16), .ctl_ram_we(ctl_ram_we), .ctl_ram_rd(ctl_ram_rd), @@ -73,11 +74,11 @@ regfile #(32,4) REGS ( ); mux4 #(32) wdata_mux( - .sel({ctl_branch,ctl_ram_rd}), + .sel(ctl_wdata_src), .in0(result), .in1(d_data_r), .in2(pc_plus_4), - .in3(pc_plus_4), + .in3(32'b0), .out(wdata) ); @@ -87,7 +88,7 @@ wire S; assign S = opimm16[15]; mux4 #(32) pc_source( - .sel({ctl_branch_ind,ctl_branch}), + .sel(ctl_pc_src), .in0(pc_plus_4), .in1(pc + {S,S,S,S,S,S,S,S,S,S,S,S,S,S,opimm16,2'h0} ), .in2(bdata), @@ -101,17 +102,17 @@ assign ir = i_data; wire [31:0] binput; mux2 #(32) alu_right_mux( - .sel(ctl_imm16), - .in0(bdata), - .in1({ 16'h0, opimm16 }), - .out(binput) + .sel(ctl_imm16), + .in0(bdata), + .in1({ 16'h0, opimm16 }), + .out(binput) ); mux2 #(4) alu_wsel_mux( - .sel(ctl_d_or_b), - .in0(opseld), - .in1(opselb), - .out(alu_wsel) + .sel(ctl_d_or_b), + .in0(opseld), + .in1(opselb), + .out(alu_wsel) ); alu alu(