// // SoC P35 Exercise 1 2012/13 // /* The modelsim simulator is not needed for this exercise but you may want to run it as follows. Note also, you can run SystemC under modelsim and even do a hybrid RTL/SystemC. However, this is only for the really keen! For modelsim the following may work (let me know if not) $ source /usr/groups/ecad/setup.bash OR use a makefile containing the following lines: PATH := $(PATH):/usr/groups/ecad/mentor/modelsim/current/modeltech/bin export MGLS_LICENSE_FILE=1717@lmserv-mentor.cl.cam.ac.uk modelsim: rm -rf simple_lib; vlib simple_lib echo "run -all;exit" > run.do vmap simple_lib simple_lib vlog -work simple_lib socex1.v vsim -c simple_lib.socex1 -do "run.do" */ // Please do the following three things and any of the options. // // 1. Look at the following verilog module called PERIPHERAL_DEVICE and understand it. // 2. // Convert the PERIPHERAL_DEVICE to a SystemC net-level model that has exactly the same behaviour and // signature. The signature is the nets that are inputs and outputs. So the SystemC model should contain, // for instance 'sc_in < sc_uint<5> addr; ' Please increase the number of comments. Your model must // compile without syntax error for full credit. The internal variables in your model can be sc_signals // or plain C++ variables, according to the coding style you choose. // // 3. Answer the questions in the question list to form your report. // // 4. Optionally include waveform plots showing the Verilog or SystemC behaviour or both (they should be the same). // // 5. Optionally sketch some application code in C that can run on a processor where peripheral_device has been // connected as a peripheral. (We will be doing more of this sort of thing throughout the course). // // Notes // - You may ignore the testbench part of this example or you may also convert it, but certainly keep it separate and external. // // - The pattern to be detected is hardwired in this implementation for simplicity but, in general, might be programmed by the host. // // - You may find the SoC Parts slide pack helpful in understanding the meaning of this code and answering the questions. // Key points will be lectured shortly so finish your answers after that lecture. // // - We will later consider a TLM-style implementation of this same peripheral. // // // Questions: please feel free to discuss these with each other and DJ Greaves. Please answer in a few sentences each. // 1. Describe what this unit does, giving its programming model. // 2. You had the choice of using sc_signals or simple variables for the internal state of your model. Describe what difference // this has made to your coding style (see the slides regarding signals and variables in pack 1). // 3. If the number of WRDS stored in the peripheral were very large, a RAM might typically be used instead of a number of flip-flops // forming a register file. Would this cause a structural hazard? How would the performance of the unit be affected? // 4. Write a few notes on the motivation to provide custom hardware for bit-oriented kernels, such as this simple example, as // opposed to implementing them in software on the main host processor. // 5. Say whether the testbench is synthesisable and why so or not. `define WRDS 4 `define PD_DATA_REG 0 `define PD_PTR_REG 8 `define PD_CR_REG 16 `define PD_ST_REG 24 module socex1(); reg clk, reset; reg [4:0] addr; // Internal address selection within a target, reg hwen ; // Asserted during a target write, reg hren ; // Asserted during a target read, reg [63:0] wdata; // Input data to a target when written, wire [63:0] rdata; // Output data when target is read, wire interrupt; // Asserted by target when wanting attention. PERIPHERAL_DEVICE device_under_test(clk, reset, addr, hwen, hren, wdata, rdata, interrupt); initial begin // This is the testbench - this may be ignored if you wish. clk = 0; reset = 0; addr = 0; hwen = 0; hren = 0; wdata = 0; clk = 0; #10 clk = 1; #10 clk = 0; #10 hwen = 1; addr=`PD_PTR_REG; wdata=0; #10 clk = 1; #10 clk = 0; hwen = 0; #10 hwen = 1; addr=`PD_DATA_REG; wdata=12345678; // 1st #10 clk = 1; #10 clk = 0; #10 hwen = 1; addr=`PD_PTR_REG; wdata=1; #10 clk = 1; #10 clk = 0; hwen = 0; #10 hwen = 1; addr=`PD_DATA_REG; wdata=12345678; // 3rd #10 clk = 1; #10 clk = 0; #10 hwen = 1; addr=`PD_PTR_REG; wdata=2; #10 clk = 1; #10 clk = 0; hwen = 0; #10 hwen = 1; addr=`PD_DATA_REG; wdata=12345678; // 3rd #10 clk = 1; #10 clk = 0; #10 hwen = 1; addr=`PD_PTR_REG; wdata=3; #10 clk = 1; #10 clk = 0; hwen = 0; #10 hwen = 1; addr=`PD_DATA_REG; wdata=12345678; // 4th #10 clk = 1; #10 clk = 0; #10 hwen = 1; addr=`PD_CR_REG; wdata=(1<<8); #10 clk = 1; #10 clk = 0; hwen = 0; #10 #10 clk = 1; #10 clk = 0; #10 #10 clk = 1; #10 clk = 0; #10 #10 clk = 1; #10 clk = 0; #10 #10 clk = 1; #10 clk = 0; #10 #10 clk = 1; #10 clk = 0; #10 #10 clk = 1; #10 clk = 0; #10 #10 clk = 1; #10 clk = 0; #10 #10 clk = 1; #10 clk = 0; #10 #10 clk = 1; #10 clk = 0; #10 #10 clk = 1; #10 clk = 0; #10 #10 clk = 1; #10 clk = 0; #10 #10 clk = 1; #10 clk = 0; #10 $display("Testbench finished\n"); end endmodule // socex1 module PERIPHERAL_DEVICE(clk, reset, addr, hwen, hren, wdata, rdata, interrupt); input clk, reset; input [4:0] addr; // Internal address selection within a target, input hwen ; // Asserted during a target write, input hren ; // Asserted during a target read, input [63:0] wdata; // Input data to a target when written, output [63:0] rdata; // Output data when target is read, output interrupt; // Asserted by target when wanting attention. reg [7:0] ptr_reg; reg [7:0] ctr_reg; reg [63:0] codewords [0:`WRDS-1]; reg running; reg int_enable; integer i; wire matched = (codewords[0] >> 4) & (codewords[0] >> 14) & (codewords[0] >> 44) & (codewords[1] >> 14) & (codewords[1] >> 24) & (codewords[1] >> 54) & (codewords[2] >> 4) & (codewords[3] >> 34); always @(posedge clk) begin if (hwen && addr==`PD_PTR_REG) ptr_reg <= wdata; if (hwen && addr==`PD_DATA_REG) codewords[ptr_reg] <= wdata; if (hwen && addr==`PD_CR_REG) { int_enable, running, ctr_reg } <= wdata; if (matched) running <= 0; if (running) begin codewords[`WRDS-1] <= -1; for (i =0 ;i<`WRDS-1; i=i+1) codewords[i] = (codewords[i]) | (codewords[i+1] >> 4); end $display("%m %h %h %h %h ptr=%h running=%d matched=%d\n", codewords[3], codewords[2], codewords[1], codewords[0], ptr_reg, running, matched); end assign interrupt = int_enable && !running; assign rdata = (addr==`PD_PTR_REG) ? ptr_reg: (addr==`PD_DATA_REG) ? codewords[ptr_reg]: (addr==`PD_CR_REG) ? { 54'b0, int_enable, running, ctr_reg }: (addr==`PD_ST_REG) ? { 53'b0, matched, int_enable, running, ctr_reg }: 64'hDEADBEEF; endmodule // PERIPHERAL_DEVICE /* Example output: device_under_test. 0x00 0x00 0x00 0x00 ptr=0x0 running=x matched=0 device_under_test. 0x00 0x00 0x00 0xBC614E ptr=0x0 running=x matched=0 device_under_test. 0x00 0x00 0x00 0xBC614E ptr=0x1 running=x matched=0 device_under_test. 0x00 0x00 0xBC614E 0xBC614E ptr=0x1 running=x matched=0 device_under_test. 0x00 0x00 0xBC614E 0xBC614E ptr=0x2 running=x matched=0 device_under_test. 0x00 0xBC614E 0xBC614E 0xBC614E ptr=0x2 running=x matched=0 device_under_test. 0x00 0xBC614E 0xBC614E 0xBC614E ptr=0x3 running=x matched=0 device_under_test. 0xBC614E 0xBC614E 0xBC614E 0xBC614E ptr=0x3 running=x matched=0 device_under_test. 0xBC614E 0xBFE75E 0xBFE75E 0xBFE75E ptr=0x3 running=1 matched=0 device_under_test. 0xFFFFFFFF 0xFFFFFFFF 0xBFFF7F 0xBFFF7F ptr=0x3 running=1 matched=0 device_under_test. 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xBFFFFF ptr=0x3 running=1 matched=0 device_under_test. 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF ptr=0x3 running=1 matched=0 device_under_test. 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF ptr=0x3 running=1 matched=1 device_under_test. 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF ptr=0x3 running=0 matched=1 */ // eof -------------------------------------------------------- Additional Notes Definition: Programmer's/architectural view/model: the visible registers that can be manipulated by the program on the host, not including any extra temporary registers used in a particular implementation. Both Verilog and C++ accept keywords like 'signed' and 'unsigned' in variable declarations to alter the behaviour of the sign bit under shifting. But they default differently. The actual behaviour of this device is not of as much interest as the structure. The main thing is to get some sort of output under SystemC and to make sure you can answer the questions. Simultaneous read and write to a single-port RAM typically is not a structural hazard if the address is the same. Clearly this depends on the RAM details. The old value is read out and the new inserted. A 'kernel' in the context of the question is the inner loop of an algorithm. --- END