📄 risc8_control.v
字号:
//-----------------------------------------------------------------------------
// (C) COPYRIGHT 2000 S.Aravindhan
//
// This program is free software; you can redistribute it and/or
// modify it provided this header is preserved on all copies.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
// Author : S.Aravindhan
// File : risc8_control.v
// Abstract : Control Unit and Instruction Decoder.
// Please use 160 column window to view this file
//
// History:
// ============================================================================
// 02/06/2000 arvind 1.0 Initial Release
// ============================================================================
module risc8_control (/*AUTOARG*/
// Outputs
alu_cmd, carry_src, a_addr, b_addr, w_addr, wr_reg, a_src, b_src,
muldiv_op, flag_op, data_op, addr_op, invert_b, lu_op, inc_pc,
opcode_op, int_type,
// Inputs
clk, rst_n, nmi, int, queue_out, psw, data_ready, queue_count,
divide_by_0
);
output [3:0] alu_cmd; // alu command
output [2:0] carry_src; // carry source
output [3:0] a_addr; // a-bus read reg. address
output [3:0] b_addr; // b-bus read reg. address
output [3:0] w_addr; // write-back reg. address
output wr_reg; // write register
output [1:0] a_src; // alu a-bus source
output [1:0] b_src; // alu b-bus source
output [5:0] muldiv_op; // mulitier/divider operation
output [2:0] flag_op; // flag operation
output [2:0] data_op; // data cycle operation
output [3:0] addr_op; // address register operation
output invert_b; // invert b-bus
output lu_op; // Logic Unit Operation
output [1:0] inc_pc; // increment pc
output [4:0] opcode_op; // opcode fetch operations
output [1:0] int_type; // interrupt type
input clk; // clock
input rst_n; // reset
input nmi; // non-maskable interrupt
input int; // maskable interrupt
input [7:0] queue_out; // instruction queue fifo output
input [7:0] psw; // psw
input data_ready; // data ready
input [2:0] queue_count; // instruction queue count
input divide_by_0; // divide by zero
reg [3:0] state;
reg [3:0] alu_cmd;
reg [2:0] carry_src;
reg invert_b;
reg [3:0] a_addr;
reg [3:0] b_addr;
reg [3:0] w_addr;
reg wr_reg;
reg [1:0] a_src;
reg [1:0] b_src;
reg [7:0] opcode_tmp;
reg [1:0] inc_pc;
reg [4:0] opcode_op_d;
reg lu_op;
reg [2:0] flag_op;
reg [5:0] muldiv_op;
reg [2:0] data_op;
reg [3:0] addr_op;
reg condition;
reg [51:0] decode;
reg nmi_reg;
reg int_reg;
reg div_reg;
reg int_processing;
reg next_int_processing;
reg [1:0] int_type;
reg [1:0] next_int_type;
wire [3:0] operan;
wire [3:0] operan1;
wire [3:0] operan2;
wire opcode_valid;
wire sel_opcode_tmp;
wire clear_opcode;
wire load_opcode_tmp;
wire [7:0] opcode;
wire queue_count_gt0;
wire queue_count_gt1;
wire lda_sta_opcode;
wire int_pending;
assign opcode_op = decode[11:7];
assign sel_opcode_tmp = opcode_op_d[2];
assign clear_opcode = opcode_op_d[3];
assign load_opcode_tmp = opcode_op[1];
assign operan = {1'b0, opcode[2:0]};
assign operan1 = {1'b0, opcode[1:0], 1'b0};
assign operan2 = {1'b0, opcode[1:0], 1'b1};
assign int_pending = ((state == `ST0) & (nmi_reg |
(int_reg & psw[4]) | div_reg));
assign lda_sta_opcode = (opcode[7:4] == 4'b1111); // load/store only
assign queue_count_gt0 = ~(queue_count == 3'b000);
assign queue_count_gt1 = (queue_count > 3'b001);
assign opcode_valid = sel_opcode_tmp |
(~lda_sta_opcode & queue_count_gt0 & ~clear_opcode) |
(lda_sta_opcode & queue_count_gt1 & ~clear_opcode);
assign opcode = (sel_opcode_tmp)? opcode_tmp : queue_out;
// store the interrupt/nmi/divide_by_zero till they are serviced
always @ (posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
nmi_reg <= 1'b0;
int_reg <= 1'b0;
div_reg <= 1'b0;
end
else
begin
if(int_type == 2'b01)
nmi_reg <= 1'b0;
else if(nmi_reg)
nmi_reg <= 1'b1;
else
nmi_reg <= nmi;
if(int_type == 2'b10)
div_reg <= 1'b0;
else if(div_reg)
div_reg <= 1'b1;
else
div_reg <= divide_by_0;
if(int_type == 2'b11)
int_reg <= 1'b0;
else if(int_reg)
int_reg <= 1'b1;
else
int_reg <= (int); // psw[4] = ie
end
end
// moving controls from DECODE stage to EXECUTE stage.
always @ (posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
int_processing <= 0;
int_type <= 2'b00;
opcode_tmp <= 8'h00;
lu_op <= 1'b1;
{state, alu_cmd, carry_src, invert_b, a_addr, b_addr,
w_addr, wr_reg, a_src, b_src, flag_op, muldiv_op, inc_pc,
opcode_op_d, data_op, addr_op} <= 0;
end
else
begin
if(load_opcode_tmp)
opcode_tmp <= queue_out;
lu_op <= ~(decode[47:44] == `ALUadd);
if(data_ready)
begin
int_processing <= next_int_processing;
int_type <= next_int_type;
{state, alu_cmd, carry_src, invert_b, a_addr, b_addr,
w_addr, wr_reg, a_src, b_src, flag_op, muldiv_op, inc_pc,
opcode_op_d, data_op, addr_op} <= decode;
end
end
end
// branch condition check; Flags Mapping: {V, N, C, Z} = psw[3:0]
always @ (opcode or psw)
begin
case(opcode[2:0])
3'b000: condition = (psw[0]); // EQ
3'b001: condition = (~psw[0]); // NE
3'b010: condition = (~(psw[3] ^ psw[2]) & ~psw[0]); // GT
3'b011: condition = (psw[3] ^ psw[2]); // LT
3'b100: condition = (psw[1]); // CS
3'b101: condition = (psw[2]); // CC
3'b110: condition = (psw[3]); // NS
3'b111: condition = 1'b1; // AL
endcase
end
// INSTRUCTION DECODE: One BIG case statement!!
// outputs
// state, alu_cmd, carry_src, invert_b, a_addr, b_addr, w_addr, wr_reg,
// a_src, b_src, flag_op, muldiv_op, inc_pc, opcode_op, data_op, addr_opp
always @ (opcode or state or opcode_valid or operan or operan1 or operan2 or
a_addr or b_addr or w_addr or alu_cmd or invert_b or a_src or b_src
or queue_count_gt0 or queue_count_gt1 or condition or carry_src or
divide_by_0 or int_pending or int_processing or nmi_reg or div_reg
or int_type)
begin
decode = {`ST0, `ALUpre, `CRYc, `PIb, `ADRpva, `ADRpvb, `ADRpvw, `Nrg, `ASRCp, `BSRCp, `FLnul, `MDnul, `PC0, `OPC00000, `DAOPno, `ADOPnul };
next_int_type = 2'b00; next_int_processing = 0;
if(int_pending | int_processing)
begin
next_int_processing = 1;
case(state[2:0])
3'b000: decode = {`ST1, `ALUpre, `CRYp, `NIb, `ADRspl, `ADRr0, `ADRspl, `Nrg, `ASRC0, `BSRCp, `FLnul, `MDnul, `PC0, `OPC11000, `DAOPwr, `ADOPrsp};
3'b001: decode = {`ST2, `ALUpre, `CRYp, `NIb, `ADRspl, `ADRpsw, `ADRspl, `Nrg, `ASRC0, `BSRCp, `FLnul, `MDnul, `PC0, `OPC10000, `DAOPwr, `ADOPinc};
3'b010: decode = {`ST3, `ALUpre, `CRYp, `NIb, `ADRspl, `ADRpcl, `ADRspl, `Nrg, `ASRC0, `BSRCp, `FLnul, `MDnul, `PC0, `OPC10000, `DAOPwr, `ADOPinc};
3'b011: decode = {`ST4, `ALUpre, `CRYp, `NIb, `ADRspl, `ADRpch, `ADRspl, `Nrg, `ASRC0, `BSRCp, `FLnul, `MDnul, `PC0, `OPC10000, `DAOPwr, `ADOPinc};
3'b100: begin
if(nmi_reg)
begin
next_int_type = 2'b01;
decode = {`ST5, `ALUtha, `CRYp, `NIb, `ADRspl, `ADRpch, `ADRpcl, `Nrg, `ASRC1, `BSRCp, `FLclie, `MDnul, `PC0, `OPC10100, `DAOPno, `ADOPint};
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -