ECEN 449 749: Microprocessor System Design Department of Electrical and Computer Engineering Texas A&M University Homework #2 Solutions Upload your homework solution to ecampus as a single file. Your homework solution should include a listing of any C code or Verilog code, along with any output obtained when the code is run. DO NOT upload a zip file. You will have only ONE attempt to upload your homework solution. In addition, your source code (any C code or Verilog code or testbenches) should be sent via email to 449and749graders@gmail.com. Your email title should state your NAME, SECTION NUMBER and HOMEWORK NUMBER. Name your files in a way that identifies the homework number and the question (e.g. hw1-q1b.v). For all the code that you write, please provide comments for full credit. 1. A and B are two dimensional matrices. Write a C program to add the transpose of matrix A and transpose of matrix B. For both A and B, the size of the matrix will be given along with the entries of the matrix in two input files, ina.txt and inb.txt. The first line of the input file will contain the number of rows followed by the number of columns of the matrix. The entries of the matrix are listed on the next line in row-major order. Print the output matrix C to outc.txt in the same format as input files. Provide comments in your code. Example: If your matrix A is [ ] 1 2 3 4 5 6 then ina.txt would be: 2 3 1 2 3 4 5 6 Run your program on the following pairs of matrices: (a) A = [ ] 1.1 2.53, B = 2.1 3.3 [ 4.5 ] 5.67 3.73 0 1
2 Solutions to Homework #2 (b) A = [ ] 1 1 0, B = 2 1 1 [ 2 1 ] 1 1 2 1 Solution. #include<stdio.h> #include<stdlib.h> #include<string.h> int main() { //declaration of variables FILE* fp1; FILE* fp2; FILE *file_ptr_out; int array1_rows, array1_columns, array2_rows, array2_columns; int i = 0, j = 0, loop = 0; float array1[100][100], array2[100][100]; //open input file in read mode fp1 = fopen("ina.txt", "r"); //read from file while (fscanf(fp1, "%f", array1[i])!= EOF) { i++; //open second input file in read mode fp2 = fopen("inb.txt", "r"); while (fscanf(fp2, "%f", array2[j])!= EOF) { j++; //store values of array1 and array row and column dimension array1_rows = array1[0][0]; array2_rows = array2[0][0]; array1_columns = array1[1][0];
3 Solutions to Homework #2 array2_columns = array2[1][0]; //Dynamic memory allocation //create an array of pointers dynamically using a double pointer. //input matrix 1 float **matrix1 = (float**)malloc(array1_rows*array1_columns * sizeof(float*)); //transpose of matrix 1 float **transpose_matrix1 = (float**)malloc(array1_rows*array1_columns * sizeof(float*)); //input matrix 2 float **matrix2 = (float**)malloc(array2_rows*array2_columns * sizeof(float*)); //transpose of matrix 2 float **transpose_matrix2 = (float**)malloc(array2_rows*array2_columns * sizeof(float*)); //output sum matrix of the two transpose matrix float **sum_matrix = (float**)malloc(array2_rows*array2_columns * sizeof(float*)); for (i = 0; i < array1_columns; i++) { matrix1[i] = (float*)malloc(array1_columns * sizeof(float)); for (i = 0; i < array1_columns; i++) { transpose_matrix1[i] = (float*)malloc(array1_columns * sizeof(float)); for (i = 0; i < array2_columns; i++) { transpose_matrix2[i] = (float*)malloc(array2_columns * sizeof(float)); for (i = 0; i < array1_columns; i++) { sum_matrix[i] = (float*)malloc(array1_columns * sizeof(int)); for (i = 0; i < array2_columns; i++) { matrix2[i] = (float*)malloc(array2_columns * sizeof(float)); //Assigning values to matrix1 from data read from input file ina.txt for (i = 0; i < array1_rows; i++) { for (j = 0; j < array1_columns; j++) {
4 Solutions to Homework #2 matrix1[i][j] = array1[loop + 2][0]; loop++; loop = 0; //Assigning values to matrix2 from data read from input file inb.txt for (i = 0; i < array2_rows; i++) { for (j = 0; j < array2_columns; j++) { matrix2[i][j] = array2[loop + 2][0]; loop++; //Taking transpose of matrix1 and placing output in transpose_matrix1 for (i = 0; i < array1_rows; i++){ for (j = 0; j < array1_columns; j++) { transpose_matrix1[j][i] = matrix1[i][j]; //Taking transpose of matrix2 and placing output in transpose_matrix2 for (i = 0; i < array2_rows; i++) { for (j = 0; j < array2_columns; j++) { transpose_matrix2[j][i] = matrix2[i][j]; //output file OUT.txt in write mode file_ptr_out = fopen("outc.txt", "w"); // fprintf writes onto the corresponding output file fprintf(file_ptr_out, "%d %d\n", array2_columns, array2_rows ); //Calculating the sum of transpose_matrix1 and transpose_matrix2 for (i = 0; i < array1_columns; i++) { for (j = 0; j < array1_rows; j++) {
5 Solutions to Homework #2 sum_matrix[i][j] = ((transpose_matrix1[i][j]) + (transpose_matrix2[i][j])); fprintf(file_ptr_out, "%f ", sum_matrix[i][j]); //free dynamically allocated memory free(matrix1); free(matrix2); free(transpose_matrix1); free(transpose_matrix2); free(sum_matrix); //close input and output file pointers fclose(fp1); fclose(fp2); fclose(file_ptr_out); return 0; 2. Construct a Verilog module for a parity generator. It has an 8 bit wide input IN. The output OUT is 1 for even parity else 0. Simulate your parity checker module using a testbench, for the following inputs: (a) 10101010 (b) 11111111 (c) 10000010 Solution. timescale 1ns/1ps module paritygenerator(out, IN); input [7:0] IN; output OUT; ///XORing all the bits of IN gives 1 for odd number of 1 s at the input. //By adding a NOT to that statement meets the requirements of the question. assign OUT = ˆIN[7:0];
6 Solutions to Homework #2 module timescale 1ns/1ps module paritygenerator_tb(); //Output wire OUT; // Input reg [7:0]IN; // Instantiation of parity generator module. paritygenerator DUT(.OUT(OUT),.IN(IN)); initial //Set inputs. IN = 8 b10101010; #20; IN = 8 b11111111; #20; IN = 8 b10000010; #20; $finish; module 3. Consider an input clock IN CLK. Also consider an signal IN DAT which is 4 bit wide, arriving at every positive edge of IN CLK. Write Verilog code to generate the following: Output clock OUT CLK and signal OUT DAT which is of 8 bits wide, as shown in the figure below. The OUT DAT signal packs the last 2 values of IN DAT that the system encounters. Test your code for 16 clock cycles, with the input IN DAT = 0000 for first clock cycle, 0001 for the second clock cycle, and so on.
7 Solutions to Homework #2 IN_CLK IN_DAT 0000 0001 0010 0011 0100 OUT_CLK OUT_DAT XXXXXXXX 00000001 00100011 Waveform for Question 3 Solution. //Verilog Code module packer(out_dat,out_clk,in_dat,in_clk,rst); output [7:0] OUT_DAT; output OUT_CLK; input [3:0] IN_DAT; input IN_CLK; input RST; reg [7:0] OUT_DAT; reg OUT_CLK; reg [7:0] tmp_dat; //generate OUT_CLK always @(posedge IN_CLK or negedge RST) if(rst == 0) OUT_CLK <= 0; else
8 Solutions to Homework #2 OUT_CLK <= OUT_CLK; //generate tmp_dat which packs the data at rising edge of IN_CLK always @(negedge IN_CLK or negedge RST) if(rst == 0) tmp_dat <= 0; else if(out_clk == 1) tmp_dat <= else tmp_dat[3:0] <= IN_DAT; {IN_DAT,4 b0000; //latch tmp_dat at posedge of OUT_CLK always @(posedge OUT_CLK or negedge RST) if(rst == 0) OUT_DAT <= 0; else OUT_DAT <= tmp_dat;
9 Solutions to Homework #2 module //Testbench module testbench(); reg [3:0] IN_DAT; reg IN_CLK, RST; wire[7:0] OUT_DAT; wire OUT_CLK; packer U0(.OUT_DAT (OUT_DAT),.OUT_CLK (OUT_CLK),.IN_DAT (IN_DAT),.IN_CLK (IN_CLK),.RST (RST) ); initial IN_CLK = 0; //IN_clk of 20MHz always #25 IN_CLK =! IN_CLK; //active low RESET initial RST = 0; #50 RST = 1; //generate IN_DAT from 4 b0000 to 4 b1111 initial IN_DAT <= 4 b0000; #75 IN_DAT <= 4 b0000; #50 IN_DAT <= 4 b0001;
10 Solutions to Homework #2 #50 IN_DAT <= 4 b0010; #50 IN_DAT <= 4 b0011; #50 IN_DAT <= 4 b0100; #50 IN_DAT <= 4 b0101; #50 IN_DAT <= 4 b0110; #50 IN_DAT <= 4 b0111; #50 IN_DAT <= 4 b1000; #50 IN_DAT <= 4 b1001; #50 IN_DAT <= 4 b1010; #50 IN_DAT <= 4 b1011; #50 IN_DAT <= 4 b1100; #50 IN_DAT <= 4 b1101; #50 IN_DAT <= 4 b1110; #50 IN_DAT <= 4 b1111; module 4. Read the manual pages on the open() and mmap() function calls. You can either use man open or use the web to find information about these function calls. mmap() allows you to map the file contents to memory address space and then you can write to the memory addresses to write to the file and similarly reading from memory causes data to be read from the file. Write a program using open() and mmap() to create a file containing the string Hello hola how are you. Your program should write to file by writing to memory. Provide comments in your code. Solution. #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include <sys/mman.h> #include <string.h> #define FILEPATH "output.bin" //output file name #define NUMBEROFINTS (100) //Number of integers to print to file //size of file created based on NUMBEROFINTS
11 Solutions to Homework #2 int main(int argc, char *argv[]) { const char *text = "Hello hola how are you"; size_t textlen = strlen(text); int fp; int result; //used for error checking char *map; //array of ints using mmap() //open file fp= open (FILEPATH,O_RDWR O_CREAT,(mode_t)0600); if (fp == -1) { perror("error opening file for writing"); exit(exit_failure); //resize file to correct length for number ints result=lseek(fp, textlen-1, SEEK_SET); if (result == -1) { //error check close(fp); printf("error in resizing file \n"); exit(1); result = write(fp,"", 1); //write an empty string to file if (result!= 1) { //error check close(fp); printf("error in writing last byte of the file \n"); exit(1); //map file map = mmap(0, textlen, PROT_READ PROT_WRITE, MAP_SHARED, fp, 0); if (map == MAP_FAILED){ //error check close(fp); printf("error in mapping the file \n"); exit(1); //write data to file/mapped array
12 Solutions to Homework #2 for (size_t i = 0; i<textlen; i++) { map[i] = text[i]; printf("writing character %c at %zu\n", text[i],i); //unmap the file if (munmap(map, textlen) == -1) { //error check close(fp); printf("error in un-mmapping the file \n"); exit(1); close(fp); //close file return 0; 5. [GRADUATE QUESTION] Write Verilog code to implement a LIFO (Last-In-First-Out) buffer as shown in the figure below. The LIFO buffer can store upto 8 Bytes. The input clock signal is called CLK. The R/W line is used to select between LIFO Read and LIFO Write. When R/W is high, the LIFO performs a read and when R/W is low, the LIFO performs a write. The output FULL line becomes high when the LIFO buffer is or becomes FULL. Similarly, the EMPTY line becomes high when the LIFO buffer is or becomes EMPTY. The signal RST resets the LIFO. Test your code for 16 clock cycles, with DATAIN = 00000000 for the first clock cycle, 00000001 for the second clock cycle and so on upto 8 clock cycles. The data is written into LIFO for the first 8 clock cycles. Then perform a Read (R/W = high) for the next 8 clock cycles. Plot waveforms of all the inputs and outputs. DATAIN [7:0] CLK RST R / W LIFO BUFFER DATAOUT[7:0] EMPTY FULL Figure for Question 5
13 Solutions to Homework #2 Solution. //Verilog Code module lifo(dataout,empty,full,datain,clk,rst,r_wb); output [7:0] DATAOUT; output EMPTY,FULL; input [7:0] DATAIN; input CLK, RST, R_Wb; reg [7:0] DATAOUT; reg EMPTY, FULL; reg [7:0] lifo_buff [7:0]; //LIFO buffer reg [3:0] ctr; //counter which keeps track of buffer fullness integer i; //if R_Wb is LOW and FULL = 0, input data is written into the buffer and if R_Wb is HIGH and EMPTY = 0 data is read from the buffer always @(posedge CLK or negedge RST) if(rst == 0) for(i=0;i<8;i=i+1) lifo_buff[i] <= 0; ctr <= 4 b0000; else if(r_wb == 0 && FULL == 0) //write to buffer if (ctr < 8) ctr <= ctr + 1; //increment counter since the buffer is empty lifo_buff[ctr-1] <= DATAIN; else if(r_wb == 1 && EMPTY == 0) //read from buffer if(ctr > 0) ctr <= ctr - 1;
14 Solutions to Homework #2 DATAOUT <= lifo_buff[ctr-1] ; //EMPTY FLAG = 1 when ctr = 0 and FULL FLAG = 1 when ctr = 7 always @(posedge CLK or negedge RST) if(rst == 0) EMPTY <= 0; else if (ctr == 0) EMPTY <= 1; else EMPTY <= 0; always @(posedge CLK or negedge RST) if(rst == 0) FULL <= 0; else if (ctr == 8) FULL <= 1; else
15 Solutions to Homework #2 FULL <= 0; module //Testbench module testbench(); reg [7:0] DATAIN; reg CLK, RST, R_Wb; wire[7:0] DATAOUT; wire EMPTY,FULL; lifo U0(.DATAOUT (DATAOUT),.EMPTY (EMPTY),.FULL (FULL),.DATAIN (DATAIN),.CLK(CLK),.RST (RST),.R_Wb(R_Wb) ); initial CLK = 0; //IN_clk of 20MHz always #25 CLK =! CLK; //active low RESET initial RST = 0; #50 RST = 1;
16 Solutions to Homework #2 //generate DATAIN from 8 b00000000 to 4 b00000111 initial DATAIN <= 8 b00000000; R_Wb <= 0; #75 DATAIN <= 8 b00000000; R_Wb <= 0; #50 DATAIN <= 8 b00000001; R_Wb <= 0; #50 DATAIN <= 8 b00000010; R_Wb <= 0; #50 DATAIN <= 8 b00000011; R_Wb <= 0; #50 DATAIN <= 8 b00000100; R_Wb <= 0; #50 DATAIN <= 8 b00000101; R_Wb <= 0; #50 DATAIN <= 8 b00000110; R_Wb <= 0; #50 DATAIN <= 8 b00000111; R_Wb <= 0; #50 R_Wb <= 1; module