blob: a105054e85eebdabfd4de23158d3b5f79b3ec9ae [file] [log] [blame]
`default_nettype none
module xyz_peppergray_Potato1_top(
input [7:0] io_in,
output [7:0] io_out
);
localparam INSTR_WITH = 4;
localparam INSTR_NUM = 9;
localparam CNTRL_WITH = 9;
localparam CMD_WITH = 8;
localparam LOOPCTR_WITH = 16;
localparam CTRL_X_INC = 0;
localparam CTRL_X_DEC = 1;
localparam CTRL_A_INC = 2;
localparam CTRL_A_DEC = 3;
localparam CTRL_PUT = 4;
localparam CTRL_GET = 5;
localparam CTRL_LOOP = 6;
localparam CTRL_DONE = 7;
localparam CTRL_HALT = 8;
localparam X_PC_INC = 0;
localparam X_PC_DEC = 1;
localparam CMD_OFFSET = 2;
wire Clock = io_in[0];
wire Reset_n = io_in[1];
reg ZeroFlag;
reg IOWait;
reg [INSTR_WITH-1:0] Instruction;
/* Input */
always @(posedge Clock or negedge Reset_n) begin
if(~Reset_n) begin
Instruction <= 4'b1111; /* Halt */
ZeroFlag <= 0;
IOWait <= 0;
end
else begin
Instruction <= io_in[7:4];
ZeroFlag <= io_in[3];
IOWait <= (IOActivity && io_in[2]);
end
end
/* Instruction Decode */
reg [INSTR_NUM-1:0] MicroInstruction;
always @ * begin
case(Instruction)
4'b0000: begin MicroInstruction <= (1 << CTRL_X_INC); end
4'b0001: begin MicroInstruction <= (1 << CTRL_X_DEC); end
4'b0010: begin MicroInstruction <= (1 << CTRL_A_INC); end
4'b0011: begin MicroInstruction <= (1 << CTRL_A_DEC); end
4'b0100: begin MicroInstruction <= (1 << CTRL_PUT); end
4'b0101: begin MicroInstruction <= (1 << CTRL_GET); end
4'b0110: begin MicroInstruction <= (1 << CTRL_LOOP); end
4'b0111: begin MicroInstruction <= (1 << CTRL_DONE); end
4'b1111: begin MicroInstruction <= (1 << CTRL_HALT); end
default: begin MicroInstruction <= 0; /* CTRL_NOP */ end
endcase
end
/* Loop Control */
reg reverse;
reg skipCmd;
wire Reverse = setReverse | (reverse & ~clrReverse);
wire SkipCmd = setSkipCmd | (skipCmd & ~clrSkipCmd);
wire Loop = MicroInstruction[CTRL_LOOP];
wire Done = MicroInstruction[CTRL_DONE];
wire setSkipCmd_L =!reverse && !skipCmd & ZeroFlag;
wire clrReverse_L = reverse && markMatch;
wire clrSkipCmd_L = skipCmd && clrReverse;
wire setReverse_D = !reverse && !skipCmd && !ZeroFlag;
wire setSkipCmd_D = setReverse;
wire clrSkipCmd_D = skipCmd && markMatch;
wire setSkipCmd = Loop ? setSkipCmd_L : Done ? setSkipCmd_D : 0;
wire clrSkipCmd = Loop ? clrSkipCmd_L : Done ? clrSkipCmd_D : 0;
wire setReverse = Done ? setReverse_D : 0;
wire clrReverse = Loop ? clrReverse_L : 0;
wire Count = !((!reverse && setReverse) || (reverse && clrReverse));
wire Up = Count && (reverse ? Done : Loop);
wire Down = Count && (reverse ? Loop : Done);
wire Store = setSkipCmd;
reg [LOOPCTR_WITH-1:0] LoopCounter;
reg [LOOPCTR_WITH-1:0] LoopJmpMark;
wire markMatch = (LoopJmpMark == LoopCounter);
always @(negedge Clock or negedge Reset_n) begin
if(~Reset_n) begin
LoopCounter <= 0;
LoopJmpMark <= 0;
reverse <= 0;
skipCmd <= 0;
end
else begin
LoopCounter <= LoopCounter + (Count ? (Up ? 1 : Down ? -1 : 0) : 0);
LoopJmpMark <= (Store ? LoopCounter + (Up ? 1 : Down ? -1 : 0) : LoopJmpMark);
reverse <= clrReverse ? 0 : setReverse ? 1 : reverse;
skipCmd <= clrSkipCmd ? 0 : setSkipCmd ? 1 : skipCmd;
end
end
/* Execution Control */
reg [CNTRL_WITH-1:0] Control;
always @ * begin
Control = IOWait ? Control : SkipCmd ? 0 : MicroInstruction;
end
/* ProgramCounter */
wire [1:0] Control_PC;
assign Control_PC[X_PC_INC] = ~Reverse & ~(Control[CTRL_HALT] | IOWait);
assign Control_PC[X_PC_DEC] = Reverse & ~(Control[CTRL_HALT] | IOWait);
/* Output */
reg [CMD_WITH-1:0] Command;
assign io_out = Command;
wire IOActivity = (Command[CMD_OFFSET + CTRL_GET] || Command[CMD_OFFSET + CTRL_PUT]);
always @(negedge Clock or negedge Reset_n) begin
if(~Reset_n) begin
Command <= 0;
end
else begin
Command <= { Control[5:0], Control_PC[1:0]};
end
end
endmodule