Marmara Lectures Marmara Lectures Thu, 27 Jan 2022 12:06:52 +0000 en-US hourly 1 https://wordpress.org/?v=5.9 Dirac Deltas and Impulse Trains /dirac-deltas-and-impulse-trains/ /dirac-deltas-and-impulse-trains/#respond Thu, 10 Jun 2021 19:24:03 +0000 /?p=653 SUM OF COMPLEX EXPONENTIALS

Consider the geometric series
$$\begin{eqnarray}
D(u) &=& \sum_{n=-k}^{k} e^{-i u n} \\
&=& e^{-i u k}+e^{-i u (k-1)}+\ldots+e^{-i u (k-1)}+ e^{-i u k}\\
&=& e^{-i u k} \left(1+e^{i u }+e^{i 2u}+\ldots+e^{i (2k-1)u}+ e^{i 2ku}\right)\\
&=&e^{-i ku} \frac{1-e^{(2k+1)ui }}{1-e^{i u}}
\end{eqnarray} $$

To ease the notation, let us define $r=e^{i u}$. Then, the above expression can be simplified as

$$\begin{eqnarray}
r^{-k}\frac{1-r^{2k+1}}{1-r}
&=& r^{-k} \frac{r^\frac{{2k+1}}{2}\left[r^{-\frac{{2k+1}}{2}}-r^\frac{{2k+1}}{2}\right]}{r^{\frac{1}{2}}\left[ r^{-\frac{1}{2}}-r^{\frac{1}{2}}\right]}\\
&=&\frac{r^{-\frac{{2k+1}}{2}}-r^\frac{{2k+1}}{2}}{ r^{-\frac{1}{2}}-r^{\frac{1}{2}}}
\end{eqnarray} $$

Substituting back $r=e^{-i u}$,

$$\begin{eqnarray}
&=&\frac{e^{\frac{2k+1}{2}i u}-e^{-\frac{{2k+1}}{2}i u}}{ e^{\frac{i u}{2}}-e^{-\frac{i u}{2}}}\\\\
&=&\frac{\frac{e^{\frac{2k+1}{2}i u}-e^{-\frac{{2k+1}}{2}i u}}{2i}}{ \frac{e^{\frac{i u}{2}}-e^{-\frac{i u}{2}}}{2i}}\\\\
&=& \frac{\sin\left(\frac{2k+1}{2} u \right)}{\sin\left(\frac{ u}{2}\right)}
\end{eqnarray} $$

Or, in summary, we have proved that

$$\begin{eqnarray}
D(u) &=& \sum_{n=-k}^{k} e^{-i u n} &=& \frac{\sin\left(\frac{2k+1}{2} u\right)}{\sin\left(\frac{ u}{2}\right)}
\end{eqnarray} $$

The denominator becomes zero at $\frac{u}{2}=m\pi$ or $u = 2 m \pi$ for any integer $m$. By using L’Hospital’s rule

$$\begin{eqnarray}
D(u=2 m \pi) = 2k+1
\end{eqnarray} $$

]]>
/dirac-deltas-and-impulse-trains/feed/ 0
Discrete Fourier Transforms /discrete-fourier-transforms/ /discrete-fourier-transforms/#respond Sun, 06 Jun 2021 12:52:52 +0000 /?p=649 $$ \begin{eqnarray}
x[n] = \frac{1}{2\pi} \int_{<2\pi>}X(\Omega)e^{i\Omega n}d\Omega\\\\
X(\Omega) = \sum_{k=-\infty}^{\infty}x[k]e^{-i\Omega k}
\end{eqnarray}$$

DFT FOR PERIODIC CASE

Consider a periodic signal $x[n]$, $x[n+N]=x[n]$.

$$ \begin{eqnarray}
X(\Omega) &=& \sum_{k=-\infty}^{\infty}x[k]e^{-i\Omega k}\\\\
&=& \sum_{n=-\infty}^{\infty}\sum_{k=nN}^{(n+1)N-1}x[k]e^{-i\Omega k}\\\\
&=& \sum_{n=-\infty}^{\infty} \sum_{k=0}^{N-1}x[k+nN]e^{-i\Omega (k+nN)}\\\\
&=& \sum_{n=-\infty}^{\infty} \sum_{k=0}^{N-1}x[k]e^{-i\Omega k}e^{-i\Omega Nn}\\\\
&=&\left(  \sum_{k=0}^{N-1}x[k]e^{-i\Omega k}\right)\left(\sum_{n=-\infty}^{\infty}e^{-i\Omega Nn}\right)
\end{eqnarray}$$

]]>
/discrete-fourier-transforms/feed/ 0
Continuous Fourier Transforms /continuous-fourier-transforms/ /continuous-fourier-transforms/#respond Sat, 05 Jun 2021 20:18:57 +0000 /?p=629 Theorem:
$$
X(\omega)=\int_{t=-\infty}^{\infty}x(t) e^{-i \omega t} dt $$

$$
x(t)=\frac{1}{2\pi}\int_{\omega=-\infty}^{\infty}X(\omega) e^{i \omega t} d\omega $$

EXAMPLES

Example 1: Find the FT of $x(t)=e^{-\alpha t}U(t)$ for $\alpha>0$.

Answer 1:

$$\begin{eqnarray}
X(\omega)&=&\int_{t=-\infty}^{\infty}e^{-\alpha t}U(t) e^{-i \omega t} dt\\
&=&\int_{t=0}^{\infty}e^{-(\alpha t+i \omega) t} dt\\
&=&\left. \frac{e^{-(\alpha t+i \omega) t}}{-(\alpha +i \omega)}\right\vert_{t=0}^{\infty}\\
&=&\frac{1}{\alpha +i \omega}
\end{eqnarray} $$

Example 2: Find the FT of $x(t)=U(t)$.

Answer 2:

$$\begin{eqnarray}
X(\omega)&=&\int_{t=-\infty}^{\infty}U(t) e^{-i \omega t} dt\\
&=&\int_{t=0}^{\infty}e^{-i \omega t} dt\\
&=&\left. \frac{e^{-i \omega t}}{-i \omega}\right\vert_{t=0}^{\infty}\\
&=&\frac{1}{i \omega}-\lim_{t \rightarrow \infty }\frac{e^{-i \omega t}}{i \omega}\\
&=&\frac{1}{i \omega}+\pi\delta(\omega)
\end{eqnarray} $$

Example 3: Find the FT of $x(t)=1$.

Answer 3:

$$\begin{eqnarray}
X(\omega)&=&\int_{t=-\infty}^{\infty}1. e^{-i \omega t} dt\\
&=&\left. \frac{e^{-i \omega t}}{-i \omega}\right\vert_{t=-\infty}^{\infty}\\
&=&\lim_{t \rightarrow \infty }\frac{e^{i \omega t}-e^{-i \omega t}}{i \omega}\\
&=&\lim_{t \rightarrow \infty }2\frac{\sin(\omega t)}{\omega}\\
&=& 2 \pi \delta(\omega)
\end{eqnarray} $$

Example 4: Find the FT of $\chi_{[-T,T]}(t)$.

Answer 4:

$$\begin{eqnarray}
X(\omega)&=&\int_{t=-\infty}^{\infty}\chi_{[-T,T]}(t) e^{-i \omega t} dt\\
&=&\int_{t=-T}^{T} e^{-i \omega t} dt\\
&=&\left. \frac{e^{-i \omega t}}{-i \omega}\right\vert_{t=-T}^{T}\\
&=&\frac{e^{i \omega T}-e^{-i \omega T}}{i \omega}\\
&=&2\frac{\sin(\omega T)}{\omega}
\end{eqnarray} $$

Note that Example 3 is a special case of this example, as $T \rightarrow \infty$:

$$\begin{eqnarray}
\lim_{T \rightarrow \infty }\chi_{[-T,T]}(t) &\rightarrow& 1\\
\lim_{T \rightarrow \infty } 2\frac{\sin(\omega T)}{\omega} &\rightarrow& 2\pi \delta(\omega)
\end{eqnarray} $$

Example 5: Find the FT of $x(t)=e^{iat}$ .

Answer 5:

$$\begin{eqnarray}
X(\omega)&=&\int_{t=-\infty}^{\infty}e^{iat}. e^{-i \omega t} dt\\
&=&\left. \frac{e^{i (a-\omega) t}}{i (a-\omega)}\right\vert_{t=-\infty}^{\infty}\\
&=&\lim_{t \rightarrow \infty }\frac{e^{i (a-\omega) t}-e^{-i (a-\omega) t}}{i (a-\omega)}\\
&=&\lim_{t \rightarrow \infty }2\frac{\sin((a-\omega) t)}{a-\omega}\\
&=& 2 \pi \delta(a-\omega)
\end{eqnarray} $$

Note that example 3 is a special case of this example for $a=0$. (also remember that $\delta(t)=\delta(-t))$

Example 6: Find the FT of $x(t)=\delta(t-a)$.

Answer 6:

$$\begin{eqnarray}
X(\omega)&=&\int_{t=-\infty}^{\infty}\delta(t-a) e^{-i \omega t} dt\\\\
&=& e^{-i a t}
\end{eqnarray} $$

Example 7: Find the FT of $x(t)=e^{-a|t|}$ for $a>0$.

Answer 7:

$$\begin{eqnarray}
X(\omega)&=&\int_{t=-\infty}^{\infty}e^{-a|t|} e^{-i \omega t} dt\\\\
&=&\int_{t=-\infty}^{0}e^{at} e^{-i \omega t} dt+\int_{t=0}^{\infty}e^{-at} e^{-i \omega t} dt\\\\
&=&\left. \frac{e^{(\alpha -i \omega) t}}{\alpha -i \omega}\right\vert_{t=-\infty}^{0} + \left. \frac{e^{(-\alpha -i \omega) t}}{-\alpha -i \omega}\right\vert_{t=0}^{\infty}\\\\
&=&\frac{1}{\alpha -i \omega}+\frac{1}{\alpha +i \omega}\\\\
&=&\frac{2a}{\alpha^2 + \omega^2}
\end{eqnarray} $$

SUM OF COMPLEX EXPONENTIALS

Consider the geometric series
$$\begin{eqnarray}
\sum_{n=-k}^{k} e^{-i A n} &=& e^{-i A k}+e^{-i A (k-1)}+\ldots+e^{-i A (k-1)}+ e^{-i A k}\\
&=& e^{-i A k} \left(1+e^{i A }+e^{i 2A}+\ldots+e^{i (2k-1)A}+ e^{i 2kA}\right)\\
&=&e^{-i kA} \frac{1-e^{(2k+1)Ai }}{1-e^{i A}}
\end{eqnarray} $$

To ease the notation, let us define $r=e^{i A}$. Then, the above expression can be simplified as

$$\begin{eqnarray}
r^{-k}\frac{1-r^{2k+1}}{1-r}
&=& r^{-k} \frac{r^\frac{{2k+1}}{2}\left[r^{-\frac{{2k+1}}{2}}-r^\frac{{2k+1}}{2}\right]}{r^{\frac{1}{2}}\left[ r^{-\frac{1}{2}}-r^{\frac{1}{2}}\right]}\\
&=&\frac{r^{-\frac{{2k+1}}{2}}-r^\frac{{2k+1}}{2}}{ r^{-\frac{1}{2}}-r^{\frac{1}{2}}}
\end{eqnarray} $$

Substituting back $r=e^{-i \omega T}$,

$$\begin{eqnarray}
&=&\frac{e^{\frac{2k+1}{2}i \omega T}-e^{\frac{-{2k+1}}{2}i \omega T}}{ e^{\frac{i \omega T}{2}}-e^{-\frac{i \omega T}{2}}}\\\\
&=&\frac{\frac{e^{\frac{2k+1}{2}i \omega T}-e^{\frac{-{2k+1}}{2}i \omega T}}{2i}}{ \frac{e^{\frac{i \omega T}{2}}-e^{-\frac{i \omega T}{2}}}{2i}}\\\\
&=& \frac{\sin\left(\frac{2k+1}{2} \omega T\right)}{\sin\left(\frac{ \omega T}{2}\right)}
\end{eqnarray} $$

Or, in summary, we have proved that

$$\begin{eqnarray}
\sum_{n=-k}^{k} e^{-i \omega nT} &=& \frac{\sin\left(\frac{2k+1}{2} \omega T\right)}{\sin\left(\frac{ \omega T}{2}\right)}
\end{eqnarray} $$

CFT OF IMPULSE TRAIN

Impulse train is a periodic signal with period $T$:

$$\begin{eqnarray}
x(t)=\sum_{k=-\infty}^{\infty}\delta(t-kT)
\end{eqnarray} $$

Its CFT is

$$\begin{eqnarray}
X(\omega)&=&\int_{t=-\infty}^{\infty}\left( \sum_{k=-\infty}^{\infty}\delta(t-kT) \right)e^{-i \omega t} dt\\\\
&=& \sum_{k=-\infty}^{\infty}\int_{t=-\infty}^{\infty}\delta(t-kT) e^{-i \omega t} dt\\\\
&=& \sum_{k=-\infty}^{\infty}e^{-i \omega kT}
\end{eqnarray} $$

We can express this result as

$$\begin{eqnarray}
X(\omega)&=&\lim_{N \rightarrow \infty}\sum_{k=-N}^{N}e^{-i \omega kT}
\end{eqnarray} $$

Then, we can utilize the summation of complex exponentials formula given above, with the substitution $\omega T \Rightarrow A$.

$$\begin{eqnarray}
X(\omega)&=& \frac{\sin\left(\frac{2N+1}{2} \omega T\right)}{\sin\left(\frac{ \omega T}{2}\right)}
\end{eqnarray} $$

CFT OF PERIODIC FUNCTIONS

Let $x(t)=x(t+T)$. Then,

$$\begin{eqnarray}
X(\omega)&=&\int_{t=-\infty}^{\infty}x(t) e^{-i \omega t} dt \\
&=& \sum_{n=-\infty}^{\infty} \int_{t=nT}^{(n+1)T} x(t) e^{-i \omega t} dt\\
&=& \sum_{n=-\infty}^{\infty} \int_{t=0}^{T} x(t+nT) e^{-i \omega (t+nT)} dt\\
&=& \sum_{n=-\infty}^{\infty} \int_{t=0}^{T} x(t) e^{-i \omega (t+nT)} dt\\
&=& \sum_{n=-\infty}^{\infty} \int_{t=0}^{T} x(t) e^{-i \omega t} e^{-i \omega nT}dt\\
&=&\left( \int_{t=0}^{T} x(t) e^{-i \omega t}dt\right) \left( \sum_{n=-\infty}^{\infty} e^{-i \omega nT} \right)
\end{eqnarray} $$
We have to evaluate the left-hand paranthesis. We write it as
$$
\sum_{n=-\infty}^{\infty} e^{-i \omega nT} = \lim_{k \rightarrow \infty }\sum_{n=-k}^{k} e^{-i \omega nT}
$$
This is a geometric series with the sum
$$\begin{eqnarray}
\sum_{n=-k}^{k} e^{-i \omega nT} &=& e^{-i \omega kT}+e^{-i \omega (k-1)T}+\ldots+e^{-i \omega (k-1)T}+ e^{-i \omega kT}\\
&=& e^{-i \omega kT} \left(1+e^{i \omega T}+e^{i \omega 2T}+\ldots+e^{i \omega (2k-1)T}+ e^{i \omega 2kT}\right)\\
&=&e^{-i \omega kT} \frac{1-e^{(2k+1)i \omega T}}{1-e^{i \omega T}}
\end{eqnarray} $$

To ease the notation, let us define $r=e^{-i \omega T}$. Then, the above expression can be simplified as

