// // SoC P35 Exercise 1 2011/12 // /* 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 do $ 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 // It 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 ones 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 this is appropriate. `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 [31: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