diff --git a/RTL/ALU.sv b/RTL/ALU.sv index 4a6f28b..9227475 100644 --- a/RTL/ALU.sv +++ b/RTL/ALU.sv @@ -1,55 +1,46 @@ -// Create Date: 2018.10.15 -// Module Name: ALU +// Module Name: ALU // Project Name: CSE141L // -// Revision 2022.04.30 -// Additional Comments: -// combinational (unclocked) ALU -import definitions::*; // includes package "definitions" -module ALU #(parameter W=8)( - input [W-1:0] InputA, // data inputs - InputB, - input SC_in, // shift or carry in - input [ 2:0] OP, // ALU opcode, part of microcode - output logic [W-1:0] Out, // or: output reg [7:0] OUT, - output logic PF, // reduction parity - output logic Zero, // output = zero flag - output logic SC_out // shift or carry out -// you may provide additional status flags as inputs, if desired - ); - - op_mne op_mnemonic; // type enum: used for convenient waveform viewing - -// InputA = current LFSR state -// InputB = tap_pattern - always_comb begin - Out = 0; - SC_out = 0; // No Op = default - case(OP) - kADD : {SC_out,Out} = {1'b0,InputA} + InputB; // add - kLSH : {SC_out,Out} = {InputA[7:0],SC_in}; // shift left, fill in with SC_in - // for logical left shift, tie SC_in = 0 - kRSH : {Out,SC_out} = {SC_in, InputA[7:0]}; // shift right - kXOR : Out = InputA ^ InputB; // exclusive OR - kAND : Out = InputA & InputB; // bitwise AND - endcase - end - - always_comb // assign Zero = !Out; - case(Out) - 'b0 : Zero = 1'b1; - default : Zero = 1'b0; - endcase - - always_comb - PF = ^Out; // Out[7]^Out[6]^...^Out[0] // reduction XOR +// Additional Comments: +// combinational (unclocked) ALU - always_comb - op_mnemonic = op_mne'(OP); // displays operation name in waveform viewer - -endmodule - - - /* InputA=10101010 SC_in = 1 - kLSH Out = 01010101 -*/ \ No newline at end of file +// includes package "Definitions" +// be sure to adjust "Definitions" to match your final set of ALU opcodes +import Definitions::*; + +module ALU #(parameter W=8)( + input [W-1:0] InputA, // data inputs + InputB, + input op_mne OP, // ALU opcode, part of microcode + input SC_in, // shift or carry in + output logic [W-1:0] Out, // data output + output logic Zero, // output = zero flag !(Out) + Parity, // outparity flag ^(Out) + Odd, // output odd flag (Out[0]) + SC_out // shift or carry out + // you may provide additional status flags, if desired + // comment out or delete any you don't need +); + +always_comb begin +// No Op = default +// add desired ALU ops, delete or comment out any you don't need + Out = 8'b0; // don't need NOOP? Out = 8'bx + SC_out = 1'b0; // will flag any illegal opcodes + case(OP) + ADD : {SC_out,Out} = InputA + InputB + SC_in; // unsigned add with carry-in and carry-out + LSH : {SC_out,Out} = {InputA[7:0],SC_in}; // shift left, fill in with SC_in, fill SC_out with InputA[7] +// for logical left shift, tie SC_in = 0 + RSH : {Out,SC_out} = {SC_in, InputA[7:0]}; // shift right + XOR : Out = InputA ^ InputB; // bitwise exclusive OR + AND : Out = InputA & InputB; // bitwise AND + SUB : {SC_out,Out} = InputA + (~InputB) + 1; // InputA - InputB; + CLR : {SC_out,Out} = 'b0; + endcase +end + +assign Zero = ~|Out; // reduction NOR Zero = !Out; +assign Parity = ^Out; // reduction XOR +assign Odd = Out[0]; // odd/even -- just the value of the LSB + +endmodule diff --git a/RTL/Ctrl.sv b/RTL/Ctrl.sv index 8083863..c07b829 100644 --- a/RTL/Ctrl.sv +++ b/RTL/Ctrl.sv @@ -1,25 +1,53 @@ // CSE141L -import definitions::*; +import Definitions::*; // control decoder (combinational, not clocked) // inputs from instrROM, ALU flags // outputs to program_counter (fetch unit) module Ctrl ( - input[ 8:0] Instruction, // machine code - input[ 7:0] DatMemAddr, - output logic Jump , - BranchEn , - RegWrEn , // write to reg_file (common) - MemWrEn , // write to mem (store only) - LoadInst , // mem or ALU to reg_file ? - PCTarg , - tapSel , - Ack // "done w/ program" + input[ 8:0] Instruction, // machine code + input[ 7:0] DatMemAddr, + output logic Branch , + BranchEn , + RegWrEn , // write to reg_file (common) + MemWrEn , // write to mem (store only) + LoadInst , // mem or ALU to reg_file ? + TapSel , + Ack , // "done w/ program" + output logic[1:0] PCTarg, // output logic[2:0] ALU_inst ); /* ***** All numerical values are completely arbitrary and for illustration only ***** */ +// alternative -- case format +always_comb begin +// list the defaults here + Branch = 'b0; + BranchEn = 'b0; + RegWrEn = 'b1; + MemWrEn = 'b0; + LoadInst = 'b0; + TapSel ' 'b0; // + PCTarg = 'b0; // branch "where to?" + case(Instruction[8:6]) // list just the exceptions + 3'b000: begin + MemWrEn = 'b1; // store, maybe + RegWrEn = 'b0; + end + 3'b001: LoadInst = 'b1; // load + 3'b010: begin end + 3'b011: begin end + 3'b100: begin end + 3'b101: begin end + 3'b110: begin end +// no default case needed -- covered before "case" + endcase +end + +assign Ack = ProgCtr == 971; +// alternative Ack = Instruction == 'b111_000_111 + // ALU commands //assign ALU_inst = Instruction[2:0]; @@ -35,12 +63,12 @@ assign LoadInst = Instruction[8:6]==3'b110; // calls out load specially assign tapSel = LoadInst && DatMemAddr=='d62; // jump enable command to program counter / instruction fetch module on right shift command -// equiv to simply: assign Jump = Instruction[2:0] == kRSH; +// equiv to simply: assign Jump = Instruction[2:0] == RSH; always_comb - if(Instruction[2:0] == kRSH) - Jump = 1; + if(Instruction[2:0] == RSH) + Branch = 1; else - Jump = 0; + Branch = 0; // branch every time instruction = 9'b?????1111; assign BranchEn = &Instruction[3:0]; @@ -50,7 +78,7 @@ assign BranchEn = &Instruction[3:0]; assign PCTarg = Instruction[3:2]; // reserve instruction = 9'b111111111; for Ack -assign Ack = &Instruction; +assign Ack = &Instruction; // = ProgCtr == 385; endmodule diff --git a/RTL/DataMem.sv b/RTL/DataMem.sv index b02a6fa..74f1b00 100644 --- a/RTL/DataMem.sv +++ b/RTL/DataMem.sv @@ -1,39 +1,50 @@ -// Create Date: 2017.01.25 -// Revision: 2022.05.04 made data width parametric -// Design Name: -// Module Name: DataMem -// single address pointer for both read and write -// CSE141L -module DataMem #(parameter W=8, D=8)( - input Clk, - Reset, // again, note use of Reset for preloads - WriteEn, - input [D-1:0] DataAddress, // 8-bit-wide pointer to 256-deep memory - input [W-1:0] DataIn, // 8-bit-wide data path, also - output logic[W-1:0] DataOut); - - logic [W-1:0] Core[2**D]; // 8x256 two-dimensional array -- the memory itself - - always_comb // reads are combinational - DataOut = Core[DataAddress]; - -/* optional way to plant constants into DataMem at startup - initial - $readmemh("dataram_init.list", Core); -*/ - always_ff @ (posedge Clk) // writes are sequential -/*( Reset response is needed only for initialization (see inital $readmemh above for another choice) - if you do not need to preload your data memory with any constants, you may omit the if(Reset) and the else, - and go straight to if(WriteEn) ... -*/ - if(Reset) begin -// you may initialize your memory w/ constants, if you wish - for(int i=128;i<256;i++) - Core[ i] <= 0; - Core[ 16] <= 254; // overrides the 0 ***sample only*** - Core[244] <= 5; // likewise - end - else if(WriteEn) - Core[DataAddress] <= DataIn; - -endmodule +// Create Date: 2017.01.25 +// Design Name: CSE141L +// Module Name: DataMem +// Last Update: 2022.01.13 + +// Memory can only read (LDR) or write (STR) on each Clk cycle, so there is a single +// address pointer for both read and write operations. +// +// Parameters: +// - A: Address Width. This controls the number of entries in memory +// - W: Data Width. This controls the size of each entry in memory +// This memory can hold `(2**A) * W` bits of data. +// +// WI22 is a 256-entry single-byte (8 bit) data memory. +module DataMem #(parameter W=8, A=8) ( // do not change W=8 + input Clk, + Reset, // initialization + WriteEn, // write enable + input [A-1:0] DataAddress, // A-bit-wide pointer to 256-deep memory + input [W-1:0] DataIn, // W-bit-wide data path, also + output logic[W-1:0] DataOut +); + +// 8x256 two-dimensional array -- the memory itself +logic [W-1:0] core[2**A]; + +// reads are combinational +always_comb + DataOut = core[DataAddress]; + +// writes are sequential +always_ff @ (posedge Clk) + /* + // Reset response is needed only for initialization. + // (see inital $readmemh above for another choice) + // + // If you do not need to preload your data memory with any constants, + // you may omit the `if (Reset) ... else` and go straight to `if(WriteEn)` + */ + + if(Reset) begin + // Preload desired constants into data_mem[128:255] + core[128] <= 'b1; + core[129] <= 'hff; + core[130] <= 'd64; + end + else if(WriteEn) // store + // Do the actual writes + core[DataAddress] <= DataIn; +endmodule diff --git a/RTL/Definitions.sv b/RTL/Definitions.sv index 83693f3..0be773b 100644 --- a/RTL/Definitions.sv +++ b/RTL/Definitions.sv @@ -1,24 +1,16 @@ //This file defines the parameters used in the alu // CSE141L -// Rev. 2020.5.27 +// Rev. 2022.5.27 // import package into each module that needs it // packages very useful for declaring global variables -package definitions; +// need > 8 instructions? +// typedef enum logic[3:0] and expand the list of enums +package Definitions; -/* Instruction map - const logic [2:0]kADD = 3'b000; - const logic [2:0]kLSH = 3'b001; - const logic [2:0]kRSH = 3'b010; - const logic [2:0]kXOR = 3'b011; - const logic [2:0]kAND = 3'b100; - const logic [2:0]kSUB = 3'b101; - const logic [2:0]kCLR = 3'b110; -*/ // enum names will appear in timing diagram - typedef enum logic[2:0] { - ADD, LSH, BSH, XOR, - AND, SUB, CLR } op_mne; -// note: kADD is of type logic[2:0] (3-bit binary) -// ADD is of type enum -- equiv., but watch casting -// see ALU.sv for how to handle this +// ADD = 3'b000; LSH = 3'b001; etc. 3'b111 is undefined here + typedef enum logic[2:0] { + ADD, LSH, RSH, XOR, + AND, SUB, CLR } op_mne; + endpackage // definitions diff --git a/RTL/Immediate_LUT.sv b/RTL/Immediate_LUT.sv new file mode 100644 index 0000000..498c966 --- /dev/null +++ b/RTL/Immediate_LUT.sv @@ -0,0 +1,26 @@ +/* CSE141L + possible lookup table for PC target + leverage a few-bit pointer to a wider number + Lookup table acts like a function: here Target = f(Addr); + in general, Output = f(Input); lots of potential applications +*/ +module Immediate_LUT #(PC_width = 10)( + input [ 2:0] addr, + output logic[PC_width-1:0] datOut + ); + +always_comb begin + datOut = 'h001; // default to 1 (or PC+1 for relative) + case(addr) + 2'b00: datOut = 'hfc; // -4, i.e., move back 16 lines of machine code + 2'b01: datOut = 'h03; + 2'b10: datOut = 'h07; + endcase +end + +endmodule + + + // 3fc = 1111111100 -4 + // PC 0000001000 8 + // 0000000100 4 \ No newline at end of file diff --git a/RTL/InstFetch.sv b/RTL/InstFetch.sv index 95fdd2e..2e9e56d 100644 --- a/RTL/InstFetch.sv +++ b/RTL/InstFetch.sv @@ -3,13 +3,13 @@ // Project Name: CSE141L // Description: instruction fetch (pgm ctr) for processor // -// Revision: 2019.01.27 +// Revision: 2021.11.27 // Suggested ProgCtr width 10 t0 12 bits module InstFetch #(parameter T=10)( // PC width -- up to 32, if you like input Reset, // reset, init, etc. -- force PC to 0 Start, // begin next program in series (request issued by test bench) Clk, // PC can change on pos. edges only - BranchAbs, // jump unconditionally to Target value + BranchAbs, // jump conditionally to Target value BranchRelEn, // jump conditionally to Target + PC ALU_flag, // flag from ALU, e.g. Zero, Carry, Overflow, Negative (from ARM) input [T-1:0] Target, // jump ... "how high?" @@ -19,13 +19,14 @@ module InstFetch #(parameter T=10)( // PC width -- up to 32, if you like // you may wish to use either absolute or relative branching // you may use both, but you will need appropriate control bits // branch/jump is how we handle gosub and return to main -// program counter can clear to 0, increment, or jump +// program counter can clear to 0, increment, or branch +// for unconditional branching, "ALU_flag" input should be driven by 1 always_ff @(posedge Clk) // or just always; always_ff is a linting construct if(Reset) ProgCtr <= 0; // for first program; want different value for 2nd or 3rd else if(Start) // hold while start asserted; commence when released ProgCtr <= 0; //or <= ProgCtr; holds at starting value - else if(BranchAbs) // unconditional absolute jump + else if(BranchAbs && ALU_flag // unconditional absolute jump ProgCtr <= Target; // how would you make it conditional and/or relative? else if(BranchRelEn && ALU_flag) // conditional relative jump ProgCtr <= Target + ProgCtr; // how would you make it unconditional and/or absolute diff --git a/RTL/InstFetch_TB.sv b/RTL/InstFetch_TB.sv deleted file mode 100644 index ad95c4f..0000000 --- a/RTL/InstFetch_TB.sv +++ /dev/null @@ -1,32 +0,0 @@ -module InstFetch_TB(); - - logic Reset = 1'b1, - Start = 1'b0, - Clk = 1'b0, - BranchAbs = 1'b0, - BranchRelEn = 1'b0, - ALU_flag = 1'b0; - logic [9:0] Target = 'b1; //10'h3fc;//'1; -4 - wire [9:0] ProgCtr; - -InstFetch IF1(.*); - -always begin - #5ns Clk = 1'b1; - #5ns Clk = 1'b0; -end - -initial begin - #20ns Reset = 1'b0; - #20ns Start = 1'b1; - #20ns Start = 1'b0; - #120ns BranchAbs = 1'b1; // should reset PC to 0 - #30ns BranchAbs = 1'b0; - #250ns BranchRelEn = 1'b1; - Target = 'h3fc; // -4 - #20ns ALU_flag = 1'b1; - #40ns ALU_flag = 1'b0; - #240ns $stop; -end - -endmodule \ No newline at end of file diff --git a/RTL/InstROM.sv b/RTL/InstROM.sv index ce9934b..5cad2a5 100644 --- a/RTL/InstROM.sv +++ b/RTL/InstROM.sv @@ -6,14 +6,18 @@ // Description: Verilog module -- instruction ROM template // preprogrammed with instruction values (see case statement) // -// Revision: 2020.08.08 -// +// Revision: 2021.08.08 +// +// A = program counter width +// W = machine code width -- do not change for CSE141L module InstROM #(parameter A=12, W=9) ( input [A-1:0] InstAddress, output logic[W-1:0] InstOut); // (usually recommended) expression // need $readmemh or $readmemb to initialize all of the elements +// This version will work best with assemblers, but you can try the alternative starting line 33 +// This version is also by far the easiest if you have a long program scrip. // declare 2-dimensional array, W bits wide, 2**A words deep logic[W-1:0] inst_rom[2**A]; always_comb InstOut = inst_rom[InstAddress]; diff --git a/RTL/TopLevel.sv b/RTL/TopLevel.sv deleted file mode 100644 index 434327a..0000000 --- a/RTL/TopLevel.sv +++ /dev/null @@ -1,151 +0,0 @@ -// Revision Date: 2022.05.05 -// Design Name: BasicProcessor -// Module Name: TopLevel -// CSE141L -- partial only -module TopLevel( // you will have the same 3 ports - input Reset, // init/reset, active high - Start, // start next program - Clk, // clock -- posedge used inside design - output logic Ack // done flag from DUT - ); - -// program counter / instructon fetch connections -wire [ 1:0] TargSel; // for branch LUT select -wire [ 9:0] PgmCtr, // program counter (wider if you wish) - PCTarg; -wire [ 8:0] Instruction; // our 9-bit opcode - -// data path connections -- everything is 8 bits wide -wire [ 7:0] ReadA, ReadB; // reg_file outputs -wire [ 7:0] InA, InB, // ALU operand inputs - ALU_out; // ALU result -wire [ 7:0] RegWriteValue, // data in to reg file - MemWriteValue, // data in to data_memory - MemReadValue, // data out from data_memory - DatMemAddr , // - Immediate; // - -// control wires -wire Imm, // inserts Immediate into ALU - MemWrite, // data_memory write enable - RegWrEn, // reg_file write enable - Zero, // ALU output = 0 flag - Jump, // to program counter: jump - BranchEn; // to program counter: branch enable -// ALU status register, analogous to ARM -logic PFq, // delayed/stored parity bit from ALU - SCq, // delayed/stored shift-carry out flag - Zq; // delayed/stored null out flag from ALU -logic[15:0] CycleCt; // standalone; NOT PC! - -// Fetch stage = Program Counter + Instruction ROM -// "InstFetch" = PC register + branch/increment logic - InstFetch IF1 ( // this is the program counter module - .Reset (Reset ) , // reset to 0 - .Start (Start ) , // SystemVerilog shorthand for .grape(grape) is just .grape - .Clk (Clk ) , // here, (Clk) is required in Verilog, optional in SystemVerilog - .BranchAbs (Jump ) , // jump enable - .BranchRelEn (BranchEn) , // branch enable - .ALU_flag (Zero ) , // - .Target (PCTarg ) , // "where to?" or "how far?" during a jump or branch - .ProgCtr (PgmCtr ) // program count = index to instruction memory - ); - - LUT LUT1(.Addr (TargSel ) , - .Target (PCTarg ) - ); - -// instruction ROM -- holds the machine code selected by program counter -// don't change W(9); increase A(10) if your machine code exceeds 1K lines - InstROM #(.W(9),.A(10)) IR1( - .InstAddress (PgmCtr ) , - .InstOut (Instruction) - ); - -// Decode stage = Control Decoder + Reg_file -// Control decoder - Ctrl Ctrl1 ( - .Instruction (Instruction) , // from instr_ROM -// outputs - .Jump (Jump ) , // to PC to handle jump/branch instructions - .BranchEn (BranchEn ) , // to PC - .RegWrEn (RegWrEn ) , // register file write enable - .MemWrEn (MemWrite ) , // data memory write enable - .LoadInst (LoadInst ) , // selects memory vs ALU output as data input to reg_file - .PCTarg (TargSel ) , - .tapSel (tapSel ) , - .DatMemAddr (DatMemAddr ) , - .Ack (Ack ) // "done" flag - ); - -// reg file -- don't change W(8); may increase to D(4) -// I arbitrarily mapped to Instructon fields [5:3] and [2:0] -// you do not have to do this!!! - RegFile #(.W(8),.D(3)) RF1 ( // D(3) makes this 8 elements deep - .Clk , - .WriteEn (RegWrEn) , - .RaddrA (Instruction[5:3]), // see hint below - .RaddrB (Instruction[2:0]), // or perhaps (Instruction[2:0]+1); -// by choosing Waddr = RaddrA, I am doing write-in-place operations -// such as A = A+B, as opposed to C = A+B - .Waddr (Instruction[5:3]), //3'b0 // mux above - .DataIn (RegWriteValue) , - .DataOutA (ReadA ) , - .DataOutB (ReadB ) - ); -// a trick you MAY find useful: -// use 2 instructon bits to select 2 adjacent addresses in RegFile -// .RaddA ({Instruction[1:0],1'b0}), -// .RaddB ({Instruction[1:0],1'b1}), - -// logic[3:0] Tap_ptr; // tap pattern selector -// sample LUT from a different program - logic[7:0] Immediate; // tap pattern itself - Immediate_LUT IL1(.addr(Instruction[5:3]), .datOut(Immediate)); - - assign InA = Imm? Immediate : ReadA; // connect RF out to ALU in - assign InB = ReadB; // interject switch/mux if needed/desired - assign MemWriteValue = ReadB; -// controlled by Ctrl1 -- must be high for load from data_mem; otherwise usually low - assign RegWriteValue = LoadInst? MemReadValue : ALU_out; // 2:1 switch into reg_file - ALU ALU1 ( - .InputA (InA), //(ReadA), - .InputB (InB), - .SC_in (PFq), // registered version of output flag - .OP (Instruction[8:6]), - .Out (ALU_out),//regWriteValue), - .PF (PF), // output parity status flag - .Zero (Zero), // null output status flag - .SC_out (SCout), // shift/carry output flag - ); // other flags as desired? - -// equiv. to ARM ALU status register -// store flags for next clock cycle - always @(posedge Clk) begin - SCq <= SCout; - PFq <= PF; - Zq <= Zero; - end - - DataMem DM1( - .DataAddress (ReadA) , - .WriteEn (MemWrite), - .DataIn (MemWriteValue), - .DataOut (MemReadValue) , - .Clk (Clk) , - .Reset (Reset) - ); - -//always_comb chosen_bit = MemReadValue[5:2]; - -/* count number of instructions executed - not part of main design, potentially useful - This one halts when Ack is high -*/ -always_ff @(posedge Clk) - if (Reset == 1) // if(start) - CycleCt <= 0; - else if(Ack == 0) // if(!halt) - CycleCt <= CycleCt+16'b1; - -endmodule \ No newline at end of file diff --git a/RTL/TopLevelLab2.sv b/RTL/TopLevelLab2.sv deleted file mode 100644 index 212e532..0000000 --- a/RTL/TopLevelLab2.sv +++ /dev/null @@ -1,78 +0,0 @@ -// team name quarter -module TopLevel( // you will have the same 3 ports - input Reset, // init/reset, active high - Start, // start next program - Clk, // clock -- posedge used inside design - output logic Ack // done flag from DUT - ); - - - InstFetch IF1 ( // this is the program counter module - .Reset (Reset ) , // reset to 0 - .Start (Start ) , // SystemVerilog shorthand for .grape(grape) is just .grape - .Clk (Clk ) , // here, (Clk) is required in Verilog, optional in SystemVerilog - .BranchAbs (Jump ) , // jump enable - .BranchRelEn (BranchEn) , // branch enable - .ALU_flag (Zero ) , // - .Target (PCTarg ) , // "where to?" or "how far?" during a jump or branch - .ProgCtr (PgmCtr ) // program count = index to instruction memory - ); - - LUT LUT1(.Addr (TargSel ) , - .Target (PCTarg ) - ); - - -// instruction ROM -- holds the machine code pointed to by program counter - InstROM #(.W(9),.A(10)) IR1( - .InstAddress (PgmCtr ) , - .InstOut (Instruction) - ); - - // in place c = a+c ADD R0 R1 R0 -// reg file - RegFile #(.W(8),.D(3)) RF1 ( // D(3) makes this 8 elements deep - .Clk , - .WriteEn (RegWrEn) , - .RaddrA (Instruction[5:3]), //3'b0 //concatenate with 0 to give us 4 bits - .RaddrB (Instruction[2:0]), // (Instruction[2:0]+1); - .Waddr (Instruction[5:3]), //3'b0 // mux above - .DataIn (RegWriteValue) , -// outputs - .DataOutA (ReadA ) , - .DataOutB (ReadB ) - ); - - ALU ALU1 ( - .InputA (InA), - .InputB (InB), - .SC_in (PFq), - .OP (Instruction[8:6]), -// outputs - .Out (ALU_out),//regWriteValue), - .PF (PF), - .Zero // status flag; may have others, if desired - ); - - always @(posedge Clk) - PFq <= PF; - - - DataMem DM1( -// inputs - .Clk (Clk) , - .Reset (Reset) , - .DataAddress (ReadA) , - .WriteEn (MemWrite), - .DataIn (MemWriteValue), -// outputs - .DataOut (MemReadValue) - ); - - - - - - - -endmodule \ No newline at end of file diff --git a/RTL/TopLevel_tb.sv b/RTL/TopLevel_tb.sv deleted file mode 100644 index 22a4671..0000000 --- a/RTL/TopLevel_tb.sv +++ /dev/null @@ -1,71 +0,0 @@ -// Create Date: 2017.01.25 -// Design Name: TopLevel Test Bench -// Module Name: TopLevel_tb.v -// CSE141L -// This is NOT synthesizable; use for logic simulation only -// Verilog Test Fixture created for module: TopLevel - -module TopLevel_tb; // Lab 17 - -// To DUT Inputs - bit Init = 'b1, - Req, // start - Clk; // logic Clk; // inits to 1'bx -// logic Clk = 1'b0; - -// From DUT Outputs - wire Ack; // done flag - -// Instantiate the Device Under Test (DUT) - TopLevel DUT ( - .Reset (Init) , - .Start (Req ) , - .Clk (Clk ) , - .Ack (Ack ) - ); - -initial begin - #10ns Init = 'b0; - #10ns Req = 'b1; -// Initialize DUT's data memory - #10ns for(int i=0; i<256; i++) begin - DUT.DM1.Core[i] = 8'h0; // clear data_mem - end - DUT.DM1.Core[1] = 8'h03; // MSW of operand A - DUT.DM1.Core[2] = 8'hff; - DUT.DM1.Core[3] = 8'hff; // MSW of operand B - DUT.DM1.Core[4] = 8'hfb; - DUT.DM1.Core[128] = 8'h00; // preload constants -// ... - DUT.DM1.Core[255] = 8'h00; -// students may also pre_load desired constants into DM -// Initialize DUT's register file - for(int j=0; j<16; j++) - DUT.RF1.Registers[j] = 8'b0; // default -- clear it -// students may pre-load desired constants into the reg_file -// $readmemb("machine_code.txt",inst); -// for(int k=0; k<1024; k++) -// DUT.IR1.inst_rom[k] = inst[k]; - - -// launch prodvgram in DUT - #10ns Req = 0; -// Wait for done flag, then display results - wait (Ack); - #10ns $displayh(DUT.DM1.Core[5], - DUT.DM1.Core[6],"_", - DUT.DM1.Core[7], - DUT.DM1.Core[8]); -// $display("instruction = %d %t",DUT.PC,$time); - #10ns $stop; // $finish; -end - -always begin // clock period = 10 Verilog time units - #5ns Clk = 'b1; - #5ns Clk = 'b0; -end - -endmodule - - - // always #5ns Clk = ~Clk; \ No newline at end of file diff --git a/RTL/dummy_DUT.sv b/RTL/dummy_DUT.sv new file mode 100644 index 0000000..296c587 --- /dev/null +++ b/RTL/dummy_DUT.sv @@ -0,0 +1,35 @@ +// skeletal starter code top level of your DUT +module top_level( + input clk, init, req, + output logic ack); + + logic mem_wen; + logic[7:0] mem_addr, + mem_in, + mem_out; + logic[11:0] pctr; // temporary program counter + +// populate with program counter, instruction ROM, reg_file (if used), +// accumulator (if used), + +DataMem DM(.Clk (clk), + .Reset (init), + .WriteEn (mem_wen), + .DataAddress (mem_addr), + .DataIn (mem_in), + .DataOut (mem_out)); + + +// temporary circuit to provide ack (done) flag to test bench +// remove or greatly increase the match value once you get a +// proper ack +always @(posedge clk) + if(init || req) + pctr <= 'h0; + else + pctr <= pctr+'h1; + +assign ack = pctr=='h256; // pctr needed to trigger ack (arbitary time) + +endmodule + diff --git a/RTL/prog_ctr2.sv b/RTL/prog_ctr2.sv deleted file mode 100644 index c864636..0000000 --- a/RTL/prog_ctr2.sv +++ /dev/null @@ -1,34 +0,0 @@ -// Design Name: basic_proc -// Module Name: InstFetch -// Project Name: CSE141L -// Description: instruction fetch (pgm ctr) for processor -// -// Revision: 2019.01.27 -// -module InstFetch( - input Reset, // reset, init, etc. -- force PC to 0 - Start, // begin next program in series (request issued by test bench) - Clk, // PC can change on pos. edges only - BranchAbs, // jump unconditionally to Target value - ALU_flag, // flag from ALU, e.g. Zero, Carry, Overflow, Negative (from ARM) - input [9:0] Target, // jump ... "how high?" - output logic [9:0] ProgCtr // the program counter register itself - ); - -// program counter can clear to 0, increment, or jump - always_ff @(posedge Clk) // or just always; always_ff is a linting construct - if(Reset) - ProgCtr <= 0; // for first program; want different value for 2nd or 3rd - else if(Start) // hold while start asserted; commence when released - ProgCtr <= 0;//ProgCtr; - else if(BranchAbs) // unconditional absolute jump - ProgCtr <= Target; // how would you make it conditional and/or relative? - else - ProgCtr <= ProgCtr+'b1; // default increment (no need for ARM/MIPS +4 -- why?) - -endmodule - -/* Note about Start: if your programs are spread out, with a gap in your machine code listing, you will want -to make Start cause an appropriate jump. If your programs are packed sequentially, such that program 2 begins -right after Program 1 ends, then you won't need to do anything special here. -*/ \ No newline at end of file diff --git a/RTL/program1_tb1.sv b/RTL/program1_tb1.sv new file mode 100644 index 0000000..b9c2262 --- /dev/null +++ b/RTL/program1_tb1.sv @@ -0,0 +1,156 @@ +// program1_tb +// testbench for programmable message encryption (Program #1) +// CSE141L +// runs program 1 (encrypt a message) +module encrypt_tb () ; +// DUT interface -- four one-bit wires, three to DUT, one from + bit clk , // advances simulation step-by-step + init = 1'b1 , // init (reset) command to DUT + start = 1'b1 ; // request (start program) command to DUT + wire done ; // acknowledge (program done) flag returned by DUT +// test bench parameters + logic[7:0] pre_length ; // number of space char. before message itself, sent to data_mem[61] + logic[7:0] message1[54] , // original raw message, in binary, up to 54 characters in length + msg_padded1[64], // original message, plus pre- and post-padding w/ ASCII spaces + msg_crypto1[64]; // encrypted message returned by DUT + logic[7:0] lfsr_ptrn , // choses one of 9 maximal length 7-tap shift reg. patterns + LFSR_ptrn[9] , // the 9 candidate maximal-length 7-bit LFSR tap ptrns themselves + lfsr1[64] , // states of program 1 encrypting LFSR + LFSR_init ; // one of 127 possible NONZERO starting states for encrypting LFSR + int score ; // count of correctly encyrpted characters +// our original American Standard Code for Information Interchange message follows +// note in practice your design should be able to handle ANY ASCII string that is +// restricted to characters between space (0x20) and script f (0x9f) and shorter than +// 55 characters in length + string str1 = "Mr. Watson, come here. I want to see you."; // sample program 1 input +// string str1 = " Knowledge comes, but wisdom lingers. "; // alternative inputs +// string str1 = " 01234546789abcdefghijklmnopqrstuvwxyz. "; // (make up your own, +// string str1 = " f A joke is a very serious thing."; // as well) +// string str1 = " Ajoke "; // +// string str1 = "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"; +// string str1 = " Knowledge comes, but wisdom lingers. "; // + +// displayed encrypted string will go here: + string str_enc1[64]; // program 1 desired output will go here + int strlen; // length of incoming message string itself, before padding + logic[3:0] pt_no; // select LFSR pattern, index value 0 through 8 + int file_no; // output file tag (set to 1 for write to console/transcript) +// the 9 possible 7-tap maximal-length feedback tap patterns from which to choose + assign LFSR_ptrn[0] = 8'h60; // (0)110_0000 + assign LFSR_ptrn[1] = 8'h48; + assign LFSR_ptrn[2] = 8'h78; + assign LFSR_ptrn[3] = 8'h72; + assign LFSR_ptrn[4] = 8'h6A; + assign LFSR_ptrn[5] = 8'h69; + assign LFSR_ptrn[6] = 8'h5C; + assign LFSR_ptrn[7] = 8'h7E; // (0)111_1110 + assign LFSR_ptrn[8] = 8'h7B; + always_comb begin + pt_no = 0;//$random; // or select a specific pattern ([0] and [1] are simplest to debug + if(pt_no>8) pt_no[3] = 0; // restrict pt_no to 0 through 8 + lfsr_ptrn = LFSR_ptrn[pt_no]; // look up and engage the selected pattern; to data_mem[62] + end +// now select a starting LFSR state -- any nonzero value will do + always_comb begin + LFSR_init = 'b1;//$random>>2; // or set a specific value, such as 7'b1, for easier debug + if(!LFSR_init) LFSR_init = 7'b1; // prevents illegal starting state = 7'b0; + end + +// set preamble length for the program run (always > 9 but < 26) + always_comb begin + pre_length = 10;//$random>>10 ; // number of space characters ahead of message; the >>10 changes the random value + if(pre_length < 10) pre_length = 10; // prevents pre_length < 10 + else if(pre_length > 26) pre_length = 26; + end + +// ***** instantiate your own top level design here ***** + top_level dut( + .clk (clk ), // input: use your own port names, if different + .init (init ), // input: some prefer to call this ".reset" + .req (start), // input: launch program + .ack (done ) // output: "program run complete" + ); + + initial begin +//***** pre-load your instruction ROM here or inside itself ***** +// $readmemb("encoder.bin", dut.instr_rom.rom); +// you may also pre-load desired constants, etc. into +// your data_mem here -- the upper addresses are reserved for your use +// dut.data_mem.DM[128]=8'hfe; //whatever constants you want +// to display to console, change this line to file_no = 'b1; + file_no = 'b1; // display to console instead of file +// file_no = $fopen("msg_enocder_out.txt","w"); // create your output file + #0ns strlen = str1.len; // length of string 1 (# characters between " ") + if(strlen>54) strlen = 54; // clip message at 54 characters +// program 1 -- precompute encrypted message + lfsr1[0] = LFSR_init; // any nonzero value (zero may be helpful for debug) + $fdisplay(file_no,"run encryption program; original message = "); + $fdisplay(file_no,"%s",str1); // print original message in transcript window + $fdisplay(file_no,"pt_no = %d",pt_no); + $fdisplay(file_no,"LFSR_ptrn = 0x%h, LFSR_init = 0x%h",lfsr_ptrn,LFSR_init); + +// will subtract 0x20 from each preamble and each message character + for(int j=0; j<64; j++) // pre-fill message_padded with ASCII space characters + msg_padded1[j] = 8'h20; // + for(int l=0; l