$$\begin{eqnarray}
r^{-k}\frac{1-r^{2k+1}}{1-r}
&=& r^{-k} \frac{r^\frac{{2k+1}}{2}\left[r^{-\frac{{2k+1}}{2}}-r^\frac{{2k+1}}{2}\right]}{r^{\frac{1}{2}}\left[ r^{-\frac{1}{2}}-r^{\frac{1}{2}}\right]}\\
&=&\frac{r^{-\frac{{2k+1}}{2}}-r^\frac{{2k+1}}{2}}{ r^{-\frac{1}{2}}-r^{\frac{1}{2}}}
\end{eqnarray} $$

Substituting back $r=e^{-i \omega T}$,

$$\begin{eqnarray}
&=&\frac{e^{\frac{2k+1}{2}i \omega T}-e^{\frac{-{2k+1}}{2}i \omega T}}{ e^{\frac{i \omega T}{2}}-e^{-\frac{i \omega T}{2}}}\\\\
&=&\frac{\frac{e^{\frac{2k+1}{2}i \omega T}-e^{\frac{-{2k+1}}{2}i \omega T}}{2i}}{ \frac{e^{\frac{i \omega T}{2}}-e^{-\frac{i \omega T}{2}}}{2i}}\\\\
&=& \frac{\sin\left(\frac{2k+1}{2} \omega T\right)}{\sin\left(\frac{ \omega T}{2}\right)}
\end{eqnarray} $$

Or, in summary, we have proved that

$$\begin{eqnarray}
\sum_{n=-k}^{k} e^{-i \omega nT} &=& \frac{\sin\left(\frac{2k+1}{2} \omega T\right)}{\sin\left(\frac{ \omega T}{2}\right)}
\end{eqnarray} $$

]]>
/continuous-fourier-transforms/feed/ 0
Reference for Second Project /reference-for-second-project/ /reference-for-second-project/#respond Fri, 11 Sep 2020 08:06:54 +0000 /?p=579 Bird Instruction Format

Format for new instructions of Bird. (as discussed in the lecture)

Machine Code Format PUSH
Push r

Machine Code Format POP
POP r

Machine Code Format CALL
CALL x

Machine Code Format RET
RET

Main Module

//Main module


module main_module (
			output wire [3:0] rowwrite,
			input [3:0] colread,
			input clk,
			output wire [3:0] grounds,
			output wire [6:0] display,
			input pushbutton //may be used as clock
			);

reg [15:0] data_all;
wire [3:0] keyout;
reg [25:0] clk1;
reg [1:0] ready_buffer;
reg ack;
reg statusordata;

//memory map is defined here
localparam	BEGINMEM=12'h000,
		ENDMEM=12'h1ff,
		KEYPAD=12'h900,
		SEVENSEG=12'hb00;
//  memory chip
reg [15:0] memory [0:127]; 
 
// cpu's input-output pins
wire [15:0] data_out;
reg [15:0] data_in;
wire [11:0] address;
wire memwt;


sevensegment ss1 (//to be added);

keypad  kp1(//to be added);

bird br1 (//to be added);


//multiplexer for cpu input
always @*
	if ( (BEGINMEM<=address) && (address<=ENDMEM) )
		begin
			data_in=memory[address];
			ack=0;
			statusordata=0;
		end
	else if (address==KEYPAD+1)
		begin	
			statusordata=1;
			data_in=keyout;
			ack=0;
		end
	else if (address==KEYPAD)
		begin
			//to be added 
		end
	else
		begin
			data_in=16'hf345; //any number
			ack=0;
			statusordata=0;
		end

//multiplexer for cpu output 

always @(posedge clk) //data output port of the cpu
	if (memwt)
		if ( (BEGINMEM<=address) && (address<=ENDMEM) )
			memory[address]<=data_out;
		else if ( SEVENSEG==address) 
			data_all<=data_out;


initial 
	begin
		data_all=0;
		ack=0;
		statusordata=0;
		$readmemh("ram.dat", memory);
	end

endmodule

 

CPU Module

//bird CPU
module bird (
		input clk,
		input [15:0] data_in,
		output reg [15:0] data_out,
		output reg [11:0] address,
		output memwt
		);

reg [11:0] pc, ir; //program counter, instruction register

reg [4:0] state; //FSM
reg [15:0] regbank [7:0];//registers 
reg zeroflag; //zero flag register
reg [15:0] result; //output for result
 
 
localparam	FETCH=4'b0000,
		LDI=4'b0001, 
		LD=4'b0010,
		ST=4'b0011,
		JZ=4'b0100,
		JMP=4'b0101,
		ALU=4'b0111,
		PUSH=4'b1000,
		POP1=4'b1001,
		POP2=4'b1100,
		CALL=4'b1010,
		RET1=4'b1011,
		RET2=4'b1101;
 

wire zeroresult; 

always @(posedge clk)
	case(state) 
		FETCH: 
			begin
				if ( data_in[15:12]==JZ) // if instruction is jz  
					if (zeroflag)  //and if last bit of 7th register is 0 then jump to jump instruction state
						state <= JMP;
					else
						state <= FETCH; //stay here to catch next instruction
			else
				state <= data_in[15:12]; //read instruction opcode and jump the state of the instruction to be read
				ir<=data_in[11:0]; //read instruction details into instruction register
				pc<=pc+1; //increment program counter
			end

		LDI:
			begin
				regbank[ ir[2:0] ] <= data_in; //if inst is LDI get the destination register number from ir and move the data in it.
				pc<=pc+1; //for next instruction (32 bit instruction)  
				state <= FETCH;
			end

		LD:
			begin
				regbank[ir[2:0]] <= data_in;
				state <= FETCH;  
				end 
 
		ST:
			begin
				state <= FETCH;  
			end
 
		JMP:
			begin
				pc <= pc+ir;
				state <= FETCH;  
			end
 
		ALU:
			begin
				regbank[ir[2:0]]<=result;
				zeroflag<=zeroresult;
				state <= FETCH;
			end

		PUSH:
			begin
				 regbank[7]<=regbank[7]-1;
				 state <= FETCH;
			end

		POP1:
			begin
				//to be added
			end

		POP2: 
			begin
				//to be added
			end

		CALL: 
			begin
			        //to be added 
			end

		RET1:
			begin
				//to be added
			end

		RET2:
			begin
				//to be added 
			end

	endcase

always @*
	case (state)
		LD:	address=regbank[ir[5:3]][11:0];
		ST:	address=regbank[ir[5:3]][11:0];
		PUSH:	address=regbank[7];
		POP2:	//to be added
		CALL:	//to be added
		RET2:	//to be added
		default: address=pc;
	endcase
 
 
assign memwt=(state==ST)|| // to be added
 
always @*
	case (state)
		CALL: data_out = //to be added 
		default: data_out = regbank[ir[8:6]];
	endcase

always @* //ALU Operation
	case (ir[11:9])
		3'h0: result = regbank[ir[8:6]]+regbank[ir[5:3]]; //000
		3'h1: result = regbank[ir[8:6]]-regbank[ir[5:3]]; //001
		3'h2: result = regbank[ir[8:6]]&regbank[ir[5:3]]; //010
		3'h3: result = regbank[ir[8:6]]|regbank[ir[5:3]]; //011
		3'h4: result = regbank[ir[8:6]]^regbank[ir[5:3]]; //100
		3'h7: case (ir[8:6])
			3'h0: result = !regbank[ir[5:3]];
			3'h1: result = regbank[ir[5:3]];
			3'h2: result = regbank[ir[5:3]]+1;
			3'h3: result = regbank[ir[5:3]]-1;
			default: result=16'h0000;
		     endcase
		default: result=16'h0000;
	endcase
 
assign zeroresult = ~|result;

initial begin;
	state=FETCH;
	zeroflag=0;
	pc=0;
end

endmodule

Keypad Module

module keypad (
						output reg [3:0] rowwrite,
						input [3:0] colread,
						input clk,
						input ack,
						input statusordata,
						output reg [15:0] keyout
						);
wire keypressed;		
reg [25:0] clk1;
reg ready;
reg [3:0] keyread, data;
reg [3:0] rowpressed;
reg [3:0] pressedcol [0:3];
reg [11:0] rowpressed_buffer0, rowpressed_buffer1, rowpressed_buffer2, rowpressed_buffer3;
reg [3:0] rowpressed_debounced;

always @(posedge clk)
	clk1<=clk1+1;

always @(posedge clk1[15])
	rowwrite<={rowwrite[2:0], rowwrite[3]};

always @(posedge clk1[15])
	if (rowwrite== 4'b1110)
		begin
			rowpressed[0]<= ~(&colread); //colread=1111--> none of them pressed, colread=1110 --> 1, colread=1101-->2, 1011-->3, 0111->A
			pressedcol[0]<=colread;
		end
	else if (rowwrite==4'b1101)
		begin
			rowpressed[1]<= ~(&colread); //colread=1111--> none of them pressed, colread=1110 --> 4, colread=1101-->5, 1011-->6, 0111->B
			pressedcol[1]<=colread;
		end
	else if (rowwrite==4'b1011)
		begin
			rowpressed[2]<= ~(&colread); //colread=1111--> none of them pressed, colread=1110 --> 7, colread=1101-->8, 1011-->9, 0111->C
			pressedcol[2]<=colread;
		end
	else if (rowwrite==4'b0111)
		begin
			rowpressed[3]<= ~(&colread); //colread=1111--> none of them pressed, colread=1110 --> *(E), colread=1101-->0, 1011-->#(F), 0111->D
			pressedcol[3]<=colread;
		end
		
wire transition0_10;
wire transition0_01;

assign transition0_10=~|rowpressed_buffer0;
assign transition0_01=&rowpressed_buffer0;

wire transition1_10;
wire transition1_01;

assign transition1_10=~|rowpressed_buffer1;
assign transition1_01=&rowpressed_buffer1;

wire transition2_10;
wire transition2_01;

assign transition2_10=~|rowpressed_buffer2;
assign transition2_01=&rowpressed_buffer2;

wire transition3_10;
wire transition3_01;

assign transition3_10=~|rowpressed_buffer3; //kpd=1-->0
assign transition3_01=&rowpressed_buffer3;  //kpd=0-->1


always @(posedge clk1[15])
	begin
		rowpressed_buffer0<= {rowpressed_buffer0[10:0],rowpressed[0]};
		if (rowpressed_debounced[0]==0 && transition0_01)
			rowpressed_debounced[0]<=1;
		if (rowpressed_debounced[0]==1 && transition0_10)
			rowpressed_debounced[0]<=0;
	
	rowpressed_buffer1<= {rowpressed_buffer1[10:0],rowpressed[1]};
		if (rowpressed_debounced[1]==0 && transition1_01)
			rowpressed_debounced[1]<=1;
		if (rowpressed_debounced[1]==1 && transition1_10)
			rowpressed_debounced[1]<=0;
			
	rowpressed_buffer2<= {rowpressed_buffer2[10:0],rowpressed[2]};
		if (rowpressed_debounced[2]==0 && transition2_01)
			rowpressed_debounced[2]<=1;
		if (rowpressed_debounced[2]==1 && transition2_10)
			rowpressed_debounced[2]<=0;
	
	rowpressed_buffer3<= {rowpressed_buffer3[10:0],rowpressed[3]};
		if (rowpressed_debounced[3]==0 && transition3_01)
			rowpressed_debounced[3]<=1;
		if (rowpressed_debounced[3]==1 && transition3_10)
			rowpressed_debounced[3]<=0;
	end 

always @*
	begin
		if (rowpressed_debounced[0]==1)
			begin
				if (pressedcol[0]==4'b1110)
					keyread=4'h1;
				else if (pressedcol[0]==4'b1101)
					keyread=4'h2;
				else if (pressedcol[0]==4'b1011)
					keyread=4'h3;
				else if (pressedcol[0]==4'b0111)
					keyread=4'hA;
				else keyread=4'b0000;
			end
		else if (rowpressed_debounced[1]==1)
			begin
				if (pressedcol[1]==4'b1110)
					keyread=4'h4;
				else if (pressedcol[1]==4'b1101)
					keyread=4'h5;
				else if (pressedcol[1]==4'b1011)
					keyread=4'h6;
				else if (pressedcol[1]==4'b0111)
					keyread=4'hB;
				else keyread=4'b0000;
			end
		else if (rowpressed_debounced[2]==1)
			begin
				if (pressedcol[2]==4'b1110)
					keyread=4'h7;
				else if (pressedcol[2]==4'b1101)
					keyread=4'h8;
				else if (pressedcol[2]==4'b1011)
					keyread=4'h9;
				else if (pressedcol[2]==4'b0111)
					keyread=4'hC;
				else keyread=4'b0000;
			end
		else if (rowpressed_debounced[3]==1)
			begin
				if (pressedcol[3]==4'b1110)
					keyread=4'hE;
				else if (pressedcol[3]==4'b1101)
					keyread=4'h0;
				else if (pressedcol[3]==4'b1011)
					keyread=4'hF;
				else if (pressedcol[3]==4'b0111)
					keyread=4'hD;
				else keyread=4'b0000;
			end
		else keyread=4'b0000;
	end //always


assign keypressed= rowpressed_debounced[0]||rowpressed_debounced[1]||rowpressed_debounced[2]||rowpressed_debounced[3];

reg [1:0] keypressed_buffer; //yeni karakter için parmağı çekip tekrar basmamız için gerekli

always @(posedge clk)
	keypressed_buffer<={keypressed_buffer[0],keypressed};

always @(posedge clk)
	if ((keypressed_buffer==2'b01)&&(ready==0))
		begin
			data<=keyread;
			ready<=1;
		end
	else if ((ack==1)&&(ready==1))
		ready<=0;
	
always @(*)
	if (statusordata==1)
		keyout={15'b0,ready};
	else
		keyout={12'b0,data};
	
initial 
	begin
		rowwrite=4'b1110;		
		ready=0;
	end
endmodule

 

Seven Segment Display Module

module sevensegment(datain, grounds, display, clk);

	input wire [15:0] datain;
	output reg [3:0] grounds;
	output reg [6:0] display;
	input clk;
	
	reg [3:0] data [3:0];
	reg [1:0] count;
	reg [25:0] clk1;
	
	always @(posedge clk1[15])
		begin
			grounds <= {grounds[2:0],grounds[3]};
			count <= count + 1;
		end
	
	always @(posedge clk)
		clk1 <= clk1 + 1;
	
	always @(*)
		case(data[count])	
			0:display=7'b1111110; //starts with a, ends with g
			1:display=7'b0110000;
			2:display=7'b1101101;
			3:display=7'b1111001;
			4:display=7'b0110011;
			5:display=7'b1011011;
			6:display=7'b1011111;
			7:display=7'b1110000;
			8:display=7'b1111111;
			9:display=7'b1111011;
			'ha:display=7'b1110111;
			'hb:display=7'b0011111;
			'hc:display=7'b1001110;
			'hd:display=7'b0111101;
			'he:display=7'b1001111;
			'hf:display=7'b1000111;
			default display=7'b1111111;
		endcase
	
	always @*
		begin
			data[0] = datain[15:12];
			data[1] = datain[11:8];
			data[2] = datain[7:4];
			data[3] = datain[3:0];
		end
	
	initial begin		
		count = 2'b0;
		grounds = 4'b1110;
		clk1 = 0;
	end
endmodule

 

Bird Assembler

// to compile, gcc assembler.c -o assembler
// No error check is provided.
// Variable names cannot start with numeric characters, ie, with 0-9.
// hexadecimals are twos complement.
// first address of the code section is zero, and the data section follows the code section in memory.
// four tables are formed: jump table, ldi table, label table and variable table.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


//Converts a hexadecimal string to integer.
int hex2int( char* hex)
{
    int result=0;

    while ((*hex)!='\0')
    {
        if (('0'<=(*hex))&&((*hex)<='9'))
            result = result*16 + (*hex) -'0';
        else if (('a'<=(*hex))&&((*hex)<='f'))
            result = result*16 + (*hex) -'a'+10;
        else if (('A'<=(*hex))&&((*hex)<='F'))
            result = result*16 + (*hex) -'A'+10;
        hex++;
    }
    return(result);
}


main()
{
    FILE *fp;
    char line[100];
    char *token = NULL;
    char *op1, *op2, *op3, *label;
    char ch;
    int  chch;

    int program[1000];
    int counter=0;  //holds the address of the machine code instruction


    struct label_or_variable
    {
        int location;
        char *name;
    };

// A label is a symbol which mark a location within the code section. In the example
// program above, the strings "lpp", "loop" and "lp1" are labels.
// In reptile, labels are used by jump, jz and ldi instructions.
    struct label_or_variable labeltable[50]; //there can be 50 labels at most in our programs
    int nooflabels = 0;                       //number of labels encountered during assembly.

 // A variable is a symbol which mark a location within the data section. In the example
// program above, the strings "", "" and "" are variables.
// In reptile, variables are used by ldi instructions.
    struct label_or_variable variabletable[50]; // The list of variables in .data section and their locations.
    int noofvariables = 0;    //number of jumps encountered during assembly.

// Jump instructions cannot be assembled readily because we may not know the value of
// the label when we encountered a jump instruction. This happens if the label used by
// that jump instruction appear below that jump instruction. This is the situation
// with the label "loop" in the example program above. Hence, the location of jump
// instructions must be stored.
    struct label_or_variable jumptable[100]; //There can be at most 100 jumps
    int noofjumps=0;                        //number of jump instructions encountered during assembly.


//Variables and labels are used by ldi instructions.
//The memory for the variables are traditionally allocated at the end of the code section.
//Hence their addresses are not known when we assemble a ldi instruction. Also, the value of
//a label may not be known when we encounter a ldi instruction which uses that label.
//Hence, the location of the ldi instructions must be kept, and these instructions must be
//modified when we discover the address of the label or variable that it uses.
    struct label_or_variable lditable[100];
    int noofldis=0;



    fp = fopen("code.txt","r");

    if (fp != NULL)
    {
        while(fgets(line,sizeof line,fp)!= NULL)  //skip till .code section
        {
            token=strtok(line,"\n\t\r ");
            if (strcmp(token,".code")==0 )
                break;
        }
        while(fgets(line,sizeof line,fp)!= NULL)
        {
            token=strtok(line,"\n\t\r ");  //get the instruction mnemonic or label

//========================================   FIRST PASS  ======================================================
            while (token)
            {
                if (strcmp(token,"ldi")==0)        //---------------LDI INSTRUCTION--------------------
                {
                    op1 = strtok(NULL,"\n\t\r ");                                //get the 1st operand of ldi, which is the register that ldi loads
                    op2 = strtok(NULL,"\n\t\r ");                                //get the 2nd operand of ldi, which is the data that is to be loaded
                    program[counter]=0x1000+hex2int(op1);                        //generate the first 16-bit of the ldi instruction
                    counter++;                                                   //move to the second 16-bit of the ldi instruction
                    if ((op2[0]=='0')&&(op2[1]=='x'))                            //if the 2nd operand is twos complement hexadecimal
                        program[counter]=hex2int(op2+2)&0xffff;              //convert it to integer and form the second 16-bit
                    else if ((  (op2[0])=='-') || ((op2[0]>='0')&&(op2[0]<='9')))       //if the 2nd operand is decimal
                        program[counter]=atoi(op2)&0xffff;                         //convert it to integer and form the second 16-bit
                    else                                                           //if the second operand is not decimal or hexadecimal, it is a laber or a variable.
                    {                                                               //in this case, the 2nd 16-bits of the ldi instruction cannot be generated.
                        lditable[noofldis].location = counter;                 //record the location of this 2nd 16-bit
                        op1=(char*)malloc(sizeof(op2));                         //and the name of the label/variable that it must contain
                        strcpy(op1,op2);                                        //in the lditable array.
                        lditable[noofldis].name = op1;
                        noofldis++;
                    }
                    counter++;                                                     //skip to the next memory location
                }

                else if (strcmp(token,"ld")==0)      //------------LD INSTRUCTION---------------------
                {
                    op1 = strtok(NULL,"\n\t\r ");                //get the 1st operand of ld, which is the destination register
                    op2 = strtok(NULL,"\n\t\r ");                //get the 2nd operand of ld, which is the source register
                    ch = (op1[0]-48)| ((op2[0]-48) << 3);        //form bits 11-0 of machine code. 48 is ASCII value of '0'
                    program[counter]=0x2000+((ch)&0x00ff);       //form the instruction and write it to memory
                    counter++;                                   //skip to the next empty location in memory
                }
                else if (strcmp(token,"st")==0) //-------------ST INSTRUCTION--------------------
                {
                    op1 = strtok(NULL,"\n\t\r ");                //get the 1st operand of ld, which is the destination register
                    op2 = strtok(NULL,"\n\t\r ");                //get the 2nd operand of ld, which is the source register
                    chch = (op1[0]-48)<<3| ((op2[0]-48) << 6);        //form bits 11-0 of machine code. 48 is ASCII value of '0'
                    program[counter]=0x3000+((chch)&0x01ff);       //form the instruction and write it to memory
                    counter++;                                   //skip to the next empty location in memory
                    
                }
                else if (strcmp(token,"jz")==0) //------------- CONDITIONAL JUMP ------------------
                {
                    op1 = strtok(NULL,"\n\t\r ");            //read the label string
                    jumptable[noofjumps].location = counter;    //write the jz instruction's location into the jumptable
                    op2=(char*)malloc(sizeof(op1));         //allocate space for the label
                    strcpy(op2,op1);                //copy the label into the allocated space
                    jumptable[noofjumps].name=op2;            //point to the label from the jumptable
                    noofjumps++;                    //skip to the next empty location in jumptable
                    program[counter]=0x4000;            //write the incomplete instruction (just opcode) to memory
                    counter++;
                    
                }
                else if (strcmp(token,"jmp")==0)  //-------------- JUMP -----------------------------
                {
                    op1 = strtok(NULL,"\n\t\r ");            //read the label string
                    jumptable[noofjumps].location = counter;    //write the jz instruction's location into the jumptable
                    op2=(char*)malloc(sizeof(op1));         //allocate space for the label
                    strcpy(op2,op1);                //copy the label into the allocated space
                    jumptable[noofjumps].name=op2;            //point to the label from the jumptable
                    noofjumps++;                    //skip to the next empty location in jumptable
                    program[counter]=0x5000;            //write the incomplete instruction (just opcode) to memory
                    counter++;                    //skip to the next empty location in memory.
                }
                else if (strcmp(token,"add")==0) //----------------- ADD -------------------------------
                {
                    op1 = strtok(NULL,"\n\t\r ");
                    op2 = strtok(NULL,"\n\t\r ");
                    op3 = strtok(NULL,"\n\t\r ");
                    chch = (op1[0]-48)| ((op2[0]-48)<<6)|((op3[0]-48)<<3);
                    program[counter]=0x7000+((chch)&0x01ff);
                    counter++;
                }
                else if (strcmp(token,"sub")==0)
                {
                     //to be added
                }
                else if (strcmp(token,"and")==0)
                {
                    //to be added
                }
                else if (strcmp(token,"or")==0)
                {
                      //to be added
                }
                else if (strcmp(token,"xor")==0)
                {
                    //to be added
                }
                else if (strcmp(token,"not")==0)
                {
                    op1 = strtok(NULL,"\n\t\r ");
                    op2 = strtok(NULL,"\n\t\r ");
                    ch = (op1[0]-48)| ((op2[0]-48)<<3);
                    program[counter]=0x7E00+((ch)&0x00ff);
                    counter++;
                }
                else if (strcmp(token,"mov")==0)
                {
                    //to be added
                }
                else if (strcmp(token,"inc")==0)
                {
                    op1 = strtok(NULL,"\n\t\r ");
                    ch = (op1[0]-48)| ((op1[0]-48)<<3);
                    program[counter]=0x7E80+((ch)&0x00ff);
                    counter++;
                }
                else if (strcmp(token,"dec")==0)
                {
                     //to be added
                }
                else if (strcmp(token,"push")==0)
                {
                      //to be added
                }
                else if (strcmp(token,"pop")==0)
                {
                      //to be added
                }
                else if (strcmp(token,"call")==0)  //-------------- CALL -----------------------------
                {
                    //to be added
                }
                else if (strcmp(token,"ret")==0)
                {
                    //to be added
                }
                else //------WHAT IS ENCOUNTERED IS NOT AN INSTRUCTION BUT A LABEL. UPDATE THE LABEL TABLE--------
                {
                    labeltable[nooflabels].location = counter;  //read the label and update labeltable.
                    op1=(char*)malloc(sizeof(token));
                    strcpy(op1,token);
                    labeltable[nooflabels].name=op1;
                    nooflabels++;
                }
                token = strtok(NULL,",\n\t\r ");  // if what is read before is an instruction, this will be NULL
                                                  //if what is read before is an label, this will be an opcode.
            }
        }


//================================= SECOND PASS ==============================

//supply the address fields of the jump and jz instructions by matching jumptable and labeltable
        int i,j;
        for (i=0; i<noofjumps;i++)   //for all jump/jz instructions encountered
        {
            j=0;
            while ((j<nooflabels)&&( strcmp(jumptable[i].name , labeltable[j].name ) != 0 ))  //if the label for this jump/jz does not match with the
                j++;                                            // jth label in the labeltable, check the next label..
            program[jumptable[i].location] +=(labeltable[j].location-jumptable[i].location-1)&0x0fff;       //copy the jump address into memory.
        }


//search for the start of the .data segment
        rewind(fp);
        while(fgets(line,sizeof line,fp)!= NULL)  //skip till .data, if no .data, also ok.
        {
            token=strtok(line,"\n\t\r ");
            if (strcmp(token,".data")==0 )
                break;

        }

// process the .data segment and generate the variabletable[] array.
        int dataarea=0;
         while(fgets(line,sizeof line,fp)!= NULL)
        {
            token=strtok(line,"\n\t\r ");
            if (strcmp(token,".code")==0 )  //go till the .code segment
                break;
            else if (token[strlen(token)-1]==':')
            {
                token[strlen(token)-1]='\0';  //will not cause memory leak, as we do not do malloc
                variabletable[noofvariables].location=counter+dataarea;
                op1=(char*)malloc(sizeof(token));
                strcpy(op1,token);
                variabletable[noofvariables].name=op1;
                token = strtok(NULL,",\n\t\r ");
                if (token==NULL)
                    program[counter+dataarea]=0;
                else if (strcmp(token, ".space")==0)
                {
                    token=strtok(NULL,"\n\t\r ");
                    dataarea+=atoi(token);
                }
                else if((token[0]=='0')&&(token[1]=='x'))
                    program[counter+dataarea]=hex2int(token+2)&0xffff;
                else if ((  (token[0])=='-') || ('0'<=(token[0])&&(token[0]<='9'))  )
                    program[counter+dataarea]=atoi(token)&0xffff;
                noofvariables++;
                dataarea++;
            }
        }


// supply the address fields for the ldi instructions from the variable table
        for( i=0; i<noofldis;i++)
        {
            j=0;
            while ((j<noofvariables)&&( strcmp( lditable[i].name , variabletable[j].name)!=0 ))
                j++;
            if (j<noofvariables)
                program[lditable[i].location] = variabletable[j].location;
        }


// supply the address fields for the ldi instructions from the label table
        for( i=0; i<noofldis;i++)
        {
            j=0;
            while ((j<nooflabels)&&( strcmp( lditable[i].name , labeltable[j].name)!=0 ))
                j++;
            if (j<nooflabels){
                program[lditable[i].location] = (labeltable[j].location)&0x0fff;
                printf("%d %d %d\n", i, j, (labeltable[j].location));
            }
        }


//display the resulting tables
        printf("LABEL TABLE\n");
        for (i=0;i<nooflabels;i++)
            printf("%d %s\n", labeltable[i].location, labeltable[i].name);
        printf("\n");
        printf("JUMP TABLE\n");
        for (i=0;i<noofjumps;i++)
            printf("%d %s\n", jumptable[i].location, jumptable[i].name);
        printf("\n");
        printf("VARIABLE TABLE\n");
        for (i=0;i<noofvariables;i++)
            printf("%d %s\n", variabletable[i].location, variabletable[i].name);
        printf("\n");
        printf("LDI INSTRUCTIONS\n");
        for (i=0;i<noofldis;i++)
            printf("%d %s\n", lditable[i].location, lditable[i].name);
        printf("\n");
        fclose(fp);
        fp = fopen("RAM","w");
        fprintf(fp,"v2.0 raw\n");
        for (i=0;i<counter+dataarea;i++)
            fprintf(fp,"%04x\n",program[i]);
        fclose(fp);
        fp = fopen("ram.dat","w");
        for (i=0;i<counter+dataarea;i++)
            fprintf(fp, "%04x\n", program[i]);
    }
}

 

 

 

]]>
/reference-for-second-project/feed/ 0
Bird: IO Design /bird-io-design/ /bird-io-design/#respond Thu, 10 Sep 2020 18:34:21 +0000 /?p=563 Bird Instruction Format

Machine Code Format PUSH
Push r

Machine Code Format POP
POP r

Machine Code Format CALL
CALL x

Machine Code Format RET
RET

Main Module

//Main module

module main_module (
			output wire [3:0] rowwrite,
			input [3:0] colread,
			input clk,
			output wire [3:0] grounds,
			output wire [6:0] display,
			input pushbutton //may be used as clock
			);
reg [15:0] data_all;
wire [3:0] keyout;
reg [25:0] clk1;
reg [1:0] ready_buffer;
reg ack;
reg statusordata;

//memory map is defined here
localparam	BEGINMEM=12'h000,
		ENDMEM=12'h1ff,
		KEYPAD=12'h900,
		SEVENSEG=12'hb00;
//  memory chip
reg [15:0] memory [0:127]; 
 
// cpu's input-output pins
wire [15:0] data_out;
reg [15:0] data_in;
wire [11:0] address;
wire memwt;


sevensegment ss1 (.datain(data_all), .grounds(grounds), .display(display), .clk(clk));

keypad_ex  kp1(.rowwrite(rowwrite),.colread(colread),.clk(clk),.keyout(keyout),.statusordata(statusordata),.ack(ack));

bird br1 (.data_in(data_in), .data_out(data_out), .clk(~pushbutton), .memwt(memwt), .address(address));


//multiplexer for cpu input
always @*
	if ( (BEGINMEM<=address) && (address<=ENDMEM) )
		begin
			data_in=memory[address];
			ack=0;
			statusordata=0;
		end
	else if (address==KEYPAD+1)
		begin	
			statusordata=1;
			data_in=keyout;
			ack=0;
		end
	else if (address==KEYPAD)
		begin
			data_in=keyout;
			statusordata=0;
			ack=1;
		end
	else
		begin
			data_in=16'hf345; //any number
			ack=0;
			statusordata=0;
		end

//multiplexer for cpu output 

always @(posedge clk) //data output port of the cpu
	if (memwt)
		if ( (BEGINMEM<=address) && (address<=ENDMEM) )
			memory[address]<=data_out;
		else if ( SEVENSEG==address) 
			data_all<=data_out;


initial 
	begin
		data_all=0;
		ack=0;
		statusordata=0;
		$readmemh("ram.dat", memory);
	end

endmodule

 

CPU Module

//bird CPU
module bird (
		input clk,
		input [15:0] data_in,
		output reg [15:0] data_out,
		output reg [11:0] address,
		output memwt
		);

reg [11:0] pc, ir; //program counter, instruction register

reg [4:0] state; //FSM
reg [15:0] regbank [7:0];//registers 
reg zeroflag; //zero flag register
reg [15:0] result; //output for result
 
 
localparam	FETCH=4'b0000,
		LDI=4'b0001, 
		LD=4'b0010,
		ST=4'b0011,
		JZ=4'b0100,
		JMP=4'b0101,
		ALU=4'b0111,
		PUSH=4'b1000,
		POP1=4'b1001,
		POP2=4'b1100,
		CALL=4'b1010,
		RET1=4'b1011,
		RET2=4'b1101;
 

wire zeroresult; 

always @(posedge clk)
	case(state) 
		FETCH: 
			begin
				if ( data_in[15:12]==JZ) // if instruction is jz  
					if (zeroflag)  //and if last bit of 7th register is 0 then jump to jump instruction state
						state <= JMP;
					else
						state <= FETCH; //stay here to catch next instruction
			else
				state <= data_in[15:12]; //read instruction opcode and jump the state of the instruction to be read
				ir<=data_in[11:0]; //read instruction details into instruction register
				pc<=pc+1; //increment program counter
			end

		LDI:
			begin
				regbank[ ir[2:0] ] <= data_in; //if inst is LDI get the destination register number from ir and move the data in it.
				pc<=pc+1; //for next instruction (32 bit instruction)  
				state <= FETCH;
			end

		LD:
			begin
				regbank[ir[2:0]] <= data_in;
				state <= FETCH;  
				end 
 
		ST:
			begin
				state <= FETCH;  
			end
 
		JMP:
			begin
				pc <= pc+ir;
				state <= FETCH;  
			end
 
		ALU:
			begin
				regbank[ir[2:0]]<=result;
				zeroflag<=zeroresult;
				state <= FETCH;
			end

		PUSH:
			begin
				 regbank[7]<=regbank[7]-1;
				 state <= FETCH;
			end

		POP1:
			begin
				regbank[7]<=regbank[7]+1;
				state <= POP2;
			end

		POP2: //actually unnecessary
			begin
				regbank[ir[2:0]] <= data_in;
				state <= FETCH; 
			end

		CALL: 
			begin
				regbank[7]<=regbank[7]-1;
				pc<=pc+ir;
				state <= FETCH; 
			end

		RET1:
			begin
				regbank[7]<=regbank[7]+1;
				state <= RET2;
			end

		RET2:
			begin
				pc<=data_in[11:0];
				state <= FETCH; 
			end

	endcase

always @*
	case (state)
		LD:	address=regbank[ir[5:3]][11:0];
		ST:	address=regbank[ir[5:3]][11:0];
		PUSH:	address=regbank[7];
		POP2:	address=regbank[7];
		CALL:	address=regbank[7];
		RET2:	address=regbank[7];
		default: address=pc;
	endcase
 
 
assign memwt=(state==ST)||(state==PUSH)||(state==CALL);
 
always @*
	case (state)
		CALL: data_out = {4'b0,pc};
		default: data_out = regbank[ir[8:6]];
	endcase

always @* //ALU Operation
	case (ir[11:9])
		3'h0: result = regbank[ir[8:6]]+regbank[ir[5:3]]; //000
		3'h1: result = regbank[ir[8:6]]-regbank[ir[5:3]]; //001
		3'h2: result = regbank[ir[8:6]]&regbank[ir[5:3]]; //010
		3'h3: result = regbank[ir[8:6]]|regbank[ir[5:3]]; //011
		3'h4: result = regbank[ir[8:6]]^regbank[ir[5:3]]; //100
		3'h7: case (ir[8:6])
			3'h0: result = !regbank[ir[5:3]];
			3'h1: result = regbank[ir[5:3]];
			3'h2: result = regbank[ir[5:3]]+1;
			3'h3: result = regbank[ir[5:3]]-1;
			default: result=16'h0000;
		     endcase
		default: result=16'h0000;
	endcase
 
assign zeroresult = ~|result;

initial begin;
	state=FETCH;
	zeroflag=0;
	pc=0;
end

endmodule

Bird Assembler

// to compile, gcc assembler.c -o assembler
// No error check is provided.
// Variable names cannot start with numeric characters, ie, with 0-9.
// hexadecimals are twos complement.
// first address of the code section is zero, and the data section follows the code section in memory.
// four tables are formed: jump table, ldi table, label table and variable table.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


//Converts a hexadecimal string to integer.
int hex2int( char* hex)
{
    int result=0;

    while ((*hex)!='\0')
    {
        if (('0'<=(*hex))&&((*hex)<='9'))
            result = result*16 + (*hex) -'0';
        else if (('a'<=(*hex))&&((*hex)<='f'))
            result = result*16 + (*hex) -'a'+10;
        else if (('A'<=(*hex))&&((*hex)<='F'))
            result = result*16 + (*hex) -'A'+10;
        hex++;
    }
    return(result);
}


main()
{
    FILE *fp;
    char line[100];
    char *token = NULL;
    char *op1, *op2, *op3, *label;
    char ch;
    int  chch;

    int program[1000];
    int counter=0;  //holds the address of the machine code instruction


    struct label_or_variable
    {
        int location;
        char *name;
    };

// A label is a symbol which mark a location within the code section. In the example
// program above, the strings "lpp", "loop" and "lp1" are labels.
// In reptile, labels are used by jump, jz and ldi instructions.
    struct label_or_variable labeltable[50]; //there can be 50 labels at most in our programs
    int nooflabels = 0;                       //number of labels encountered during assembly.

 // A variable is a symbol which mark a location within the data section. In the example
// program above, the strings "", "" and "" are variables.
// In reptile, variables are used by ldi instructions.
    struct label_or_variable variabletable[50]; // The list of variables in .data section and their locations.
    int noofvariables = 0;    //number of jumps encountered during assembly.

// Jump instructions cannot be assembled readily because we may not know the value of
// the label when we encountered a jump instruction. This happens if the label used by
// that jump instruction appear below that jump instruction. This is the situation
// with the label "loop" in the example program above. Hence, the location of jump
// instructions must be stored.
    struct label_or_variable jumptable[100]; //There can be at most 100 jumps
    int noofjumps=0;                        //number of jump instructions encountered during assembly.


//Variables and labels are used by ldi instructions.
//The memory for the variables are traditionally allocated at the end of the code section.
//Hence their addresses are not known when we assemble a ldi instruction. Also, the value of
//a label may not be known when we encounter a ldi instruction which uses that label.
//Hence, the location of the ldi instructions must be kept, and these instructions must be
//modified when we discover the address of the label or variable that it uses.
    struct label_or_variable lditable[100];
    int noofldis=0;



    fp = fopen("code.txt","r");

    if (fp != NULL)
    {
        while(fgets(line,sizeof line,fp)!= NULL)  //skip till .code section
        {
            token=strtok(line,"\n\t\r ");
            if (strcmp(token,".code")==0 )
                break;
        }
        while(fgets(line,sizeof line,fp)!= NULL)
        {
            token=strtok(line,"\n\t\r ");  //get the instruction mnemonic or label

//========================================   FIRST PASS  ======================================================
            while (token)
            {
                if (strcmp(token,"ldi")==0)        //---------------LDI INSTRUCTION--------------------
                {
                    op1 = strtok(NULL,"\n\t\r ");                                //get the 1st operand of ldi, which is the register that ldi loads
                    op2 = strtok(NULL,"\n\t\r ");                                //get the 2nd operand of ldi, which is the data that is to be loaded
                    program[counter]=0x1000+hex2int(op1);                        //generate the first 16-bit of the ldi instruction
                    counter++;                                                   //move to the second 16-bit of the ldi instruction
                    if ((op2[0]=='0')&&(op2[1]=='x'))                            //if the 2nd operand is twos complement hexadecimal
                        program[counter]=hex2int(op2+2)&0xffff;              //convert it to integer and form the second 16-bit
                    else if ((  (op2[0])=='-') || ((op2[0]>='0')&&(op2[0]<='9')))       //if the 2nd operand is decimal
                        program[counter]=atoi(op2)&0xffff;                         //convert it to integer and form the second 16-bit
                    else                                                           //if the second operand is not decimal or hexadecimal, it is a laber or a variable.
                    {                                                               //in this case, the 2nd 16-bits of the ldi instruction cannot be generated.
                        lditable[noofldis].location = counter;                 //record the location of this 2nd 16-bit
                        op1=(char*)malloc(sizeof(op2));                         //and the name of the label/variable that it must contain
                        strcpy(op1,op2);                                        //in the lditable array.
                        lditable[noofldis].name = op1;
                        noofldis++;
                    }
                    counter++;                                                     //skip to the next memory location
                }

                else if (strcmp(token,"ld")==0)      //------------LD INSTRUCTION---------------------
                {
                    op1 = strtok(NULL,"\n\t\r ");                //get the 1st operand of ld, which is the destination register
                    op2 = strtok(NULL,"\n\t\r ");                //get the 2nd operand of ld, which is the source register
                    ch = (op1[0]-48)| ((op2[0]-48) << 3);        //form bits 11-0 of machine code. 48 is ASCII value of '0'
                    program[counter]=0x2000+((ch)&0x00ff);       //form the instruction and write it to memory
                    counter++;                                   //skip to the next empty location in memory
                }
                else if (strcmp(token,"st")==0) //-------------ST INSTRUCTION--------------------
                {
                    op1 = strtok(NULL,"\n\t\r ");                //get the 1st operand of ld, which is the destination register
                    op2 = strtok(NULL,"\n\t\r ");                //get the 2nd operand of ld, which is the source register
                    chch = (op1[0]-48)<<3| ((op2[0]-48) << 6);        //form bits 11-0 of machine code. 48 is ASCII value of '0'
                    program[counter]=0x3000+((chch)&0x01ff);       //form the instruction and write it to memory
                    counter++;                                   //skip to the next empty location in memory
                    //to be added
                }
                else if (strcmp(token,"jz")==0) //------------- CONDITIONAL JUMP ------------------
                {
                    op1 = strtok(NULL,"\n\t\r ");            //read the label string
                    jumptable[noofjumps].location = counter;    //write the jz instruction's location into the jumptable
                    op2=(char*)malloc(sizeof(op1));         //allocate space for the label
                    strcpy(op2,op1);                //copy the label into the allocated space
                    jumptable[noofjumps].name=op2;            //point to the label from the jumptable
                    noofjumps++;                    //skip to the next empty location in jumptable
                    program[counter]=0x4000;            //write the incomplete instruction (just opcode) to memory
                    counter++;
                    //to be added
                }
                else if (strcmp(token,"jmp")==0)  //-------------- JUMP -----------------------------
                {
                    op1 = strtok(NULL,"\n\t\r ");            //read the label string
                    jumptable[noofjumps].location = counter;    //write the jz instruction's location into the jumptable
                    op2=(char*)malloc(sizeof(op1));         //allocate space for the label
                    strcpy(op2,op1);                //copy the label into the allocated space
                    jumptable[noofjumps].name=op2;            //point to the label from the jumptable
                    noofjumps++;                    //skip to the next empty location in jumptable
                    program[counter]=0x5000;            //write the incomplete instruction (just opcode) to memory
                    counter++;                    //skip to the next empty location in memory.
                }
                else if (strcmp(token,"add")==0) //----------------- ADD -------------------------------
                {
                    op1 = strtok(NULL,"\n\t\r ");
                    op2 = strtok(NULL,"\n\t\r ");
                    op3 = strtok(NULL,"\n\t\r ");
                    chch = (op1[0]-48)| ((op2[0]-48)<<6)|((op3[0]-48)<<3);
                    program[counter]=0x7000+((chch)&0x01ff);
                    counter++;
                }
                else if (strcmp(token,"sub")==0)
                {
                    op1 = strtok(NULL,"\n\t\r ");
                    op2 = strtok(NULL,"\n\t\r ");
                    op3 = strtok(NULL,"\n\t\r ");
                    chch = (op1[0]-48)| ((op2[0]-48)<<6)|((op3[0]-48)<<3);
                    program[counter]=0x7200+((chch)&0x01ff);
                    counter++;
                    //to be added
                }
                else if (strcmp(token,"and")==0)
                {
                    op1 = strtok(NULL,"\n\t\r ");
                    op2 = strtok(NULL,"\n\t\r ");
                    op3 = strtok(NULL,"\n\t\r ");
                    chch = (op1[0]-48)| ((op2[0]-48)<<6)|((op3[0]-48)<<3);
                    program[counter]=0x7400+((chch)&0x01ff);
                    counter++;
                    //to be added
                }
                else if (strcmp(token,"or")==0)
                {
                    op1 = strtok(NULL,"\n\t\r ");
                    op2 = strtok(NULL,"\n\t\r ");
                    op3 = strtok(NULL,"\n\t\r ");
                    chch = (op1[0]-48)| ((op2[0]-48)<<6)|((op3[0]-48)<<3);
                    program[counter]=0x7600+((chch)&0x01ff);
                    counter++;//to be added
                }
                else if (strcmp(token,"xor")==0)
                {
                    op1 = strtok(NULL,"\n\t\r ");
                    op2 = strtok(NULL,"\n\t\r ");
                    op3 = strtok(NULL,"\n\t\r ");
                    chch = (op1[0]-48)| ((op2[0]-48)<<6)|((op3[0]-48)<<3);
                    program[counter]=0x7800+((chch)&0x01ff);
                    counter++;
                    //to be added
                }
                else if (strcmp(token,"not")==0)
                {
                    op1 = strtok(NULL,"\n\t\r ");
                    op2 = strtok(NULL,"\n\t\r ");
                    ch = (op1[0]-48)| ((op2[0]-48)<<3);
                    program[counter]=0x7E00+((ch)&0x00ff);
                    counter++;
                }
                else if (strcmp(token,"mov")==0)
                {
                    op1 = strtok(NULL,"\n\t\r ");
                    op2 = strtok(NULL,"\n\t\r ");
                    ch = (op1[0]-48)| ((op2[0]-48)<<3);
                    program[counter]=0x7E40+((ch)&0x00ff);
                    counter++;
                    //to be added
                }
                else if (strcmp(token,"inc")==0)
                {
                    op1 = strtok(NULL,"\n\t\r ");
                    ch = (op1[0]-48)| ((op1[0]-48)<<3);
                    program[counter]=0x7E80+((ch)&0x00ff);
                    counter++;
                }
                else if (strcmp(token,"dec")==0)
                {
                    op1 = strtok(NULL,"\n\t\r ");
                    ch = (op1[0]-48)| ((op1[0]-48)<<3);
                    program[counter]=0x7EC0+((ch)&0x00ff);
                    counter++;                   //to be added
                }
                else if (strcmp(token,"push")==0)
                {
                    op1 = strtok(NULL,"\n\t\r ");
                    ch =((op1[0]-48)<<3);
                    program[counter]=0x8000+((ch)&0x003f);
                    counter++;                   //to be added
                }
                else if (strcmp(token,"pop")==0)
                {
                    op1 = strtok(NULL,"\n\t\r ");
                    ch =(op1[0]-48);
                    program[counter]=0x9000+((ch)&0x000f);
                    counter++;                   //to be added
                }
                else if (strcmp(token,"call")==0)  //-------------- CALL -----------------------------
                {
                    op1 = strtok(NULL,"\n\t\r ");            //read the label string
                    jumptable[noofjumps].location = counter;    //write the jz instruction's location into the jumptable
                    op2=(char*)malloc(sizeof(op1));         //allocate space for the label
                    strcpy(op2,op1);                //copy the label into the allocated space
                    jumptable[noofjumps].name=op2;            //point to the label from the jumptable
                    noofjumps++;                    //skip to the next empty location in jumptable
                    program[counter]=0xA000;            //write the incomplete instruction (just opcode) to memory
                    counter++;                    //skip to the next empty location in memory.
                }
                else if (strcmp(token,"ret")==0)
                {
                    program[counter]=0xB000;
                    counter++;                   //to be added
                }
                else //------WHAT IS ENCOUNTERED IS NOT AN INSTRUCTION BUT A LABEL. UPDATE THE LABEL TABLE--------
                {
                    labeltable[nooflabels].location = counter;  //read the label and update labeltable.
                    op1=(char*)malloc(sizeof(token));
                    strcpy(op1,token);
                    labeltable[nooflabels].name=op1;
                    nooflabels++;
                }
                token = strtok(NULL,",\n\t\r ");  // if what is read before is an instruction, this will be NULL
                                                  //if what is read before is an label, this will be an opcode.
            }
        }


//================================= SECOND PASS ==============================

//supply the address fields of the jump and jz instructions by matching jumptable and labeltable
        int i,j;
        for (i=0; i<noofjumps;i++)   //for all jump/jz instructions encountered
        {
            j=0;
            while ((j<nooflabels)&&( strcmp(jumptable[i].name , labeltable[j].name ) != 0 ))  //if the label for this jump/jz does not match with the
                j++;                                            // jth label in the labeltable, check the next label..
            program[jumptable[i].location] +=(labeltable[j].location-jumptable[i].location-1)&0x0fff;       //copy the jump address into memory.
        }


//search for the start of the .data segment
        rewind(fp);
        while(fgets(line,sizeof line,fp)!= NULL)  //skip till .data, if no .data, also ok.
        {
            token=strtok(line,"\n\t\r ");
            if (strcmp(token,".data")==0 )
                break;

        }

// process the .data segment and generate the variabletable[] array.
        int dataarea=0;
         while(fgets(line,sizeof line,fp)!= NULL)
        {
            token=strtok(line,"\n\t\r ");
            if (strcmp(token,".code")==0 )  //go till the .code segment
                break;
            else if (token[strlen(token)-1]==':')
            {
                token[strlen(token)-1]='\0';  //will not cause memory leak, as we do not do malloc
                variabletable[noofvariables].location=counter+dataarea;
                op1=(char*)malloc(sizeof(token));
                strcpy(op1,token);
                variabletable[noofvariables].name=op1;
                token = strtok(NULL,",\n\t\r ");
                if (token==NULL)
                    program[counter+dataarea]=0;
                else if (strcmp(token, ".space")==0)
                {
                    token=strtok(NULL,"\n\t\r ");
                    dataarea+=atoi(token);
                }
                else if((token[0]=='0')&&(token[1]=='x'))
                    program[counter+dataarea]=hex2int(token+2)&0xffff;
                else if ((  (token[0])=='-') || ('0'<=(token[0])&&(token[0]<='9'))  )
                    program[counter+dataarea]=atoi(token)&0xffff;
                noofvariables++;
                dataarea++;
            }
        }


// supply the address fields for the ldi instructions from the variable table
        for( i=0; i<noofldis;i++)
        {
            j=0;
            while ((j<noofvariables)&&( strcmp( lditable[i].name , variabletable[j].name)!=0 ))
                j++;
            if (j<noofvariables)
                program[lditable[i].location] = variabletable[j].location;
        }


// supply the address fields for the ldi instructions from the label table
        for( i=0; i<noofldis;i++)
        {
            j=0;
            while ((j<nooflabels)&&( strcmp( lditable[i].name , labeltable[j].name)!=0 ))
                j++;
            if (j<nooflabels){
                program[lditable[i].location] = (labeltable[j].location)&0x0fff;
                printf("%d %d %d\n", i, j, (labeltable[j].location));
            }
        }


//display the resulting tables
        printf("LABEL TABLE\n");
        for (i=0;i<nooflabels;i++)
            printf("%d %s\n", labeltable[i].location, labeltable[i].name);
        printf("\n");
        printf("JUMP TABLE\n");
        for (i=0;i<noofjumps;i++)
            printf("%d %s\n", jumptable[i].location, jumptable[i].name);
        printf("\n");
        printf("VARIABLE TABLE\n");
        for (i=0;i<noofvariables;i++)
            printf("%d %s\n", variabletable[i].location, variabletable[i].name);
        printf("\n");
        printf("LDI INSTRUCTIONS\n");
        for (i=0;i<noofldis;i++)
            printf("%d %s\n", lditable[i].location, lditable[i].name);
        printf("\n");
        fclose(fp);
        fp = fopen("RAM","w"); //for Logisim
        fprintf(fp,"v2.0 raw\n"); 
        for (i=0;i<counter+dataarea;i++)
            fprintf(fp,"%04x\n",program[i]);
        fclose(fp);
        fp = fopen("ram.dat","w"); //for Verilog
        for (i=0;i<counter+dataarea;i++)
            fprintf(fp, "%04x\n", program[i]);
    }
}

 

Asembly Code

//Assembly Code
.code
ldi 7 0x60 		//stack address
ldi 6 0x0 		//clear r6
ldi 5 0x0		//clear r5
ldi 3 0xb00		//seven segment address  
loop ldi 2 0x0901  	//keypad status address loaded into r2
ld 0 2			// status is read into r2
ldi 1 0x1		// r1=1
and 1 0 1		// check status
jz loop			// if status is 0 turn back to starting point
ldi 2 0x0900		// keypad data address
ld 0 2			// load data into r2
ldi 4 0x000f		// r4= + sign
xor 4 0 4		// check data is +
jz addon		//if data is + go addition
ldi 4 0x000e		//r4= # sign
xor 4 0 4		//check data is #
jz mult			//if data is # go multiplication
// here decimal number is formed
add 4 6 6 		// assume x is in r6.  r4=2x
add 6 6 6		//r6=2x
add 6 6 6		//r6=4x
add 6 6 6		//r6=8x
add 6 4 6		//r6=10x
add 6 0 6		//r6=10x+newly entered digit
st 3 6			// show it on seven segment
jmp loop		//turn back to starting point to read new digit
addon add 5 5 6		// r5 is used to store total number. add new number to on it
xor 6 6 6		// clear r6 to get new number
st 3 5			// show the result on seven segment
jmp loop		// turn back to starting point
mult push 4		// store r4 on stack
call multi		
pop 4			// get r4 back
st 3 5			// show multiplication result on seven segment
jmp loop		// turn back to starting point
multi ldi 4 0x0		// clear r4
loop2 add 4 5 4		//add number in r5 to r4 r6 times
dec 6
jz out
jmp loop2
out mov 5 4		//move the result to r5 
ret

 

Demo Video

 

]]>
/bird-io-design/feed/ 0
Reptile-8: IO Design /reptile-8-io-design/ /reptile-8-io-design/#respond Wed, 09 Sep 2020 19:48:50 +0000 /?p=554  

//addition
.code
ldi 3 0xb00
loop ldi 2 0x901
ld 0 2 
ldi 1 0x1
and 1 0 1 
jz loop
ldi 2 0x900
ld 0 2
ldi 7 0x000f
xor 7 0 7
jz pressed
add 4 6 6
add 6 6 6
add 6 6 6
add 6 6 6
add 6 4 6
add 6 0 6
st 3 6
jmp loop
pressed st 3 0 
add 5 5 6
st 3 5
xor 6 6 6 
jmp loop

 

 

Main Module

//Main module
module top_module (  output wire [3:0] rowwrite,
			input [3:0] colread,
			input clk,
			output wire [3:0] grounds,
			output wire [6:0] display,
			input pushbutton // can be used as clock signal
		);


reg [15:0] data_all;
wire [3:0] keyout;
reg [25:0] clk1;
reg [1:0] ready_buffer;
reg ack;
reg statusordata;
 
 
 
    //memory map is defined here
    localparam     BEGINMEM=12'h000,
                   ENDMEM=12'h1ff,
                   KEYPAD=12'h900,
                   SEVENSEG=12'hb00;
 //  memory chip
    reg     [15:0] memory [0:127]; 
 
    // cpu's input-output pins
    wire     [15:0] data_out;
    reg     [15:0] data_in;
    wire     [11:0] address;
    wire     memwt;


sevensegment ss1 (.datain(data_all), .grounds(grounds), .display(display), .clk(clk));

keypad_ex  kp1(.rowwrite(rowwrite),.colread(colread),.clk(clk),.keyout(keyout),.statusordata(statusordata),.ack(ack));

reptile rr1 (.data_in(data_in), .data_out(data_out), .clk(clk), .memwt(memwt), .address(address));


 //multiplexer for cpu input
    always @*  
        if ( (BEGINMEM<=address) && (address<=ENDMEM) )
            begin
					data_in=memory[address];
					ack=0;
				   statusordata=0;
				end
        else if (address==KEYPAD+1)
				begin	
					statusordata=1;
					data_in=keyout;
					ack=0;
				end
		  else if (address==KEYPAD)
				begin
					data_in=keyout;
					statusordata=0;
					ack=1;
				end
        else
            begin
					data_in=16'hf345;    
					ack=0;
					statusordata=0;
				end
			
//multiplexer for cpu output            
    always @(posedge clk) //data output port of the cpu
        if (memwt)
            if ( (BEGINMEM<=address) && (address<=ENDMEM) )
                memory[address]<=data_out;
            else if ( SEVENSEG==address) 
                 data_all<=data_out;	
			
			
initial 	
	begin
		data_all=0;
		ack=0;
		statusordata=0;
		$readmemh("ram.dat", memory);
	end

endmodule

Keypad Module

 

//Keypad Module
module keypad_ex (
						output reg [3:0] rowwrite,
						input [3:0] colread,
						input clk,
						input ack,
						input statusordata,
						output reg [15:0] keyout
						
						);
wire keypressed;		
reg [25:0] clk1;
reg ready;
reg [3:0] keyread, data;
reg [3:0] rowpressed;
reg [3:0] pressedcol [0:3];
reg [11:0] rowpressed_buffer0, rowpressed_buffer1, rowpressed_buffer2, rowpressed_buffer3;
reg [3:0] rowpressed_debounced;

always @(posedge clk)
	clk1<=clk1+1;

always @(posedge clk1[15])
	rowwrite<={rowwrite[2:0], rowwrite[3]};

always @(posedge clk1[15])
	if (rowwrite== 4'b1110)
		begin
			rowpressed[0]<= ~(&colread); //colread=1111--> none of them pressed, colread=1110 --> 1, colread=1101-->2, 1011-->3, 0111->A
			pressedcol[0]<=colread;
		end
	else if (rowwrite==4'b1101)
		begin
			rowpressed[1]<= ~(&colread); //colread=1111--> none of them pressed, colread=1110 --> 4, colread=1101-->5, 1011-->6, 0111->B
			pressedcol[1]<=colread;
		end
	else if (rowwrite==4'b1011)
		begin
			rowpressed[2]<= ~(&colread); //colread=1111--> none of them pressed, colread=1110 --> 7, colread=1101-->8, 1011-->9, 0111->C
			pressedcol[2]<=colread;
		end
	else if (rowwrite==4'b0111)
		begin
			rowpressed[3]<= ~(&colread); //colread=1111--> none of them pressed, colread=1110 --> *(E), colread=1101-->0, 1011-->#(F), 0111->D
			pressedcol[3]<=colread;
		end
		
wire transition0_10;
wire transition0_01;

assign transition0_10=~|rowpressed_buffer0;
assign transition0_01=&rowpressed_buffer0;

wire transition1_10;
wire transition1_01;

assign transition1_10=~|rowpressed_buffer1;
assign transition1_01=&rowpressed_buffer1;

wire transition2_10;
wire transition2_01;

assign transition2_10=~|rowpressed_buffer2;
assign transition2_01=&rowpressed_buffer2;

wire transition3_10;
wire transition3_01;

assign transition3_10=~|rowpressed_buffer3; //kpd=1-->0
assign transition3_01=&rowpressed_buffer3;  //kpd=0-->1


always @(posedge clk1[15])
	begin
		rowpressed_buffer0<= {rowpressed_buffer0[10:0],rowpressed[0]};
		if (rowpressed_debounced[0]==0 && transition0_01)
			rowpressed_debounced[0]<=1;
		if (rowpressed_debounced[0]==1 && transition0_10)
			rowpressed_debounced[0]<=0;
	
	rowpressed_buffer1<= {rowpressed_buffer1[10:0],rowpressed[1]};
		if (rowpressed_debounced[1]==0 && transition1_01)
			rowpressed_debounced[1]<=1;
		if (rowpressed_debounced[1]==1 && transition1_10)
			rowpressed_debounced[1]<=0;
			
	rowpressed_buffer2<= {rowpressed_buffer2[10:0],rowpressed[2]};
		if (rowpressed_debounced[2]==0 && transition2_01)
			rowpressed_debounced[2]<=1;
		if (rowpressed_debounced[2]==1 && transition2_10)
			rowpressed_debounced[2]<=0;
	
	rowpressed_buffer3<= {rowpressed_buffer3[10:0],rowpressed[3]};
		if (rowpressed_debounced[3]==0 && transition3_01)
			rowpressed_debounced[3]<=1;
		if (rowpressed_debounced[3]==1 && transition3_10)
			rowpressed_debounced[3]<=0;
	end 

always @*
	begin
		if (rowpressed_debounced[0]==1)
			begin
				if (pressedcol[0]==4'b1110)
					keyread=4'h1;
				else if (pressedcol[0]==4'b1101)
					keyread=4'h2;
				else if (pressedcol[0]==4'b1011)
					keyread=4'h3;
				else if (pressedcol[0]==4'b0111)
					keyread=4'hA;
				else keyread=4'b0000;
			end
		else if (rowpressed_debounced[1]==1)
			begin
				if (pressedcol[1]==4'b1110)
					keyread=4'h4;
				else if (pressedcol[1]==4'b1101)
					keyread=4'h5;
				else if (pressedcol[1]==4'b1011)
					keyread=4'h6;
				else if (pressedcol[1]==4'b0111)
					keyread=4'hB;
				else keyread=4'b0000;
			end
		else if (rowpressed_debounced[2]==1)
			begin
				if (pressedcol[2]==4'b1110)
					keyread=4'h7;
				else if (pressedcol[2]==4'b1101)
					keyread=4'h8;
				else if (pressedcol[2]==4'b1011)
					keyread=4'h9;
				else if (pressedcol[2]==4'b0111)
					keyread=4'hC;
				else keyread=4'b0000;
			end
		else if (rowpressed_debounced[3]==1)
			begin
				if (pressedcol[3]==4'b1110)
					keyread=4'hE;
				else if (pressedcol[3]==4'b1101)
					keyread=4'h0;
				else if (pressedcol[3]==4'b1011)
					keyread=4'hF;
				else if (pressedcol[3]==4'b0111)
					keyread=4'hD;
				else keyread=4'b0000;
			end
		else keyread=4'b0000;
	end //always


assign keypressed= rowpressed_debounced[0]||rowpressed_debounced[1]||rowpressed_debounced[2]||rowpressed_debounced[3];

reg [1:0] keypressed_buffer; //yeni karakter için parmağı çekip tekrar basmamız için gerekli

always @(posedge clk)
	keypressed_buffer<={keypressed_buffer[0],keypressed};

always @(posedge clk)
	if ((keypressed_buffer==2'b01)&&(ready==0))
		begin
			data<=keyread;
			ready<=1;
		end
	else if ((ack==1)&&(ready==1))
		ready<=0;
	
always @(*)
	if (statusordata==1)
		keyout={15'b0,ready};
	else
		keyout={12'b0,data};
	
initial 
	begin
		rowwrite=4'b1110;		
		ready=0;
	end
endmodule

CPU Module

//Reptile CPU

module reptile (
		input clk,
		input [15:0] data_in,
		output [15:0] data_out,
		output reg [11:0] address,
		output memwt
		);
 
    reg [11:0] pc, ir; //program counter, instruction register
 
    reg [4:0]  state; //FSM
	 reg [15:0] regbank [7:0];//registers 
    reg zeroflag; //zero flag register
	 reg [15:0] result; //output for result
 
 
     localparam   FETCH=4'b0000,
                  LDI=4'b0001, 
                  LD=4'b0010,
                  ST=4'b0011,
                  JZ=4'b0100,
                  JMP=4'b0101,
                  ALU=4'b0111;
 
	 
    wire zeroresult; //zeroflag value 
 
    always @(posedge clk)
        case(state)
 
            FETCH: 
            begin
                if ( data_in[15:12]==JZ) // if instruction is jz  
                    if (zeroflag)  //and if last bit of 7th register is 0 then jump to jump instruction state
                        state <= JMP;
                    else
                        state <= FETCH; //stay here to catch next instruction
                else
                    state <= data_in[15:12]; //read instruction opcode and jump the state of the instruction to be read
                ir<=data_in[11:0]; //read instruction details into instruction register
                pc<=pc+1; //increment program counter
            end
 
            LDI:
            begin
                regbank[ ir[2:0] ] <= data_in; //if inst is LDI get the destination register number from ir and move the data in it.
                pc<=pc+1; //for next instruction (32 bit instruction)  
                state <= FETCH;
            end
 
             LD:
                begin
                    regbank[ir[2:0]] <= data_in;
                    state <= FETCH;  
                end 
 
            ST:
                begin
						  state <= FETCH;  
                end    
 
            JMP:
                begin
                    pc <= pc+ir;
                    state <= FETCH;  
                end          
 
            ALU:
                begin
                    regbank[ir[2:0]]<=result;
                    zeroflag<=zeroresult;
                    state <= FETCH;
                end
 
        endcase
 
 
 
    always @*   
        case (state)
            LD:      address=regbank[ir[5:3]][11:0];
            ST:      address=regbank[ir[5:3]][11:0];
            default: address=pc;
         endcase
 
 
 assign memwt=(state==ST);
 
 assign data_out = regbank[ir[8:6]];
    always @*
        case (ir[11:9])
            3'h0: result = regbank[ir[8:6]]+regbank[ir[5:3]]; //000
            3'h1: result = regbank[ir[8:6]]-regbank[ir[5:3]]; //001
            3'h2: result = regbank[ir[8:6]]&regbank[ir[5:3]]; //010
            3'h3: result = regbank[ir[8:6]]|regbank[ir[5:3]]; //011
            3'h4: result = regbank[ir[8:6]]^regbank[ir[5:3]]; //100
            3'h7: case (ir[8:6])
                        3'h0: result = !regbank[ir[5:3]];
                        3'h1: result = regbank[ir[5:3]];
                        3'h2: result = regbank[ir[5:3]]+1;
                        3'h3: result = regbank[ir[5:3]]-1;
                        default: result=16'h0000;
                    endcase
            default: result=16'h0000;
        endcase
 
   assign zeroresult = ~|result;

    initial begin;
        state=FETCH;
	zeroflag=0;
	pc=0;
    end                        
endmodule

Reptile Assembler

// to compile, gcc assembler.c -o assembler
// No error check is provided.
// Variable names cannot start with numeric characters, ie, with 0-9.
// hexadecimals are twos complement.
// first address of the code section is zero, and the data section follows the code section in memory.
// four tables are formed: jump table, ldi table, label table and variable table.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


//Converts a hexadecimal string to integer.
int hex2int( char* hex)
{
    int result=0;

    while ((*hex)!='\0')
    {
        if (('0'<=(*hex))&&((*hex)<='9'))
            result = result*16 + (*hex) -'0';
        else if (('a'<=(*hex))&&((*hex)<='f'))
            result = result*16 + (*hex) -'a'+10;
        else if (('A'<=(*hex))&&((*hex)<='F'))
            result = result*16 + (*hex) -'A'+10;
        hex++;
    }
    return(result);
}


main()
{
    FILE *fp;
    char line[100];
    char *token = NULL;
    char *op1, *op2, *op3, *label;
    char ch;
    int  chch;

    int program[1000];
    int counter=0;  //holds the address of the machine code instruction


    struct label_or_variable
    {
        int location;
        char *name;
    };

// A label is a symbol which mark a location within the code section. In the example
// program above, the strings "lpp", "loop" and "lp1" are labels.
// In reptile, labels are used by jump, jz and ldi instructions.
    struct label_or_variable labeltable[50]; //there can be 50 labels at most in our programs
    int nooflabels = 0;                       //number of labels encountered during assembly.

 // A variable is a symbol which mark a location within the data section. In the example
// program above, the strings "", "" and "" are variables.
// In reptile, variables are used by ldi instructions.
    struct label_or_variable variabletable[50]; // The list of variables in .data section and their locations.
    int noofvariables = 0;    //number of jumps encountered during assembly.

// Jump instructions cannot be assembled readily because we may not know the value of
// the label when we encountered a jump instruction. This happens if the label used by
// that jump instruction appear below that jump instruction. This is the situation
// with the label "loop" in the example program above. Hence, the location of jump
// instructions must be stored.
    struct label_or_variable jumptable[100]; //There can be at most 100 jumps
    int noofjumps=0;                        //number of jump instructions encountered during assembly.


//Variables and labels are used by ldi instructions.
//The memory for the variables are traditionally allocated at the end of the code section.
//Hence their addresses are not known when we assemble a ldi instruction. Also, the value of
//a label may not be known when we encounter a ldi instruction which uses that label.
//Hence, the location of the ldi instructions must be kept, and these instructions must be
//modified when we discover the address of the label or variable that it uses.
    struct label_or_variable lditable[100];
    int noofldis=0;



    fp = fopen("code.txt","r");

    if (fp != NULL)
    {
        while(fgets(line,sizeof line,fp)!= NULL)  //skip till .code section
        {
            token=strtok(line,"\n\t\r ");
            if (strcmp(token,".code")==0 )
                break;
        }
        while(fgets(line,sizeof line,fp)!= NULL)
        {
            token=strtok(line,"\n\t\r ");  //get the instruction mnemonic or label

//========================================   FIRST PASS  ======================================================
            while (token)
            {
                if (strcmp(token,"ldi")==0)        //---------------LDI INSTRUCTION--------------------
                {
                    op1 = strtok(NULL,"\n\t\r ");                                //get the 1st operand of ldi, which is the register that ldi loads
                    op2 = strtok(NULL,"\n\t\r ");                                //get the 2nd operand of ldi, which is the data that is to be loaded
                    program[counter]=0x1000+hex2int(op1);                        //generate the first 16-bit of the ldi instruction
                    counter++;                                                   //move to the second 16-bit of the ldi instruction
                    if ((op2[0]=='0')&&(op2[1]=='x'))                            //if the 2nd operand is twos complement hexadecimal
                        program[counter]=hex2int(op2+2)&0xffff;              //convert it to integer and form the second 16-bit
                    else if ((  (op2[0])=='-') || ((op2[0]>='0')&&(op2[0]<='9')))       //if the 2nd operand is decimal
                        program[counter]=atoi(op2)&0xffff;                         //convert it to integer and form the second 16-bit
                    else                                                           //if the second operand is not decimal or hexadecimal, it is a laber or a variable.
                    {                                                               //in this case, the 2nd 16-bits of the ldi instruction cannot be generated.
                        lditable[noofldis].location = counter;                 //record the location of this 2nd 16-bit
                        op1=(char*)malloc(sizeof(op2));                         //and the name of the label/variable that it must contain
                        strcpy(op1,op2);                                        //in the lditable array.
                        lditable[noofldis].name = op1;
                        noofldis++;
                    }
                    counter++;                                                     //skip to the next memory location
                }

                else if (strcmp(token,"ld")==0)      //------------LD INSTRUCTION---------------------
                {
                    op1 = strtok(NULL,"\n\t\r ");                //get the 1st operand of ld, which is the destination register
                    op2 = strtok(NULL,"\n\t\r ");                //get the 2nd operand of ld, which is the source register
                    ch = (op1[0]-48)| ((op2[0]-48) << 3);        //form bits 11-0 of machine code. 48 is ASCII value of '0'
                    program[counter]=0x2000+((ch)&0x00ff);       //form the instruction and write it to memory
                    counter++;                                   //skip to the next empty location in memory
                }
                else if (strcmp(token,"st")==0) //-------------ST INSTRUCTION--------------------
                {
                    op1 = strtok(NULL,"\n\t\r ");                //get the 1st operand of ld, which is the destination register
                    op2 = strtok(NULL,"\n\t\r ");                //get the 2nd operand of ld, which is the source register
                    chch = (op1[0]-48)<<3| ((op2[0]-48) << 6);        //form bits 11-0 of machine code. 48 is ASCII value of '0'
                    program[counter]=0x3000+((chch)&0x01ff);       //form the instruction and write it to memory
                    counter++;                                   //skip to the next empty location in memory
                    //to be added
                }
                else if (strcmp(token,"jz")==0) //------------- CONDITIONAL JUMP ------------------
                {
                    op1 = strtok(NULL,"\n\t\r ");            //read the label string
                    jumptable[noofjumps].location = counter;    //write the jz instruction's location into the jumptable
                    op2=(char*)malloc(sizeof(op1));         //allocate space for the label
                    strcpy(op2,op1);                //copy the label into the allocated space
                    jumptable[noofjumps].name=op2;            //point to the label from the jumptable
                    noofjumps++;                    //skip to the next empty location in jumptable
                    program[counter]=0x4000;            //write the incomplete instruction (just opcode) to memory
                    counter++;
                    //to be added
                }
                else if (strcmp(token,"jmp")==0)  //-------------- JUMP -----------------------------
                {
                    op1 = strtok(NULL,"\n\t\r ");            //read the label string
                    jumptable[noofjumps].location = counter;    //write the jz instruction's location into the jumptable
                    op2=(char*)malloc(sizeof(op1));         //allocate space for the label
                    strcpy(op2,op1);                //copy the label into the allocated space
                    jumptable[noofjumps].name=op2;            //point to the label from the jumptable
                    noofjumps++;                    //skip to the next empty location in jumptable
                    program[counter]=0x5000;            //write the incomplete instruction (just opcode) to memory
                    counter++;                    //skip to the next empty location in memory.
                }
                else if (strcmp(token,"add")==0) //----------------- ADD -------------------------------
                {
                    op1 = strtok(NULL,"\n\t\r ");
                    op2 = strtok(NULL,"\n\t\r ");
                    op3 = strtok(NULL,"\n\t\r ");
                    chch = (op1[0]-48)| ((op2[0]-48)<<6)|((op3[0]-48)<<3);
                    program[counter]=0x7000+((chch)&0x01ff);
                    counter++;
                }
                else if (strcmp(token,"sub")==0)
                {
                    op1 = strtok(NULL,"\n\t\r ");
                    op2 = strtok(NULL,"\n\t\r ");
                    op3 = strtok(NULL,"\n\t\r ");
                    chch = (op1[0]-48)| ((op2[0]-48)<<6)|((op3[0]-48)<<3);
                    program[counter]=0x7200+((chch)&0x01ff);
                    counter++;
                    //to be added
                }
                else if (strcmp(token,"and")==0)
                {
                    op1 = strtok(NULL,"\n\t\r ");
                    op2 = strtok(NULL,"\n\t\r ");
                    op3 = strtok(NULL,"\n\t\r ");
                    chch = (op1[0]-48)| ((op2[0]-48)<<6)|((op3[0]-48)<<3);
                    program[counter]=0x7400+((chch)&0x01ff);
                    counter++;
                    //to be added
                }
                else if (strcmp(token,"or")==0)
                {
                    op1 = strtok(NULL,"\n\t\r ");
                    op2 = strtok(NULL,"\n\t\r ");
                    op3 = strtok(NULL,"\n\t\r ");
                    chch = (op1[0]-48)| ((op2[0]-48)<<6)|((op3[0]-48)<<3);
                    program[counter]=0x7600+((chch)&0x01ff);
                    counter++;//to be added
                }
                else if (strcmp(token,"xor")==0)
                {
                    op1 = strtok(NULL,"\n\t\r ");
                    op2 = strtok(NULL,"\n\t\r ");
                    op3 = strtok(NULL,"\n\t\r ");
                    chch = (op1[0]-48)| ((op2[0]-48)<<6)|((op3[0]-48)<<3);
                    program[counter]=0x7800+((chch)&0x01ff);
                    counter++;
                    //to be added
                }
                else if (strcmp(token,"not")==0)
                {
                    op1 = strtok(NULL,"\n\t\r ");
                    op2 = strtok(NULL,"\n\t\r ");
                    ch = (op1[0]-48)| ((op2[0]-48)<<3);
                    program[counter]=0x7E00+((ch)&0x00ff);
                    counter++;
                }
                else if (strcmp(token,"mov")==0)
                {
                    op1 = strtok(NULL,"\n\t\r ");
                    op2 = strtok(NULL,"\n\t\r ");
                    ch = (op1[0]-48)| ((op2[0]-48)<<3);
                    program[counter]=0x7E40+((ch)&0x00ff);
                    counter++;
                    //to be added
                }
                else if (strcmp(token,"inc")==0)
                {
                    op1 = strtok(NULL,"\n\t\r ");
                    ch = (op1[0]-48)| ((op1[0]-48)<<3);
                    program[counter]=0x7E80+((ch)&0x00ff);
                    counter++;
                }
                else if (strcmp(token,"dec")==0)
                {
                    op1 = strtok(NULL,"\n\t\r ");
                    ch = (op1[0]-48)| ((op1[0]-48)<<3);
                    program[counter]=0x7EC0+((ch)&0x00ff);
                    counter++;                   //to be added
                }
                else //------WHAT IS ENCOUNTERED IS NOT AN INSTRUCTION BUT A LABEL. UPDATE THE LABEL TABLE--------
                {
                    labeltable[nooflabels].location = counter;  //read the label and update labeltable.
                    op1=(char*)malloc(sizeof(token));
                    strcpy(op1,token);
                    labeltable[nooflabels].name=op1;
                    nooflabels++;
                }
                token = strtok(NULL,",\n\t\r ");  // if what is read before is an instruction, this will be NULL
                                                  //if what is read before is an label, this will be an opcode.
            }
        }


//================================= SECOND PASS ==============================

//supply the address fields of the jump and jz instructions by matching jumptable and labeltable
        int i,j;
        for (i=0; i<noofjumps;i++)   //for all jump/jz instructions encountered
        {
            j=0;
            while ((j<nooflabels)&&( strcmp(jumptable[i].name , labeltable[j].name ) != 0 ))  //if the label for this jump/jz does not match with the
                j++;                                            // jth label in the labeltable, check the next label..
            program[jumptable[i].location] +=(labeltable[j].location-jumptable[i].location-1)&0x0fff;       //copy the jump address into memory.
        }


//search for the start of the .data segment
        rewind(fp);
        while(fgets(line,sizeof line,fp)!= NULL)  //skip till .data, if no .data, also ok.
        {
            token=strtok(line,"\n\t\r ");
            if (strcmp(token,".data")==0 )
                break;

        }

// process the .data segment and generate the variabletable[] array.
        int dataarea=0;
         while(fgets(line,sizeof line,fp)!= NULL)
        {
            token=strtok(line,"\n\t\r ");
            if (strcmp(token,".code")==0 )  //go till the .code segment
                break;
            else if (token[strlen(token)-1]==':')
            {
                token[strlen(token)-1]='\0';  //will not cause memory leak, as we do not do malloc
                variabletable[noofvariables].location=counter+dataarea;
                op1=(char*)malloc(sizeof(token));
                strcpy(op1,token);
                variabletable[noofvariables].name=op1;
                token = strtok(NULL,",\n\t\r ");
                if (token==NULL)
                    program[counter+dataarea]=0;
                else if (strcmp(token, ".space")==0)
                {
                    token=strtok(NULL,"\n\t\r ");
                    dataarea+=atoi(token);
                }
                else if((token[0]=='0')&&(token[1]=='x'))
                    program[counter+dataarea]=hex2int(token+2)&0xffff;
                else if ((  (token[0])=='-') || ('0'<=(token[0])&&(token[0]<='9'))  )
                    program[counter+dataarea]=atoi(token)&0xffff;
                noofvariables++;
                dataarea++;
            }
        }


// supply the address fields for the ldi instructions from the variable table
        for( i=0; i<noofldis;i++)
        {
            j=0;
            while ((j<noofvariables)&&( strcmp( lditable[i].name , variabletable[j].name)!=0 ))
                j++;
            if (j<noofvariables)
                program[lditable[i].location] = variabletable[j].location;
        }


// supply the address fields for the ldi instructions from the label table
        for( i=0; i<noofldis;i++)
        {
            j=0;
            while ((j<nooflabels)&&( strcmp( lditable[i].name , labeltable[j].name)!=0 ))
                j++;
            if (j<nooflabels){
                program[lditable[i].location] = (labeltable[j].location)&0x0fff;
                printf("%d %d %d\n", i, j, (labeltable[j].location));
            }
        }


//display the resulting tables
        printf("LABEL TABLE\n");
        for (i=0;i<nooflabels;i++)
            printf("%d %s\n", labeltable[i].location, labeltable[i].name);
        printf("\n");
        printf("JUMP TABLE\n");
        for (i=0;i<noofjumps;i++)
            printf("%d %s\n", jumptable[i].location, jumptable[i].name);
        printf("\n");
        printf("VARIABLE TABLE\n");
        for (i=0;i<noofvariables;i++)
            printf("%d %s\n", variabletable[i].location, variabletable[i].name);
        printf("\n");
        printf("LDI INSTRUCTIONS\n");
        for (i=0;i<noofldis;i++)
            printf("%d %s\n", lditable[i].location, lditable[i].name);
        printf("\n");
        fclose(fp);
        fp = fopen("RAM","w");
        fprintf(fp,"v2.0 raw\n");
        for (i=0;i<counter+dataarea;i++)
            fprintf(fp,"%04x\n",program[i]);
        fclose(fp);
        fp = fopen("ram.dat","w");
        for (i=0;i<counter+dataarea;i++)
            fprintf(fp, "%04x\n", program[i]);
    }
}

 

 

 

 

]]>
/reptile-8-io-design/feed/ 0
Reptile-8: The Hardware Design /reptile-8-the-hardware-design/ /reptile-8-the-hardware-design/#respond Tue, 08 Sep 2020 18:09:34 +0000 /?p=523  

Machine Code Format for LDI
LDI r,x

Machine Code Format for INC and DEC
INC r1

Machine Code Format for MOV and NOT
MOV r1 r2

Machine Code Format for ADD, SUB, AND, OR, XOR
ADD r1 r2 r3

Machine Code Format for LD
LD r1 r2

Machine Code Format for ST
ST r1 r2

Machine Code Format for JMP
JMP x

Machine Code Format for JZ
JZ x

 

Reptile Verilog Code

//Reptile design with 8 Registers. 
// This module also sents register #0 to main module as an output


module reptile (
					input clk,
					input [15:0] data_in,
					output [15:0] data_out,
					output reg [11:0] address,
					output memwt,
					output [15:0] reg0
					);
 
    reg [11:0] pc, ir; //program counter, instruction register
 
    reg [4:0]  state; //FSM
	 reg [15:0] regbank [7:0];//registers 
    reg zeroflag; //zero flag register
	 reg [15:0] result; //output for result
 
 
     localparam   FETCH=4'b0000,
                  LDI=4'b0001, 
                  LD=4'b0010,
                  ST=4'b0011,
                  JZ=4'b0100,
                  JMP=4'b0101,
                  ALU=4'b0111;
 
	 
    wire zeroresult; //zeroflag value 
 
    always @(posedge clk)
        case(state)
 
            FETCH: 
            begin
                if ( data_in[15:12]==JZ) // if instruction is jz  
                    if (zeroflag)  //and if last bit of 7th register is 0 then jump to jump instruction state
                        state <= JMP;
                    else
                        state <= FETCH; //stay here to catch next instruction
                else
                    state <= data_in[15:12]; //read instruction opcode and jump the state of the instruction to be read
                ir<=data_in[11:0]; //read instruction details into instruction register
                pc<=pc+1; //increment program counter
            end
 
            LDI:
            begin
                regbank[ ir[2:0] ] <= data_in; //if inst is LDI get the destination register number from ir and move the data in it.
                pc<=pc+1; //for next instruction (32 bit instruction)  
                state <= FETCH;
            end
 
             LD:
                begin
                    regbank[ir[2:0]] <= data_in;
                    state <= FETCH;  
                end 
 
            ST:
                begin
						  state <= FETCH;  
                end    
 
            JMP:
                begin
                    pc <= pc+ir;
                    state <= FETCH;  
                end          
 
            ALU:
                begin
                    regbank[ir[2:0]]<=result;
                    zeroflag<=zeroresult;
                    state <= FETCH;
                end
 
        endcase
 
 
 
    always @*   
        case (state)
            LD:      address=regbank[ir[5:3]][11:0];
            ST:      address=regbank[ir[5:3]][11:0];
            default: address=pc;
         endcase
 
 
 assign memwt=(state==ST);
 
 assign data_out = regbank[ir[8:6]];
    always @*
        case (ir[11:9])
            3'h0: result = regbank[ir[8:6]]+regbank[ir[5:3]]; //000
            3'h1: result = regbank[ir[8:6]]-regbank[ir[5:3]]; //001
            3'h2: result = regbank[ir[8:6]]&regbank[ir[5:3]]; //010
            3'h3: result = regbank[ir[8:6]]|regbank[ir[5:3]]; //011
            3'h4: result = regbank[ir[8:6]]^regbank[ir[5:3]]; //100
            3'h7: case (ir[8:6])
                        3'h0: result = !regbank[ir[5:3]];
                        3'h1: result = regbank[ir[5:3]];
                        3'h2: result = regbank[ir[5:3]]+1;
                        3'h3: result = regbank[ir[5:3]]-1;
                        default: result=16'h0000;
                    endcase
            default: result=16'h0000;
        endcase
 
   assign zeroresult = ~|result;

	assign reg0=regbank[0];
    initial begin;
            state=FETCH;
				zeroflag=0;
				pc=0;
            end                        
endmodule

 

Main Module for Reptile

//This module sents Register #0 to seven segment display 

module top_module (grounds, display, clk, pushbutton,led);
 
    input   pushbutton; 
    output  [3:0] grounds;
    output  [6:0] display;
    input   clk; 
    output led;
 
    //  memory chip
    reg     [15:0] memory [0:127]; 
 
    // cpu's input-output pins
    wire     [11:0] pc; //for debugging
    wire     [15:0] data_out;
    wire     [15:0] data_in;
    wire     [11:0] address;
    wire     memwt;
 
    wire     [15:0] reg0;
 
 assign led=memwt; //check memory write signal works or not. For debugging 
 
    //instantiation of cpu
  reptile rr1 (.data_in(data_in), .data_out(data_out), .clk(~pushbutton), .memwt(memwt), .address(address),.reg0(reg0));
    //instantiation of seven segment
    sevensegment ss1 (.grounds(grounds), .display(display), .clk(clk),  .datain(reg0));
    
 
    assign data_in=memory[address];
    
	 always @(posedge clk)
		if (memwt==1)
			memory[address]<=data_out;
	
	
    initial begin
		$readmemh("ram.dat", memory);
    end
 
endmodule

 

 

 

]]>
/reptile-8-the-hardware-design/feed/ 0
Dirac delta function /dirac-delta-function/ /dirac-delta-function/#respond Tue, 05 May 2020 02:03:04 +0000 /?p=319 Dirac delta function

A dirac delta “function” is a function which puts area 1 on top of a single point, and area zero on top of the rest of the points. We have written the word function within quotes, as dirac delta function is in reality not a function. In mathematical terminology, it is called a “distribution” or a “generalized function”. We will see why this is so later.

In the usual functions, area on top of a single point x is always zero, assuming that the function has a finite value there. Consider the function $f(x)$.

Periodic Dirac Delta Functions

Theorem:
$$
\sum_{k=-\infty}^{\infty}e^{{2 \pi i} kt}=\sum_{n=-\infty}^{\infty}\delta(t-n)$$
Proof:
$$\begin{eqnarray}
\sum_{k=-N}^{N}e^{{2 \pi i} kt}&=& e^{-{2 \pi i} Nt}+e^{-{2 \pi i} (N-1)t}+\ldots+e^{{2 \pi i} (N-1)t}+e^{{2 \pi i} Nt} \\
&=&e^{-{2 \pi i} Nt} (1+e^{2 \pi i t} + \ldots +e^{\pi i (4N-1)t}+e^{4 \pi i Nt})
\end{eqnarray}$$
The part within the parantheses is a truncated geomertic series. After summing it, and performing some algebraic manipulations, we arrive at
$$\begin{eqnarray}
\sum_{k=-N}^{N}e^{2 \pi i kt}&=&e^{-2 \pi i Nt}\frac{1-e^{2 \pi i (2N+1)t}}{1-e^{2 \pi i t}}\\
&=&e^{-2 \pi i Nt}\frac{e^{\pi i (2N+1)t}(e^{- \pi i (2N+1)t}-e^{ \pi i (2N+1)t})}{e^{\pi i t}(e^{-\pi i t}-e^{ \pi i t})}\\
&=&\frac{e^{- \pi i (2N+1)t}-e^{ \pi i (2N+1)t}}{e^{-\pi i t}-e^{ \pi i t}}\\
\end{eqnarray}$$
Remembering the definition of sin(.), we arrive at
$$\begin{eqnarray}
\sum_{k=-N}^{N}e^{2 \pi i kt}=\frac{\sin[(2N+1)\pi t]}{\sin(\pi t)}
\end{eqnarray}$$
Now, let us take the limit $N \rightarrow \infty$, ie, consider the expression
$$\begin{eqnarray}
\lim_{N \rightarrow \infty}\frac{\sin[(2N+1)\pi t]}{\sin(\pi t)}
\end{eqnarray}$$
As this expression is periodic with period 1, it is sufficient to analyze it only on a single period. Hence, let us limit our analysis to the interval $[-1/2,1/2]$. This interval can be decomposed into three subintervals:
$$\begin{eqnarray}
[-\frac{1}{2},\frac{1}{2}]=[-\frac{1}{2},-\delta] \cup (-\delta,\delta) \cup [\delta,\frac{1}{2}].
\end{eqnarray}$$
where $\delta$ is a small positive number.

  • In $[-\frac{1}{2},-\delta]$, $\sin(\pi t)$ is not zero and the function is a bounded and infinitely fast oscillation.
  • In $(-\delta,\delta)$, $t$ is very small hence $\sin(\pi t) \approx \pi t$. Therefore
    $$\begin{eqnarray}
    \lim_{N \rightarrow \infty}\frac{\sin[(2N+1)\pi t]}{\sin(\pi t)} \approx \lim_{N \rightarrow \infty}\frac{\sin[(2N+1)\pi t]}{\pi t}=\delta(t)
    \end{eqnarray}$$
  • In $[\delta,\frac{1}{2}]$, $\sin(\pi t)$ is not zero and the function is a bounded and infinitely fast oscillation.

Therefore,
$$\begin{eqnarray}
\lim_{N \rightarrow \infty}\frac{\sin[(2N+1)\pi t]}{\sin(\pi t)} =\delta(t)
\end{eqnarray} \qquad,\qquad t \in [-\delta,\delta] $$
If we consider all the periods, we obtain the theorem..

Scaled version of the Periodic Dirac Delta Functions

Let us scale time in the above expression
$$ \begin{eqnarray}
t \rightarrow \frac{t}{T}
\end{eqnarray}$$
where $T$ is the scaling factor. Then
$$
\sum_{k=-\infty}^{\infty}e^{{2 \pi i} k\frac{t}{T}}=\sum_{n=-\infty}^{\infty}\delta(\frac{t}{T}-n)$$
Or, using the modulation property of dirac deltas,
$$
\delta(at)=\frac{1}{|a|}\delta(t)
$$
we get
$$
\sum_{k=-\infty}^{\infty}e^{{2 \pi i} k\frac{t}{T}}=T\sum_{n=-\infty}^{\infty}\delta(t-nT)$$

]]>
/dirac-delta-function/feed/ 0
Frog: A Calculator that can load data into registers /frog-a-calculator-that-can-load-data-into-registers/ /frog-a-calculator-that-can-load-data-into-registers/#respond Sun, 26 Apr 2020 22:23:13 +0000 /?p=300 Before executing a program in Fish, the programmer has to do a two-step preparation:

  • He has to put his program into memory
  • He has to put his data into registers.

and subsequently the program will be executed instruction by instruction by the arriving clock edges.

In Frog, we want to get rid of the second step of this preparation, ie, “put the data into registers” step. Instead, we want to put both the data and the program into the memory. Then, the program will load the required data from memory into the registers as it executes. For this, we need a new type of instruction, called “load immediate” or LDI instruction. And, in order to distinguish this new type of instruction from the previous instructions, we need a new field in our machine code, called the “opcode field“.

1. Instruction Set

In Fish, we only loaded instructions from the memory to CPU, and the data is directly loaded into registers at the start of the program . The data was 16 bit numbers, and instructions required only 9 bits. Hence we make our CPU registers 16 bits wide and memory locations 9 bits wide.

In frog, things have changed. Both data (ie, 16 bits wide) and instructions (9 bits wide) are loaded from memory into CPU. Therefore, memory locations must be widened to 16 bits to accommodate data.

As Frog has two different instructions, it needs a single bit for the opcode field. But we will allocate four bits, instead of one bit as opcode, because in future we plan to increase the number of instructions up to 16.

1.1 ALU Instruction format

ALU instructions of frog have the same fields with fish, except the opcode field, which is new.

Note that we expect an instruction to fit into a memory location, which is 16 bits. Assume that we are using 8 registers for frog. In this case, each of the Src1, Src2 and Dst fields will take three bits, which will make 9 bits in total. If we add AluOp (4 bits) and Opcode (4 bits) on top of that, the total instruction length will become 17 bits. This will not fit into a single memory location, which is a problem..

Possible solutions are

  1. Reduce Opcode width to 3 bits. Downside: This will restrict the future expansion of our instruction set, as in this case we can have at most 8 instructions.
  2. Reduce AluOp fields to 3 bits. Downside: This will reduce the number of available ALU operations to 8.
  3. Increase the register and memory widths to 17, and use 17-bit wide data. Downside: the processor will be highly unconventional, as the memory and register widths are standardized to 8, 16, 32 bits..
  4. Use two consecutive memory locations for each ALU instructions. Downside: Two memory locations contain 32 bits, and we will use 17 of them.
  5. Reduce the width of src1, src2 and dst fields from 3 to 2 bits. Downside: This will reduce the number of registers from 8 to 4.

We choose solution number 5. Why? Because when we investigate reptile we will introduce a trick which allows us to have 8 registers while still keeping the opcode and aluop fields 4 bits wide and the instruction 16-bits long.

Also note that the order of fields are changed. This is for making you remember that when designing an instruction set order of fields in an instruction is not important..

1.2 LDI Instruction Format

2. Finite state machine and Control Unit.

In Fish, we had only one instruction: the ALU instruction. In Frog, the number of instructions is increased to two: ALU instruction and LDI instruction. Hence, when we bring down an instruction from memory into the CPU, it cannot be executed instantly, as in fish. First, it must be stored in some register and its opcode field has to be inspected to determine if it is a LDI or ALU instruction. In our design, this is achieved in the following way:

  • The opcode field of the instruction is stored in the control unit (cu in the FSM diagram below)
  • The rest of the instruction bits is stored in a special puropse register called the instruction register.

Next, frog must choose an appropriate course of action for each kind of instructions.

3. Architecture

Let us first draw the CPU without its control unit:

As can be seen from the circuit diagram, at the core of the frog processor is a fish processor. On top of fish, there is a new register, a new multiplexer, and some new connections:

  • In fish, we had a single type of instruction:

MicroCode

Address FETCH IRLD MUX LD PCINC
0x0 1 1 0 0 0
0x1 0 0 0 1 0
0x2 0 0 1 1 1
Adress Data
0x0 0x18
0x1 0x02
0x2 0x07

4. Verilog Design

Realizing Frog will be our first project in Verilog. We will take this opportunity …

4.1 How NOT to write the Frog in Verilog

When realizing a circuit idea in Verilog, students generally follow the following steps:

  1. Draw a schematic of the circuit
  2. Write a Verilog module corresponding to every major block in the schematic
  3. connect all these modules within a top module to generate the circuit they draw.

When applied to frog, this will result in approximately the following:

  1. Draw the schematic of Frog, which is Fig. …
  2. Write modules for register bank, ALU, memory and control unit, etc..
  3. Join all these modules on a top CPU module.

So, the resulting Verilog code will look like:

module cpu()
wire IRLOAD, REGLOAD, PCINC, MUX
wire [15:0] datain;
wire [1:0]  srcr, srcl, regdest;
wire [3:0]  aluop;
reg  [7:0]  pc;
reg  [15:0] ir;
wire [15:0] regbank[7:0];

   memory mem1( .address(pc), .dataout(datain) )

   control_unit ctrl( .PCINC(PCINC), .IRLOAD(IRLOAD), .REGLOAD(REGLOAD) .MUX(MUX), .din(datain[15:14]) )


   alwas @(posedge clk)
        if (PCINC)
           pc <= pc+1;

   alwas @(posedge clk)
        if (IRLOAD)
           ir <= datain;

    assign  aluop = ir[11:8]
    assign  regdest = ir[1:0]
    assign  srcr = ir[4:3]
    assign  srcl = din[7:5]

    alu alu1(.aluinl(regbank[srcl]), .aluinr(regbank[srcr]), .aluop(aluop), .aluout(aluout) )

    always @*
        if (MUX)
            regbankin = datain;
        else
            regbankin = aluout

    registerbank rgb1( .REGLOAD(REGLOAD), .whichregtowrite(regdest), regbank(regbank), .din(regbankin) );
endmodule



module_memory(
output [15:0] dataout,
input [10:0] address
)
 reg [15:0] memory [0:511]; 

 assign dataout = memory[address];

 initial 
     $readmemh("prog.txt", memory);  //must be exactly 512 locations

 endmodule



module alu(
input [15:0] aluinl,
input [15:0] aluinr,
output reg [15:0] aluout,
input [3:0] aluop
)
always @*
    case( aluop )
        4'h0:  aluout = aluinl + aluinr;
        4'h1:  aluout = aluinl - aluinr;
        4'h2:  aluout = aluinl &amp; aluinr;
        4'h3:  aluout = aluinl | aluinr;
        4'h4:  aluout = aluinl ^ aluinr;
        4'h5:  aluout = ~aluinr;
        4'h6:  aluout =  aluinr;
        4'h7:  aluout = aluinr + 16'h0001;
        4'h8:  aluout = aluinr - 16'h0001;
        default: aluout = 0;
    endcase;
endmodule;


module registerbank(
input clk;
input [15:0] din;
input [3:0] whichregtowrite;
input REGLOAD 
output reg [15:0] regbank[7:0];
)
always @(posedge clk)                   
    if (REGLOAD)
        regbank[whichregtowrite] <= din;
endmodule;



module ControlUnit(
output wire IRLOAD, REGLOAD, PCINC, MUX
input [1:0] din;
)
wire FETCH;
reg [4:0] microcodeRom [0:3];
reg [1:0] command; 

always @(posedge clk)
   if (FETCH)
      command <= din; //if I am doing fetch now, one clock later I need the microcode addr of the command.
   else
      command <= 2'b0;

    assign { IRLOAD, REGLOAD, PCINC, MUX, FETCH } = microcodeRom[command];

endmodule

 

This is a very suboptimal way of writing a Verilog code, akin to programming in assembly language. The resulting code will not be necessarily wrong, but it will be very long, inefficient and very hard to debug.

4.2 How to write the Frog in Verilog

A better way of writing verilog is not to start from the schematic, but from the finite state machine which gave rise to that schematic.

module FirstCPU(input wire clk);

reg [1:0] state;
reg [15:0] memory[0:511];
wire[15:0] aluinr, aluinl;
wire[3:0] aluop;
reg [15:0] pc, aluout, ir;
reg [15:0] regbank[0:3];

localparam  FETCH = 2'b00;
localparam  LDI = 2'b01;
localparam  ALU = 2'b10;

    always @(posedge clk)
        case(state)

            FETCH: 
            begin
                state<=memory[pc][15:14];
                ir<=memory[pc][11:0];
                pc<=pc+1;
            end

            LDI:
            begin
                state<=FETCH;
                regbank[ ir[1:0] ] <= memory[pc];
                pc<=pc+1;
            end

            ALU:
            begin
                state<=FETCH;
                regbank[ ir[1:0] ]  <= aluout; 
            end

        endcase

assign aluinl=regbank[ir[7:6]];
assign aluinr=regbank[ir[4:3]];
assign aluop=ir[11:8];
always @*
    case( aluop )
        4'h0:  aluout = aluinl + aluinr;
        4'h1:  aluout = aluinl - aluinr;
        4'h2:  aluout = aluinl &amp; aluinr;
        4'h3:  aluout = aluinl | aluinr;
        4'h4:  aluout = aluinl ^ aluinr;
        4'h5:  aluout = ~aluinr;
        4'h6:  aluout =  aluinr;
        4'h7:  aluout = aluinr + 16'h0001;
        4'h8:  aluout = aluinr - 16'h0001;
        default: aluout = 0;
    endcase

initial begin
  //   $readmemh("prog.txt", memory);  //must be exactly 512 locations
     state = FETCH;
 end

endmodule

 

As can be seen, there is no control unit, no register bank etc in this version of the program. All these low level details are expected to be inferred by the Verilog compiler. In other words, the programmer is only required to express the FSM in Verilog. It is the compiler’s duty to construct the schematic from this FSM. And, as compilers are much better in optimization compared to humans, the resulting circuit is likely be more efficient.

5. Assembler for Frog

Assembler with frog is almost the same with the assembler for Fish. Only the code to assemle the LDI instruction is added.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


//Converts a hexadecimal string to integer.
int hex2int( char* hex)  
{
    int result=0;

    while ((*hex)!='\0')
    {
        if (('0'<=(*hex))&&((*hex)<='9'))
            result = result*16 + (*hex) -'0';
        else if (('a'<=(*hex))&&((*hex)<='f'))
            result = result*16 + (*hex) -'a'+10;
        else if (('A'<=(*hex))&&((*hex)<='F'))
            result = result*16 + (*hex) -'A'+10; 
        hex++;
    }
    return(result);
}

main()
{     
    FILE *fp;
    char line[100];
    char *token = NULL;
    char *op1, *op2, *op3;
    char ch;
    int  chch;

    int program[1000];
    int counter=0;  //holds the address of the machine code instruction


    fp = fopen("name_of_program","r");

    while(fgets(line,sizeof line,fp)!= NULL)
    {
            token=strtok(line,"\n\t\r ");  //get the instruction mnemonic or labe

            if (strcmp(token,"ldi")==0)        //---------------LDI INSTRUCTION--------------------
            {
                    op1 = strtok(NULL,"\n\t\r ");                                //get the 1st operand of ldi, which is the register that ldi loads
                    op2 = strtok(NULL,"\n\t\r ");                                //get the 2nd operand of ldi, which is the data that is to be loaded
                    program[counter]=0x1000+hex2int(op1);                        //generate the first 16-bit of the ldi instruction
                    counter++;                                                   //move to the second 16-bit of the ldi instruction
                    if ((op2[0]=='0')&&(op2[1]=='x'))                            //if the 2nd operand is twos complement hexadecimal
                        program[counter]=hex2int(op2+2)&0xffff;              //convert it to integer and form the second 16-bit 
                    else if ((  (op2[0])=='-') || ((op2[0]>='0')&&(op2[0]<='9')))       //if the 2nd operand is decimal 
                        program[counter]=atoi(op2)&0xffff;                         //convert it to integer and form the second 16-bit 
                    else                                                           //if the second operand is not decimal or hexadecimal, it is a laber or a variable.
                    {                                                               //in this case, the 2nd 16-bits of the ldi instruction cannot be generated.
                        printf("unrecognizable LDI offset\n");
                    }        
                    counter++;                                                     //skip to the next memory location 
            }                                       
            else if (strcmp(token,"add")==0) //----------------- ADD -------------------------------
            {
                    op1 = strtok(NULL,"\n\t\r ");    
                    op2 = strtok(NULL,"\n\t\r ");
                    op3 = strtok(NULL,"\n\t\r ");
                    chch = (op1[0]-48)| ((op2[0]-48)<<3)|((op3[0]-48)<<6);  
                    program[counter]=0x7000+((chch)&0x00ff); 
                    counter++; 
            }
            else if (strcmp(token,"sub")==0)
            {
                    //to be added
            }
            else if (strcmp(token,"and")==0)
            {
                    //to be added
            }
            else if (strcmp(token,"or")==0)
            {
                    //to be added
            }
            else if (strcmp(token,"xor")==0)
            {
                    //to be added
            }                        
            else if (strcmp(token,"not")==0)
            {
                    op1 = strtok(NULL,"\n\t\r ");
                    op2 = strtok(NULL,"\n\t\r ");
                    ch = (op1[0]-48)| ((op2[0]-48)<<3);
                    program[counter]=0x7500+((ch)&0x00ff);  
                    counter++;
            }
            else if (strcmp(token,"mov")==0)
            {
                    //to be added
            }
            else if (strcmp(token,"inc")==0)
            {
                    op1 = strtok(NULL,"\n\t\r ");
                    ch = (op1[0]-48)| ((op1[0]-48)<<3);
                    program[counter]=0x7700+((ch)&0x00ff);  
                    counter++;
            }
            else if (strcmp(token,"dec")==0)
            {
                                      //to be added
            }
            else //------WHAT IS ENCOUNTERED IS NOT A VALID INSTRUCTION OPCODE
            {
                     printf("no valid opcode\n");
            } 
     } //while

     fclose(fp);
     fp = fopen("RAM","w");
     fprintf(fp,"v2.0 raw\n");  //needed for logisim, remove this line for verilog..
     for (i=0;i<counter+dataarea;i++)  //complete this for memory size in verilog
            fprintf(fp,"%04x\n",program[i]);
} //main

 

6. Key Concepts

  • LDI instruction
  • Opcode field
  • Instruction register
  • Control unit

7. Problems

  1. Add an instruction which performs immediate ALU operations. With this instruction, do we still need the LDI instruction?
  2. In verilog, connect the output of register 0 to a 7-segment display.
  3. This is an extension of Problem 2. Add two DIP-switches to your design. The 7-segment display will show the output of any register depending on the switch configuration.
]]>
/frog-a-calculator-that-can-load-data-into-registers/feed/ 0
Reptile-4: The Hardware Design /reptile-the-hardware-design/ /reptile-the-hardware-design/#respond Sun, 19 Apr 2020 15:37:32 +0000 /?p=253 Reptile FSM

 

Reptile Hardware

Reptile memory connection

Reptile FSM with Control Signals

Reptile Control Unit

We must have as many lines as the number of “balls” plus one line for JZ.

Each line contains as many bits as control signals plus one bit for Fetch.

The complete circuit for the control unit of Reptile is shown below. As can be seen, it is almost identical with the control unit of Frog. The only difference is the part drawn in red in the diagram below, which handles the conditional jumps, ie, the JZ instructions.

Microcode

Reptile in Verilog

module reptile (
					input clk,
					input [15:0] data_in,
					output reg [15:0] data_out,
					output reg [11:0] address,
					output wire memwt
					);
 
    reg [11:0] pc, ir; //program counter, instruction register
 
    reg [3:0]  state; //FSM
	 reg [15:0] regbank [3:0];//registers 
    reg zeroflag; //zero flag register
	 reg [15:0] result; //output for result
 
 
     localparam   FETCH=4'b0000,
                  LDI=4'b0001, 
                  LD=4'b0010,
                  ST=4'b0011,
                  JZ=4'b0100,
                  JMP=4'b0101,
                  ALU=4'b0111;
 
	 
    wire zeroresult; //zeroflag value 
 
    always @(posedge clk)
        case(state)
 
            FETCH: 
            begin
                if ( data_in[15:12]==JZ) // if instruction is jz  
                    if (zeroflag)  //and if last bit of 7th register is 0 then jump to jump instruction state
                        state <= JMP;
                    else
                        state <= FETCH; //stay here to catch next instruction
                else
                    state <= data_in[15:12]; //read instruction opcode and jump the state of the instruction to be read
                ir<=data_in[11:0]; //read instruction details into instruction register
                pc<=pc+1; //increment program counter
            end
 
            LDI:
            begin
                regbank[ ir[1:0] ] <= data_in; //if inst is LDI get the destination register number from ir and move the data in it.
                pc<=pc+1; //for next instruction (32 bit instruction)  
                state <= FETCH;
            end
 
             LD:
                begin
                    regbank[ ir[1:0] ] <= data_in;
                    state <= FETCH;  
                end 
 
            ST:
                begin
                    data_out <= regbank[ ir[7:6] ];
                    state <= FETCH;  
                end    
 
            JMP:
                begin
                    pc <= pc+ir;
                    state <= FETCH;  
                end          
 
            ALU:
                begin
                    regbank[ir[2:0]]<=result;
                    zeroflag<=zeroresult;
                    state <= FETCH;
                end
 
        endcase
 
 
    always @*   
        case (state)
            LD:      address=regbank[ir[4:3]][11:0];
            ST:      address=regbank[ir[4:3]][11:0];
            default: address=pc;
         endcase
 
    assign memwt=(state==ST);
 //ALU
    always @*
        case (ir[11:8])
            4'h0: result = regbank[ir[7:6]]+regbank[ir[4:3]]; //000
            4'h1: result = regbank[ir[7:6]]-regbank[ir[4:3]]; //001
            4'h2: result = regbank[ir[7:6]]&regbank[ir[4:3]]; //010
            4'h3: result = regbank[ir[7:6]]|regbank[ir[4:3]]; //011
            4'h4: result = regbank[ir[7:6]]^regbank[ir[4:3]]; //100
            3'h5: result = !regbank[ir[4:3]];
            3'h6: result = regbank[ir[4:3]];
            3'h7: result = regbank[ir[4:3]]+1'h1;
            3'h8: result = regbank[ir[4:3]]-1'h1;
            default: result=16'h0000;
        endcase
 
    assign zeroresult = ~|result;
 
 
    initial begin;
            state=FETCH;
            end                        
endmodule

 

 

Problems

  1. Add an overflow flag into hardware. How you should change the instruction set to take advantage of this new flag?
  2. Add address offset to load and store instructions.
  3. Create conditional jump instructions for many different conditions, ie, not only JZ but JNZ, JEQ, JGT etc.
  4. Increase memory size to 64K while keeping the data size 16 bits. Which instructions will change?
  5. Add a monitor which shows the address and PC at each instruction.
]]>
/reptile-the-hardware-design/feed/ 0